123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637 |
- // P_enemy.c
- #include "DoomDef.h"
- #include "P_local.h"
- #include "soundst.h"
- // Macros
- #define MAX_BOSS_SPOTS 8
- // Types
- typedef struct
- {
- fixed_t x;
- fixed_t y;
- angle_t angle;
- } BossSpot_t;
- // Private Data
- static int BossSpotCount;
- static BossSpot_t BossSpots[MAX_BOSS_SPOTS];
- //----------------------------------------------------------------------------
- //
- // PROC P_InitMonsters
- //
- // Called at level load.
- //
- //----------------------------------------------------------------------------
- void P_InitMonsters(void)
- {
- BossSpotCount = 0;
- }
- //----------------------------------------------------------------------------
- //
- // PROC P_AddBossSpot
- //
- //----------------------------------------------------------------------------
- void P_AddBossSpot(fixed_t x, fixed_t y, angle_t angle)
- {
- if(BossSpotCount == MAX_BOSS_SPOTS)
- {
- I_Error("Too many boss spots.");
- }
- BossSpots[BossSpotCount].x = x;
- BossSpots[BossSpotCount].y = y;
- BossSpots[BossSpotCount].angle = angle;
- BossSpotCount++;
- }
- //----------------------------------------------------------------------------
- //
- // PROC P_RecursiveSound
- //
- //----------------------------------------------------------------------------
- mobj_t *soundtarget;
- void P_RecursiveSound(sector_t *sec, int soundblocks)
- {
- int i;
- line_t *check;
- sector_t *other;
- // Wake up all monsters in this sector
- if(sec->validcount == validcount && sec->soundtraversed <= soundblocks+1)
- { // Already flooded
- return;
- }
- sec->validcount = validcount;
- sec->soundtraversed = soundblocks+1;
- sec->soundtarget = soundtarget;
- for(i = 0; i < sec->linecount; i++)
- {
- check = sec->lines[i];
- if(!(check->flags&ML_TWOSIDED))
- {
- continue;
- }
- P_LineOpening(check);
- if(openrange <= 0)
- { // Closed door
- continue;
- }
- if(sides[check->sidenum[0]].sector == sec)
- {
- other = sides[check->sidenum[1]].sector;
- }
- else
- {
- other = sides[check->sidenum[0]].sector;
- }
- if(check->flags&ML_SOUNDBLOCK)
- {
- if(!soundblocks)
- {
- P_RecursiveSound(other, 1);
- }
- }
- else
- {
- P_RecursiveSound(other, soundblocks);
- }
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC P_NoiseAlert
- //
- // If a monster yells at a player, it will alert other monsters to the
- // player.
- //
- //----------------------------------------------------------------------------
- void P_NoiseAlert(mobj_t *target, mobj_t *emmiter)
- {
- soundtarget = target;
- validcount++;
- P_RecursiveSound(emmiter->subsector->sector, 0);
- }
- //----------------------------------------------------------------------------
- //
- // FUNC P_CheckMeleeRange
- //
- //----------------------------------------------------------------------------
- boolean P_CheckMeleeRange(mobj_t *actor)
- {
- mobj_t *mo;
- fixed_t dist;
- if(!actor->target)
- {
- return(false);
- }
- mo = actor->target;
- dist = P_AproxDistance(mo->x-actor->x, mo->y-actor->y);
- if(dist >= MELEERANGE)
- {
- return(false);
- }
- if(!P_CheckSight(actor, mo))
- {
- return(false);
- }
- if(mo->z > actor->z+actor->height)
- { // Target is higher than the attacker
- return(false);
- }
- else if(actor->z > mo->z+mo->height)
- { // Attacker is higher
- return(false);
- }
- return(true);
- }
- //----------------------------------------------------------------------------
- //
- // FUNC P_CheckMissileRange
- //
- //----------------------------------------------------------------------------
- boolean P_CheckMissileRange(mobj_t *actor)
- {
- fixed_t dist;
- if(!P_CheckSight(actor, actor->target))
- {
- return(false);
- }
- if(actor->flags&MF_JUSTHIT)
- { // The target just hit the enemy, so fight back!
- actor->flags &= ~MF_JUSTHIT;
- return(true);
- }
- if(actor->reactiontime)
- { // Don't attack yet
- return(false);
- }
- dist = (P_AproxDistance(actor->x-actor->target->x,
- actor->y-actor->target->y)>>FRACBITS)-64;
- if(!actor->info->meleestate)
- { // No melee attack, so fire more frequently
- dist -= 128;
- }
- if(actor->type == MT_IMP)
- { // Imp's fly attack from far away
- dist >>= 1;
- }
- if(dist > 200)
- {
- dist = 200;
- }
- if(P_Random() < dist)
- {
- return(false);
- }
- return(true);
- }
- /*
- ================
- =
- = P_Move
- =
- = Move in the current direction
- = returns false if the move is blocked
- ================
- */
- fixed_t xspeed[8] = {FRACUNIT,47000,0,-47000,-FRACUNIT,-47000,0,47000};
- fixed_t yspeed[8] = {0,47000,FRACUNIT,47000,0,-47000,-FRACUNIT,-47000};
- #define MAXSPECIALCROSS 8
- extern line_t *spechit[MAXSPECIALCROSS];
- extern int numspechit;
- boolean P_Move(mobj_t *actor)
- {
- fixed_t tryx, tryy;
- line_t *ld;
- boolean good;
- if(actor->movedir == DI_NODIR)
- {
- return(false);
- }
- tryx = actor->x+actor->info->speed*xspeed[actor->movedir];
- tryy = actor->y+actor->info->speed*yspeed[actor->movedir];
- if(!P_TryMove(actor, tryx, tryy))
- { // open any specials
- if(actor->flags&MF_FLOAT && floatok)
- { // must adjust height
- if(actor->z < tmfloorz)
- {
- actor->z += FLOATSPEED;
- }
- else
- {
- actor->z -= FLOATSPEED;
- }
- actor->flags |= MF_INFLOAT;
- return(true);
- }
- if(!numspechit)
- {
- return false;
- }
- actor->movedir = DI_NODIR;
- good = false;
- while(numspechit--)
- {
- ld = spechit[numspechit];
- // if the special isn't a door that can be opened, return false
- if(P_UseSpecialLine(actor, ld))
- {
- good = true;
- }
- }
- return(good);
- }
- else
- {
- actor->flags &= ~MF_INFLOAT;
- }
- if(!(actor->flags&MF_FLOAT))
- {
- if(actor->z > actor->floorz)
- {
- P_HitFloor(actor);
- }
- actor->z = actor->floorz;
- }
- return(true);
- }
- //----------------------------------------------------------------------------
- //
- // FUNC P_TryWalk
- //
- // Attempts to move actor in its current (ob->moveangle) direction.
- // If blocked by either a wall or an actor returns FALSE.
- // If move is either clear of block only by a door, returns TRUE and sets.
- // If a door is in the way, an OpenDoor call is made to start it opening.
- //
- //----------------------------------------------------------------------------
- boolean P_TryWalk(mobj_t *actor)
- {
- if(!P_Move(actor))
- {
- return(false);
- }
- actor->movecount = P_Random()&15;
- return(true);
- }
- /*
- ================
- =
- = P_NewChaseDir
- =
- ================
- */
- dirtype_t opposite[] =
- {DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, DI_EAST, DI_NORTHEAST,
- DI_NORTH, DI_NORTHWEST, DI_NODIR};
- dirtype_t diags[] = {DI_NORTHWEST,DI_NORTHEAST,DI_SOUTHWEST,DI_SOUTHEAST};
- void P_NewChaseDir (mobj_t *actor)
- {
- fixed_t deltax,deltay;
- dirtype_t d[3];
- dirtype_t tdir, olddir, turnaround;
- if (!actor->target)
- I_Error ("P_NewChaseDir: called with no target");
-
- olddir = actor->movedir;
- turnaround=opposite[olddir];
- deltax = actor->target->x - actor->x;
- deltay = actor->target->y - actor->y;
- if (deltax>10*FRACUNIT)
- d[1]= DI_EAST;
- else if (deltax<-10*FRACUNIT)
- d[1]= DI_WEST;
- else
- d[1]=DI_NODIR;
- if (deltay<-10*FRACUNIT)
- d[2]= DI_SOUTH;
- else if (deltay>10*FRACUNIT)
- d[2]= DI_NORTH;
- else
- d[2]=DI_NODIR;
- // try direct route
- if (d[1] != DI_NODIR && d[2] != DI_NODIR)
- {
- actor->movedir = diags[((deltay<0)<<1)+(deltax>0)];
- if (actor->movedir != turnaround && P_TryWalk(actor))
- return;
- }
- // try other directions
- if (P_Random() > 200 || abs(deltay)>abs(deltax))
- {
- tdir=d[1];
- d[1]=d[2];
- d[2]=tdir;
- }
- if (d[1]==turnaround)
- d[1]=DI_NODIR;
- if (d[2]==turnaround)
- d[2]=DI_NODIR;
-
- if (d[1]!=DI_NODIR)
- {
- actor->movedir = d[1];
- if (P_TryWalk(actor))
- return; /*either moved forward or attacked*/
- }
- if (d[2]!=DI_NODIR)
- {
- actor->movedir =d[2];
- if (P_TryWalk(actor))
- return;
- }
- /* there is no direct path to the player, so pick another direction */
- if (olddir!=DI_NODIR)
- {
- actor->movedir =olddir;
- if (P_TryWalk(actor))
- return;
- }
- if (P_Random()&1) /*randomly determine direction of search*/
- {
- for (tdir=DI_EAST ; tdir<=DI_SOUTHEAST ; tdir++)
- {
- if (tdir!=turnaround)
- {
- actor->movedir =tdir;
- if ( P_TryWalk(actor) )
- return;
- }
- }
- }
- else
- {
- for (tdir=DI_SOUTHEAST ; tdir >= DI_EAST;tdir--)
- {
- if (tdir!=turnaround)
- {
- actor->movedir =tdir;
- if ( P_TryWalk(actor) )
- return;
- }
- }
- }
- if (turnaround != DI_NODIR)
- {
- actor->movedir =turnaround;
- if ( P_TryWalk(actor) )
- return;
- }
- actor->movedir = DI_NODIR; // can't move
- }
- //---------------------------------------------------------------------------
- //
- // FUNC P_LookForMonsters
- //
- //---------------------------------------------------------------------------
- #define MONS_LOOK_RANGE (20*64*FRACUNIT)
- #define MONS_LOOK_LIMIT 64
- boolean P_LookForMonsters(mobj_t *actor)
- {
- int count;
- mobj_t *mo;
- thinker_t *think;
- if(!P_CheckSight(players[0].mo, actor))
- { // Player can't see monster
- return(false);
- }
- count = 0;
- for(think = thinkercap.next; think != &thinkercap; think = think->next)
- {
- if(think->function != P_MobjThinker)
- { // Not a mobj thinker
- continue;
- }
- mo = (mobj_t *)think;
- if(!(mo->flags&MF_COUNTKILL) || (mo == actor) || (mo->health <= 0))
- { // Not a valid monster
- continue;
- }
- if(P_AproxDistance(actor->x-mo->x, actor->y-mo->y)
- > MONS_LOOK_RANGE)
- { // Out of range
- continue;
- }
- if(P_Random() < 16)
- { // Skip
- continue;
- }
- if(count++ > MONS_LOOK_LIMIT)
- { // Stop searching
- return(false);
- }
- if(!P_CheckSight(actor, mo))
- { // Out of sight
- continue;
- }
- // Found a target monster
- actor->target = mo;
- return(true);
- }
- return(false);
- }
- /*
- ================
- =
- = P_LookForPlayers
- =
- = If allaround is false, only look 180 degrees in front
- = returns true if a player is targeted
- ================
- */
- boolean P_LookForPlayers(mobj_t *actor, boolean allaround)
- {
- int c;
- int stop;
- player_t *player;
- sector_t *sector;
- angle_t an;
- fixed_t dist;
- if(!netgame && players[0].health <= 0)
- { // Single player game and player is dead, look for monsters
- return(P_LookForMonsters(actor));
- }
- sector = actor->subsector->sector;
- c = 0;
- stop = (actor->lastlook-1)&3;
- for( ; ; actor->lastlook = (actor->lastlook+1)&3 )
- {
- if (!playeringame[actor->lastlook])
- continue;
-
- if (c++ == 2 || actor->lastlook == stop)
- return false; // done looking
- player = &players[actor->lastlook];
- if (player->health <= 0)
- continue; // dead
- if (!P_CheckSight (actor, player->mo))
- continue; // out of sight
-
- if (!allaround)
- {
- an = R_PointToAngle2 (actor->x, actor->y,
- player->mo->x, player->mo->y) - actor->angle;
- if (an > ANG90 && an < ANG270)
- {
- dist = P_AproxDistance (player->mo->x - actor->x,
- player->mo->y - actor->y);
- // if real close, react anyway
- if (dist > MELEERANGE)
- continue; // behind back
- }
- }
- if(player->mo->flags&MF_SHADOW)
- { // Player is invisible
- if((P_AproxDistance(player->mo->x-actor->x,
- player->mo->y-actor->y) > 2*MELEERANGE)
- && P_AproxDistance(player->mo->momx, player->mo->momy)
- < 5*FRACUNIT)
- { // Player is sneaking - can't detect
- return(false);
- }
- if(P_Random() < 225)
- { // Player isn't sneaking, but still didn't detect
- return(false);
- }
- }
- actor->target = player->mo;
- return(true);
- }
- return(false);
- }
- /*
- ===============================================================================
- ACTION ROUTINES
- ===============================================================================
- */
- /*
- ==============
- =
- = A_Look
- =
- = Stay in state until a player is sighted
- =
- ==============
- */
- void A_Look (mobj_t *actor)
- {
- mobj_t *targ;
-
- actor->threshold = 0; // any shot will wake up
- targ = actor->subsector->sector->soundtarget;
- if (targ && (targ->flags & MF_SHOOTABLE) )
- {
- actor->target = targ;
- if ( actor->flags & MF_AMBUSH )
- {
- if (P_CheckSight (actor, actor->target))
- goto seeyou;
- }
- else
- goto seeyou;
- }
-
-
- if (!P_LookForPlayers (actor, false) )
- return;
-
- // go into chase state
- seeyou:
- if (actor->info->seesound)
- {
- int sound;
-
- /*
- switch (actor->info->seesound)
- {
- case sfx_posit1:
- case sfx_posit2:
- case sfx_posit3:
- sound = sfx_posit1+P_Random()%3;
- break;
- case sfx_bgsit1:
- case sfx_bgsit2:
- sound = sfx_bgsit1+P_Random()%2;
- break;
- default:
- sound = actor->info->seesound;
- break;
- }
- */
- sound = actor->info->seesound;
- if(actor->flags2&MF2_BOSS)
- { // Full volume
- S_StartSound(NULL, sound);
- }
- else
- {
- S_StartSound(actor, sound);
- }
- }
- P_SetMobjState(actor, actor->info->seestate);
- }
- /*
- ==============
- =
- = A_Chase
- =
- = Actor has a melee attack, so it tries to close as fast as possible
- =
- ==============
- */
- void A_Chase(mobj_t *actor)
- {
- int delta;
- if(actor->reactiontime)
- {
- actor->reactiontime--;
- }
- // Modify target threshold
- if(actor->threshold)
- {
- actor->threshold--;
- }
- if(gameskill == sk_nightmare)
- { // Monsters move faster in nightmare mode
- actor->tics -= actor->tics/2;
- if(actor->tics < 3)
- {
- actor->tics = 3;
- }
- }
- //
- // turn towards movement direction if not there yet
- //
- if(actor->movedir < 8)
- {
- actor->angle &= (7<<29);
- delta = actor->angle-(actor->movedir << 29);
- if(delta > 0)
- {
- actor->angle -= ANG90/2;
- }
- else if(delta < 0)
- {
- actor->angle += ANG90/2;
- }
- }
- if(!actor->target || !(actor->target->flags&MF_SHOOTABLE))
- { // look for a new target
- if(P_LookForPlayers(actor, true))
- { // got a new target
- return;
- }
- P_SetMobjState(actor, actor->info->spawnstate);
- return;
- }
-
- //
- // don't attack twice in a row
- //
- if(actor->flags & MF_JUSTATTACKED)
- {
- actor->flags &= ~MF_JUSTATTACKED;
- if (gameskill != sk_nightmare)
- P_NewChaseDir (actor);
- return;
- }
-
- //
- // check for melee attack
- //
- if (actor->info->meleestate && P_CheckMeleeRange (actor))
- {
- if (actor->info->attacksound)
- S_StartSound (actor, actor->info->attacksound);
- P_SetMobjState (actor, actor->info->meleestate);
- return;
- }
- //
- // check for missile attack
- //
- if (actor->info->missilestate)
- {
- if (gameskill < sk_nightmare && actor->movecount)
- goto nomissile;
- if (!P_CheckMissileRange (actor))
- goto nomissile;
- P_SetMobjState (actor, actor->info->missilestate);
- actor->flags |= MF_JUSTATTACKED;
- return;
- }
- nomissile:
- //
- // possibly choose another target
- //
- if (netgame && !actor->threshold && !P_CheckSight (actor, actor->target) )
- {
- if (P_LookForPlayers(actor,true))
- return; // got a new target
- }
-
- //
- // chase towards player
- //
- if (--actor->movecount<0 || !P_Move (actor))
- {
- P_NewChaseDir (actor);
- }
- //
- // make active sound
- //
- if(actor->info->activesound && P_Random() < 3)
- {
- if(actor->type == MT_WIZARD && P_Random() < 128)
- {
- S_StartSound(actor, actor->info->seesound);
- }
- else if(actor->type == MT_SORCERER2)
- {
- S_StartSound(NULL, actor->info->activesound);
- }
- else
- {
- S_StartSound(actor, actor->info->activesound);
- }
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_FaceTarget
- //
- //----------------------------------------------------------------------------
- void A_FaceTarget(mobj_t *actor)
- {
- if(!actor->target)
- {
- return;
- }
- actor->flags &= ~MF_AMBUSH;
- actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x,
- actor->target->y);
- if(actor->target->flags&MF_SHADOW)
- { // Target is a ghost
- actor->angle += (P_Random()-P_Random())<<21;
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_Pain
- //
- //----------------------------------------------------------------------------
- void A_Pain(mobj_t *actor)
- {
- if(actor->info->painsound)
- {
- S_StartSound(actor, actor->info->painsound);
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_DripBlood
- //
- //----------------------------------------------------------------------------
- void A_DripBlood(mobj_t *actor)
- {
- mobj_t *mo;
- mo = P_SpawnMobj(actor->x+((P_Random()-P_Random())<<11),
- actor->y+((P_Random()-P_Random())<<11), actor->z, MT_BLOOD);
- mo->momx = (P_Random()-P_Random())<<10;
- mo->momy = (P_Random()-P_Random())<<10;
- mo->flags2 |= MF2_LOGRAV;
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_KnightAttack
- //
- //----------------------------------------------------------------------------
- void A_KnightAttack(mobj_t *actor)
- {
- if(!actor->target)
- {
- return;
- }
- if(P_CheckMeleeRange(actor))
- {
- P_DamageMobj(actor->target, actor, actor, HITDICE(3));
- S_StartSound(actor, sfx_kgtat2);
- return;
- }
- // Throw axe
- S_StartSound(actor, actor->info->attacksound);
- if(actor->type == MT_KNIGHTGHOST || P_Random() < 40)
- { // Red axe
- P_SpawnMissile(actor, actor->target, MT_REDAXE);
- return;
- }
- // Green axe
- P_SpawnMissile(actor, actor->target, MT_KNIGHTAXE);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_ImpExplode
- //
- //----------------------------------------------------------------------------
- void A_ImpExplode(mobj_t *actor)
- {
- mobj_t *mo;
- mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_IMPCHUNK1);
- mo->momx = (P_Random() - P_Random ())<<10;
- mo->momy = (P_Random() - P_Random ())<<10;
- mo->momz = 9*FRACUNIT;
- mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_IMPCHUNK2);
- mo->momx = (P_Random() - P_Random ())<<10;
- mo->momy = (P_Random() - P_Random ())<<10;
- mo->momz = 9*FRACUNIT;
- if(actor->special1 == 666)
- { // Extreme death crash
- P_SetMobjState(actor, S_IMP_XCRASH1);
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_BeastPuff
- //
- //----------------------------------------------------------------------------
- void A_BeastPuff(mobj_t *actor)
- {
- if(P_Random() > 64)
- {
- P_SpawnMobj(actor->x+((P_Random()-P_Random())<<10),
- actor->y+((P_Random()-P_Random())<<10),
- actor->z+((P_Random()-P_Random())<<10), MT_PUFFY);
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_ImpMeAttack
- //
- //----------------------------------------------------------------------------
- void A_ImpMeAttack(mobj_t *actor)
- {
- if(!actor->target)
- {
- return;
- }
- S_StartSound(actor, actor->info->attacksound);
- if(P_CheckMeleeRange(actor))
- {
- P_DamageMobj(actor->target, actor, actor, 5+(P_Random()&7));
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_ImpMsAttack
- //
- //----------------------------------------------------------------------------
- void A_ImpMsAttack(mobj_t *actor)
- {
- mobj_t *dest;
- angle_t an;
- int dist;
- if(!actor->target || P_Random() > 64)
- {
- P_SetMobjState(actor, actor->info->seestate);
- return;
- }
- dest = actor->target;
- actor->flags |= MF_SKULLFLY;
- S_StartSound(actor, actor->info->attacksound);
- A_FaceTarget(actor);
- an = actor->angle >> ANGLETOFINESHIFT;
- actor->momx = FixedMul(12*FRACUNIT, finecosine[an]);
- actor->momy = FixedMul(12*FRACUNIT, finesine[an]);
- dist = P_AproxDistance(dest->x-actor->x, dest->y-actor->y);
- dist = dist/(12*FRACUNIT);
- if(dist < 1)
- {
- dist = 1;
- }
- actor->momz = (dest->z+(dest->height>>1)-actor->z)/dist;
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_ImpMsAttack2
- //
- // Fireball attack of the imp leader.
- //
- //----------------------------------------------------------------------------
- void A_ImpMsAttack2(mobj_t *actor)
- {
- if(!actor->target)
- {
- return;
- }
- S_StartSound(actor, actor->info->attacksound);
- if(P_CheckMeleeRange(actor))
- {
- P_DamageMobj(actor->target, actor, actor, 5+(P_Random()&7));
- return;
- }
- P_SpawnMissile(actor, actor->target, MT_IMPBALL);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_ImpDeath
- //
- //----------------------------------------------------------------------------
- void A_ImpDeath(mobj_t *actor)
- {
- actor->flags &= ~MF_SOLID;
- actor->flags2 |= MF2_FOOTCLIP;
- if(actor->z <= actor->floorz)
- {
- P_SetMobjState(actor, S_IMP_CRASH1);
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_ImpXDeath1
- //
- //----------------------------------------------------------------------------
- void A_ImpXDeath1(mobj_t *actor)
- {
- actor->flags &= ~MF_SOLID;
- actor->flags |= MF_NOGRAVITY;
- actor->flags2 |= MF2_FOOTCLIP;
- actor->special1 = 666; // Flag the crash routine
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_ImpXDeath2
- //
- //----------------------------------------------------------------------------
- void A_ImpXDeath2(mobj_t *actor)
- {
- actor->flags &= ~MF_NOGRAVITY;
- if(actor->z <= actor->floorz)
- {
- P_SetMobjState(actor, S_IMP_CRASH1);
- }
- }
- //----------------------------------------------------------------------------
- //
- // FUNC P_UpdateChicken
- //
- // Returns true if the chicken morphs.
- //
- //----------------------------------------------------------------------------
- boolean P_UpdateChicken(mobj_t *actor, int tics)
- {
- mobj_t *fog;
- fixed_t x;
- fixed_t y;
- fixed_t z;
- mobjtype_t moType;
- mobj_t *mo;
- mobj_t oldChicken;
- actor->special1 -= tics;
- if(actor->special1 > 0)
- {
- return(false);
- }
- moType = actor->special2;
- x = actor->x;
- y = actor->y;
- z = actor->z;
- oldChicken = *actor;
- P_SetMobjState(actor, S_FREETARGMOBJ);
- mo = P_SpawnMobj(x, y, z, moType);
- if(P_TestMobjLocation(mo) == false)
- { // Didn't fit
- P_RemoveMobj(mo);
- mo = P_SpawnMobj(x, y, z, MT_CHICKEN);
- mo->angle = oldChicken.angle;
- mo->flags = oldChicken.flags;
- mo->health = oldChicken.health;
- mo->target = oldChicken.target;
- mo->special1 = 5*35; // Next try in 5 seconds
- mo->special2 = moType;
- return(false);
- }
- mo->angle = oldChicken.angle;
- mo->target = oldChicken.target;
- fog = P_SpawnMobj(x, y, z+TELEFOGHEIGHT, MT_TFOG);
- S_StartSound(fog, sfx_telept);
- return(true);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_ChicAttack
- //
- //----------------------------------------------------------------------------
- void A_ChicAttack(mobj_t *actor)
- {
- if(P_UpdateChicken(actor, 18))
- {
- return;
- }
- if(!actor->target)
- {
- return;
- }
- if(P_CheckMeleeRange(actor))
- {
- P_DamageMobj(actor->target, actor, actor, 1+(P_Random()&1));
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_ChicLook
- //
- //----------------------------------------------------------------------------
- void A_ChicLook(mobj_t *actor)
- {
- if(P_UpdateChicken(actor, 10))
- {
- return;
- }
- A_Look(actor);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_ChicChase
- //
- //----------------------------------------------------------------------------
- void A_ChicChase(mobj_t *actor)
- {
- if(P_UpdateChicken(actor, 3))
- {
- return;
- }
- A_Chase(actor);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_ChicPain
- //
- //----------------------------------------------------------------------------
- void A_ChicPain(mobj_t *actor)
- {
- if(P_UpdateChicken(actor, 10))
- {
- return;
- }
- S_StartSound(actor, actor->info->painsound);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_Feathers
- //
- //----------------------------------------------------------------------------
- void A_Feathers(mobj_t *actor)
- {
- int i;
- int count;
- mobj_t *mo;
- if(actor->health > 0)
- { // Pain
- count = P_Random() < 32 ? 2 : 1;
- }
- else
- { // Death
- count = 5+(P_Random()&3);
- }
- for(i = 0; i < count; i++)
- {
- mo = P_SpawnMobj(actor->x, actor->y, actor->z+20*FRACUNIT,
- MT_FEATHER);
- mo->target = actor;
- mo->momx = (P_Random()-P_Random())<<8;
- mo->momy = (P_Random()-P_Random())<<8;
- mo->momz = FRACUNIT+(P_Random()<<9);
- P_SetMobjState(mo, S_FEATHER1+(P_Random()&7));
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_MummyAttack
- //
- //----------------------------------------------------------------------------
- void A_MummyAttack(mobj_t *actor)
- {
- if(!actor->target)
- {
- return;
- }
- S_StartSound(actor, actor->info->attacksound);
- if(P_CheckMeleeRange(actor))
- {
- P_DamageMobj(actor->target, actor, actor, HITDICE(2));
- S_StartSound(actor, sfx_mumat2);
- return;
- }
- S_StartSound(actor, sfx_mumat1);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_MummyAttack2
- //
- // Mummy leader missile attack.
- //
- //----------------------------------------------------------------------------
- void A_MummyAttack2(mobj_t *actor)
- {
- mobj_t *mo;
- if(!actor->target)
- {
- return;
- }
- //S_StartSound(actor, actor->info->attacksound);
- if(P_CheckMeleeRange(actor))
- {
- P_DamageMobj(actor->target, actor, actor, HITDICE(2));
- return;
- }
- mo = P_SpawnMissile(actor, actor->target, MT_MUMMYFX1);
- //mo = P_SpawnMissile(actor, actor->target, MT_EGGFX);
- if(mo != NULL)
- {
- mo->special1 = (int)actor->target;
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_MummyFX1Seek
- //
- //----------------------------------------------------------------------------
- void A_MummyFX1Seek(mobj_t *actor)
- {
- P_SeekerMissile(actor, ANGLE_1*10, ANGLE_1*20);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_MummySoul
- //
- //----------------------------------------------------------------------------
- void A_MummySoul(mobj_t *mummy)
- {
- mobj_t *mo;
- mo = P_SpawnMobj(mummy->x, mummy->y, mummy->z+10*FRACUNIT, MT_MUMMYSOUL);
- mo->momz = FRACUNIT;
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_Sor1Pain
- //
- //----------------------------------------------------------------------------
- void A_Sor1Pain(mobj_t *actor)
- {
- actor->special1 = 20; // Number of steps to walk fast
- A_Pain(actor);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_Sor1Chase
- //
- //----------------------------------------------------------------------------
- void A_Sor1Chase(mobj_t *actor)
- {
- if(actor->special1)
- {
- actor->special1--;
- actor->tics -= 3;
- }
- A_Chase(actor);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_Srcr1Attack
- //
- // Sorcerer demon attack.
- //
- //----------------------------------------------------------------------------
- void A_Srcr1Attack(mobj_t *actor)
- {
- mobj_t *mo;
- fixed_t momz;
- angle_t angle;
- if(!actor->target)
- {
- return;
- }
- S_StartSound(actor, actor->info->attacksound);
- if(P_CheckMeleeRange(actor))
- {
- P_DamageMobj(actor->target, actor, actor, HITDICE(8));
- return;
- }
- if(actor->health > (actor->info->spawnhealth/3)*2)
- { // Spit one fireball
- P_SpawnMissile(actor, actor->target, MT_SRCRFX1);
- }
- else
- { // Spit three fireballs
- mo = P_SpawnMissile(actor, actor->target, MT_SRCRFX1);
- if(mo)
- {
- momz = mo->momz;
- angle = mo->angle;
- P_SpawnMissileAngle(actor, MT_SRCRFX1, angle-ANGLE_1*3, momz);
- P_SpawnMissileAngle(actor, MT_SRCRFX1, angle+ANGLE_1*3, momz);
- }
- if(actor->health < actor->info->spawnhealth/3)
- { // Maybe attack again
- if(actor->special1)
- { // Just attacked, so don't attack again
- actor->special1 = 0;
- }
- else
- { // Set state to attack again
- actor->special1 = 1;
- P_SetMobjState(actor, S_SRCR1_ATK4);
- }
- }
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_SorcererRise
- //
- //----------------------------------------------------------------------------
- void A_SorcererRise(mobj_t *actor)
- {
- mobj_t *mo;
- actor->flags &= ~MF_SOLID;
- mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SORCERER2);
- P_SetMobjState(mo, S_SOR2_RISE1);
- mo->angle = actor->angle;
- mo->target = actor->target;
- }
- //----------------------------------------------------------------------------
- //
- // PROC P_DSparilTeleport
- //
- //----------------------------------------------------------------------------
- void P_DSparilTeleport(mobj_t *actor)
- {
- int i;
- fixed_t x;
- fixed_t y;
- fixed_t prevX;
- fixed_t prevY;
- fixed_t prevZ;
- mobj_t *mo;
- if(!BossSpotCount)
- { // No spots
- return;
- }
- i = P_Random();
- do
- {
- i++;
- x = BossSpots[i%BossSpotCount].x;
- y = BossSpots[i%BossSpotCount].y;
- } while(P_AproxDistance(actor->x-x, actor->y-y) < 128*FRACUNIT);
- prevX = actor->x;
- prevY = actor->y;
- prevZ = actor->z;
- if(P_TeleportMove(actor, x, y))
- {
- mo = P_SpawnMobj(prevX, prevY, prevZ, MT_SOR2TELEFADE);
- S_StartSound(mo, sfx_telept);
- P_SetMobjState(actor, S_SOR2_TELE1);
- S_StartSound(actor, sfx_telept);
- actor->z = actor->floorz;
- actor->angle = BossSpots[i%BossSpotCount].angle;
- actor->momx = actor->momy = actor->momz = 0;
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_Srcr2Decide
- //
- //----------------------------------------------------------------------------
- void A_Srcr2Decide(mobj_t *actor)
- {
- static int chance[] =
- {
- 192, 120, 120, 120, 64, 64, 32, 16, 0
- };
- if(!BossSpotCount)
- { // No spots
- return;
- }
- if(P_Random() < chance[actor->health/(actor->info->spawnhealth/8)])
- {
- P_DSparilTeleport(actor);
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_Srcr2Attack
- //
- //----------------------------------------------------------------------------
- void A_Srcr2Attack(mobj_t *actor)
- {
- int chance;
- if(!actor->target)
- {
- return;
- }
- S_StartSound(NULL, actor->info->attacksound);
- if(P_CheckMeleeRange(actor))
- {
- P_DamageMobj(actor->target, actor, actor, HITDICE(20));
- return;
- }
- chance = actor->health < actor->info->spawnhealth/2 ? 96 : 48;
- if(P_Random() < chance)
- { // Wizard spawners
- P_SpawnMissileAngle(actor, MT_SOR2FX2,
- actor->angle-ANG45, FRACUNIT/2);
- P_SpawnMissileAngle(actor, MT_SOR2FX2,
- actor->angle+ANG45, FRACUNIT/2);
- }
- else
- { // Blue bolt
- P_SpawnMissile(actor, actor->target, MT_SOR2FX1);
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_BlueSpark
- //
- //----------------------------------------------------------------------------
- void A_BlueSpark(mobj_t *actor)
- {
- int i;
- mobj_t *mo;
- for(i = 0; i < 2; i++)
- {
- mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SOR2FXSPARK);
- mo->momx = (P_Random()-P_Random())<<9;
- mo->momy = (P_Random()-P_Random())<<9;
- mo->momz = FRACUNIT+(P_Random()<<8);
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_GenWizard
- //
- //----------------------------------------------------------------------------
- void A_GenWizard(mobj_t *actor)
- {
- mobj_t *mo;
- mobj_t *fog;
- mo = P_SpawnMobj(actor->x, actor->y,
- actor->z-mobjinfo[MT_WIZARD].height/2, MT_WIZARD);
- if(P_TestMobjLocation(mo) == false)
- { // Didn't fit
- P_RemoveMobj(mo);
- return;
- }
- actor->momx = actor->momy = actor->momz = 0;
- P_SetMobjState(actor, mobjinfo[actor->type].deathstate);
- actor->flags &= ~MF_MISSILE;
- fog = P_SpawnMobj(actor->x, actor->y, actor->z, MT_TFOG);
- S_StartSound(fog, sfx_telept);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_Sor2DthInit
- //
- //----------------------------------------------------------------------------
- void A_Sor2DthInit(mobj_t *actor)
- {
- actor->special1 = 7; // Animation loop counter
- P_Massacre(); // Kill monsters early
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_Sor2DthLoop
- //
- //----------------------------------------------------------------------------
- void A_Sor2DthLoop(mobj_t *actor)
- {
- if(--actor->special1)
- { // Need to loop
- P_SetMobjState(actor, S_SOR2_DIE4);
- }
- }
- //----------------------------------------------------------------------------
- //
- // D'Sparil Sound Routines
- //
- //----------------------------------------------------------------------------
- void A_SorZap(mobj_t *actor) {S_StartSound(NULL, sfx_sorzap);}
- void A_SorRise(mobj_t *actor) {S_StartSound(NULL, sfx_sorrise);}
- void A_SorDSph(mobj_t *actor) {S_StartSound(NULL, sfx_sordsph);}
- void A_SorDExp(mobj_t *actor) {S_StartSound(NULL, sfx_sordexp);}
- void A_SorDBon(mobj_t *actor) {S_StartSound(NULL, sfx_sordbon);}
- void A_SorSightSnd(mobj_t *actor) {S_StartSound(NULL, sfx_sorsit);}
- //----------------------------------------------------------------------------
- //
- // PROC A_MinotaurAtk1
- //
- // Melee attack.
- //
- //----------------------------------------------------------------------------
- void A_MinotaurAtk1(mobj_t *actor)
- {
- player_t *player;
- if(!actor->target)
- {
- return;
- }
- S_StartSound(actor, sfx_stfpow);
- if(P_CheckMeleeRange(actor))
- {
- P_DamageMobj(actor->target, actor, actor, HITDICE(4));
- if((player = actor->target->player) != NULL)
- { // Squish the player
- player->deltaviewheight = -16*FRACUNIT;
- }
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_MinotaurDecide
- //
- // Choose a missile attack.
- //
- //----------------------------------------------------------------------------
- #define MNTR_CHARGE_SPEED (13*FRACUNIT)
- void A_MinotaurDecide(mobj_t *actor)
- {
- angle_t angle;
- mobj_t *target;
- int dist;
- target = actor->target;
- if(!target)
- {
- return;
- }
- S_StartSound(actor, sfx_minsit);
- dist = P_AproxDistance(actor->x-target->x, actor->y-target->y);
- if(target->z+target->height > actor->z
- && target->z+target->height < actor->z+actor->height
- && dist < 8*64*FRACUNIT
- && dist > 1*64*FRACUNIT
- && P_Random() < 150)
- { // Charge attack
- // Don't call the state function right away
- P_SetMobjStateNF(actor, S_MNTR_ATK4_1);
- actor->flags |= MF_SKULLFLY;
- A_FaceTarget(actor);
- angle = actor->angle>>ANGLETOFINESHIFT;
- actor->momx = FixedMul(MNTR_CHARGE_SPEED, finecosine[angle]);
- actor->momy = FixedMul(MNTR_CHARGE_SPEED, finesine[angle]);
- actor->special1 = 35/2; // Charge duration
- }
- else if(target->z == target->floorz
- && dist < 9*64*FRACUNIT
- && P_Random() < 220)
- { // Floor fire attack
- P_SetMobjState(actor, S_MNTR_ATK3_1);
- actor->special2 = 0;
- }
- else
- { // Swing attack
- A_FaceTarget(actor);
- // Don't need to call P_SetMobjState because the current state
- // falls through to the swing attack
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_MinotaurCharge
- //
- //----------------------------------------------------------------------------
- void A_MinotaurCharge(mobj_t *actor)
- {
- mobj_t *puff;
- if(actor->special1)
- {
- puff = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PHOENIXPUFF);
- puff->momz = 2*FRACUNIT;
- actor->special1--;
- }
- else
- {
- actor->flags &= ~MF_SKULLFLY;
- P_SetMobjState(actor, actor->info->seestate);
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_MinotaurAtk2
- //
- // Swing attack.
- //
- //----------------------------------------------------------------------------
- void A_MinotaurAtk2(mobj_t *actor)
- {
- mobj_t *mo;
- angle_t angle;
- fixed_t momz;
- if(!actor->target)
- {
- return;
- }
- S_StartSound(actor, sfx_minat2);
- if(P_CheckMeleeRange(actor))
- {
- P_DamageMobj(actor->target, actor, actor, HITDICE(5));
- return;
- }
- mo = P_SpawnMissile(actor, actor->target, MT_MNTRFX1);
- if(mo)
- {
- S_StartSound(mo, sfx_minat2);
- momz = mo->momz;
- angle = mo->angle;
- P_SpawnMissileAngle(actor, MT_MNTRFX1, angle-(ANG45/8), momz);
- P_SpawnMissileAngle(actor, MT_MNTRFX1, angle+(ANG45/8), momz);
- P_SpawnMissileAngle(actor, MT_MNTRFX1, angle-(ANG45/16), momz);
- P_SpawnMissileAngle(actor, MT_MNTRFX1, angle+(ANG45/16), momz);
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_MinotaurAtk3
- //
- // Floor fire attack.
- //
- //----------------------------------------------------------------------------
- void A_MinotaurAtk3(mobj_t *actor)
- {
- mobj_t *mo;
- player_t *player;
- if(!actor->target)
- {
- return;
- }
- if(P_CheckMeleeRange(actor))
- {
- P_DamageMobj(actor->target, actor, actor, HITDICE(5));
- if((player = actor->target->player) != NULL)
- { // Squish the player
- player->deltaviewheight = -16*FRACUNIT;
- }
- }
- else
- {
- mo = P_SpawnMissile(actor, actor->target, MT_MNTRFX2);
- if(mo != NULL)
- {
- S_StartSound(mo, sfx_minat1);
- }
- }
- if(P_Random() < 192 && actor->special2 == 0)
- {
- P_SetMobjState(actor, S_MNTR_ATK3_4);
- actor->special2 = 1;
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_MntrFloorFire
- //
- //----------------------------------------------------------------------------
- void A_MntrFloorFire(mobj_t *actor)
- {
- mobj_t *mo;
- actor->z = actor->floorz;
- mo = P_SpawnMobj(actor->x+((P_Random()-P_Random())<<10),
- actor->y+((P_Random()-P_Random())<<10), ONFLOORZ, MT_MNTRFX3);
- mo->target = actor->target;
- mo->momx = 1; // Force block checking
- P_CheckMissileSpawn(mo);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_BeastAttack
- //
- //----------------------------------------------------------------------------
- void A_BeastAttack(mobj_t *actor)
- {
- if(!actor->target)
- {
- return;
- }
- S_StartSound(actor, actor->info->attacksound);
- if(P_CheckMeleeRange(actor))
- {
- P_DamageMobj(actor->target, actor, actor, HITDICE(3));
- return;
- }
- P_SpawnMissile(actor, actor->target, MT_BEASTBALL);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_HeadAttack
- //
- //----------------------------------------------------------------------------
- void A_HeadAttack(mobj_t *actor)
- {
- int i;
- mobj_t *fire;
- mobj_t *baseFire;
- mobj_t *mo;
- mobj_t *target;
- int randAttack;
- static int atkResolve1[] = { 50, 150 };
- static int atkResolve2[] = { 150, 200 };
- int dist;
- // Ice ball (close 20% : far 60%)
- // Fire column (close 40% : far 20%)
- // Whirlwind (close 40% : far 20%)
- // Distance threshold = 8 cells
- target = actor->target;
- if(target == NULL)
- {
- return;
- }
- A_FaceTarget(actor);
- if(P_CheckMeleeRange(actor))
- {
- P_DamageMobj(target, actor, actor, HITDICE(6));
- return;
- }
- dist = P_AproxDistance(actor->x-target->x, actor->y-target->y)
- > 8*64*FRACUNIT;
- randAttack = P_Random();
- if(randAttack < atkResolve1[dist])
- { // Ice ball
- P_SpawnMissile(actor, target, MT_HEADFX1);
- S_StartSound(actor, sfx_hedat2);
- }
- else if(randAttack < atkResolve2[dist])
- { // Fire column
- baseFire = P_SpawnMissile(actor, target, MT_HEADFX3);
- if(baseFire != NULL)
- {
- P_SetMobjState(baseFire, S_HEADFX3_4); // Don't grow
- for(i = 0; i < 5; i++)
- {
- fire = P_SpawnMobj(baseFire->x, baseFire->y,
- baseFire->z, MT_HEADFX3);
- if(i == 0)
- {
- S_StartSound(actor, sfx_hedat1);
- }
- fire->target = baseFire->target;
- fire->angle = baseFire->angle;
- fire->momx = baseFire->momx;
- fire->momy = baseFire->momy;
- fire->momz = baseFire->momz;
- fire->damage = 0;
- fire->health = (i+1)*2;
- P_CheckMissileSpawn(fire);
- }
- }
- }
- else
- { // Whirlwind
- mo = P_SpawnMissile(actor, target, MT_WHIRLWIND);
- if(mo != NULL)
- {
- mo->z -= 32*FRACUNIT;
- mo->special1 = (int)target;
- mo->special2 = 50; // Timer for active sound
- mo->health = 20*TICSPERSEC; // Duration
- S_StartSound(actor, sfx_hedat3);
- }
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_WhirlwindSeek
- //
- //----------------------------------------------------------------------------
- void A_WhirlwindSeek(mobj_t *actor)
- {
- actor->health -= 3;
- if(actor->health < 0)
- {
- actor->momx = actor->momy = actor->momz = 0;
- P_SetMobjState(actor, mobjinfo[actor->type].deathstate);
- actor->flags &= ~MF_MISSILE;
- return;
- }
- if((actor->special2 -= 3) < 0)
- {
- actor->special2 = 58+(P_Random()&31);
- S_StartSound(actor, sfx_hedat3);
- }
- if(actor->special1
- && (((mobj_t *)(actor->special1))->flags&MF_SHADOW))
- {
- return;
- }
- P_SeekerMissile(actor, ANGLE_1*10, ANGLE_1*30);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_HeadIceImpact
- //
- //----------------------------------------------------------------------------
- void A_HeadIceImpact(mobj_t *ice)
- {
- int i;
- angle_t angle;
- mobj_t *shard;
- for(i = 0; i < 8; i++)
- {
- shard = P_SpawnMobj(ice->x, ice->y, ice->z, MT_HEADFX2);
- angle = i*ANG45;
- shard->target = ice->target;
- shard->angle = angle;
- angle >>= ANGLETOFINESHIFT;
- shard->momx = FixedMul(shard->info->speed, finecosine[angle]);
- shard->momy = FixedMul(shard->info->speed, finesine[angle]);
- shard->momz = -.6*FRACUNIT;
- P_CheckMissileSpawn(shard);
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_HeadFireGrow
- //
- //----------------------------------------------------------------------------
- void A_HeadFireGrow(mobj_t *fire)
- {
- fire->health--;
- fire->z += 9*FRACUNIT;
- if(fire->health == 0)
- {
- fire->damage = fire->info->damage;
- P_SetMobjState(fire, S_HEADFX3_4);
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_SnakeAttack
- //
- //----------------------------------------------------------------------------
- void A_SnakeAttack(mobj_t *actor)
- {
- if(!actor->target)
- {
- P_SetMobjState(actor, S_SNAKE_WALK1);
- return;
- }
- S_StartSound(actor, actor->info->attacksound);
- A_FaceTarget(actor);
- P_SpawnMissile(actor, actor->target, MT_SNAKEPRO_A);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_SnakeAttack2
- //
- //----------------------------------------------------------------------------
- void A_SnakeAttack2(mobj_t *actor)
- {
- if(!actor->target)
- {
- P_SetMobjState(actor, S_SNAKE_WALK1);
- return;
- }
- S_StartSound(actor, actor->info->attacksound);
- A_FaceTarget(actor);
- P_SpawnMissile(actor, actor->target, MT_SNAKEPRO_B);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_ClinkAttack
- //
- //----------------------------------------------------------------------------
- void A_ClinkAttack(mobj_t *actor)
- {
- int damage;
- if(!actor->target)
- {
- return;
- }
- S_StartSound(actor, actor->info->attacksound);
- if(P_CheckMeleeRange(actor))
- {
- damage = ((P_Random()%7)+3);
- P_DamageMobj(actor->target, actor, actor, damage);
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_GhostOff
- //
- //----------------------------------------------------------------------------
- void A_GhostOff(mobj_t *actor)
- {
- actor->flags &= ~MF_SHADOW;
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_WizAtk1
- //
- //----------------------------------------------------------------------------
- void A_WizAtk1(mobj_t *actor)
- {
- A_FaceTarget(actor);
- actor->flags &= ~MF_SHADOW;
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_WizAtk2
- //
- //----------------------------------------------------------------------------
- void A_WizAtk2(mobj_t *actor)
- {
- A_FaceTarget(actor);
- actor->flags |= MF_SHADOW;
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_WizAtk3
- //
- //----------------------------------------------------------------------------
- void A_WizAtk3(mobj_t *actor)
- {
- mobj_t *mo;
- angle_t angle;
- fixed_t momz;
- actor->flags &= ~MF_SHADOW;
- if(!actor->target)
- {
- return;
- }
- S_StartSound(actor, actor->info->attacksound);
- if(P_CheckMeleeRange(actor))
- {
- P_DamageMobj(actor->target, actor, actor, HITDICE(4));
- return;
- }
- mo = P_SpawnMissile(actor, actor->target, MT_WIZFX1);
- if(mo)
- {
- momz = mo->momz;
- angle = mo->angle;
- P_SpawnMissileAngle(actor, MT_WIZFX1, angle-(ANG45/8), momz);
- P_SpawnMissileAngle(actor, MT_WIZFX1, angle+(ANG45/8), momz);
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_Scream
- //
- //----------------------------------------------------------------------------
- void A_Scream(mobj_t *actor)
- {
- switch(actor->type)
- {
- case MT_CHICPLAYER:
- case MT_SORCERER1:
- case MT_MINOTAUR:
- // Make boss death sounds full volume
- S_StartSound(NULL, actor->info->deathsound);
- break;
- case MT_PLAYER:
- // Handle the different player death screams
- if(actor->special1 < 10)
- { // Wimpy death sound
- S_StartSound(actor, sfx_plrwdth);
- }
- else if(actor->health > -50)
- { // Normal death sound
- S_StartSound(actor, actor->info->deathsound);
- }
- else if(actor->health > -100)
- { // Crazy death sound
- S_StartSound(actor, sfx_plrcdth);
- }
- else
- { // Extreme death sound
- S_StartSound(actor, sfx_gibdth);
- }
- break;
- default:
- S_StartSound(actor, actor->info->deathsound);
- break;
- }
- }
- //---------------------------------------------------------------------------
- //
- // PROC P_DropItem
- //
- //---------------------------------------------------------------------------
- void P_DropItem(mobj_t *source, mobjtype_t type, int special, int chance)
- {
- mobj_t *mo;
- if(P_Random() > chance)
- {
- return;
- }
- mo = P_SpawnMobj(source->x, source->y,
- source->z+(source->height>>1), type);
- mo->momx = (P_Random()-P_Random())<<8;
- mo->momy = (P_Random()-P_Random())<<8;
- mo->momz = FRACUNIT*5+(P_Random()<<10);
- mo->flags |= MF_DROPPED;
- mo->health = special;
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_NoBlocking
- //
- //----------------------------------------------------------------------------
- void A_NoBlocking(mobj_t *actor)
- {
- actor->flags &= ~MF_SOLID;
- // Check for monsters dropping things
- switch(actor->type)
- {
- case MT_MUMMY:
- case MT_MUMMYLEADER:
- case MT_MUMMYGHOST:
- case MT_MUMMYLEADERGHOST:
- P_DropItem(actor, MT_AMGWNDWIMPY, 3, 84);
- break;
- case MT_KNIGHT:
- case MT_KNIGHTGHOST:
- P_DropItem(actor, MT_AMCBOWWIMPY, 5, 84);
- break;
- case MT_WIZARD:
- P_DropItem(actor, MT_AMBLSRWIMPY, 10, 84);
- P_DropItem(actor, MT_ARTITOMEOFPOWER, 0, 4);
- break;
- case MT_HEAD:
- P_DropItem(actor, MT_AMBLSRWIMPY, 10, 84);
- P_DropItem(actor, MT_ARTIEGG, 0, 51);
- break;
- case MT_BEAST:
- P_DropItem(actor, MT_AMCBOWWIMPY, 10, 84);
- break;
- case MT_CLINK:
- P_DropItem(actor, MT_AMSKRDWIMPY, 20, 84);
- break;
- case MT_SNAKE:
- P_DropItem(actor, MT_AMPHRDWIMPY, 5, 84);
- break;
- case MT_MINOTAUR:
- P_DropItem(actor, MT_ARTISUPERHEAL, 0, 51);
- P_DropItem(actor, MT_AMPHRDWIMPY, 10, 84);
- break;
- default:
- break;
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_Explode
- //
- // Handles a bunch of exploding things.
- //
- //----------------------------------------------------------------------------
- void A_Explode(mobj_t *actor)
- {
- int damage;
- damage = 128;
- switch(actor->type)
- {
- case MT_FIREBOMB: // Time Bombs
- actor->z += 32*FRACUNIT;
- actor->flags &= ~MF_SHADOW;
- break;
- case MT_MNTRFX2: // Minotaur floor fire
- damage = 24;
- break;
- case MT_SOR2FX1: // D'Sparil missile
- damage = 80+(P_Random()&31);
- break;
- default:
- break;
- }
- P_RadiusAttack(actor, actor->target, damage);
- P_HitFloor(actor);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_PodPain
- //
- //----------------------------------------------------------------------------
- void A_PodPain(mobj_t *actor)
- {
- int i;
- int count;
- int chance;
- mobj_t *goo;
- chance = P_Random();
- if(chance < 128)
- {
- return;
- }
- count = chance > 240 ? 2 : 1;
- for(i = 0; i < count; i++)
- {
- goo = P_SpawnMobj(actor->x, actor->y,
- actor->z+48*FRACUNIT, MT_PODGOO);
- goo->target = actor;
- goo->momx = (P_Random()-P_Random())<<9;
- goo->momy = (P_Random()-P_Random())<<9;
- goo->momz = FRACUNIT/2+(P_Random()<<9);
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_RemovePod
- //
- //----------------------------------------------------------------------------
- void A_RemovePod(mobj_t *actor)
- {
- mobj_t *mo;
- if(actor->special2)
- {
- mo = (mobj_t *)actor->special2;
- if(mo->special1 > 0)
- {
- mo->special1--;
- }
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_MakePod
- //
- //----------------------------------------------------------------------------
- #define MAX_GEN_PODS 16
- void A_MakePod(mobj_t *actor)
- {
- mobj_t *mo;
- fixed_t x;
- fixed_t y;
- fixed_t z;
- if(actor->special1 == MAX_GEN_PODS)
- { // Too many generated pods
- return;
- }
- x = actor->x;
- y = actor->y;
- z = actor->z;
- mo = P_SpawnMobj(x, y, ONFLOORZ, MT_POD);
- if(P_CheckPosition(mo, x, y) == false)
- { // Didn't fit
- P_RemoveMobj(mo);
- return;
- }
- P_SetMobjState(mo, S_POD_GROW1);
- P_ThrustMobj(mo, P_Random()<<24, (fixed_t)(4.5*FRACUNIT));
- S_StartSound(mo, sfx_newpod);
- actor->special1++; // Increment generated pod count
- mo->special2 = (int)actor; // Link the generator to the pod
- return;
- }
- //----------------------------------------------------------------------------
- //
- // PROC P_Massacre
- //
- // Kills all monsters.
- //
- //----------------------------------------------------------------------------
- void P_Massacre(void)
- {
- mobj_t *mo;
- thinker_t *think;
- for(think = thinkercap.next; think != &thinkercap;
- think = think->next)
- {
- if(think->function != P_MobjThinker)
- { // Not a mobj thinker
- continue;
- }
- mo = (mobj_t *)think;
- if((mo->flags&MF_COUNTKILL) && (mo->health > 0))
- {
- P_DamageMobj(mo, NULL, NULL, 10000);
- }
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_BossDeath
- //
- // Trigger special effects if all bosses are dead.
- //
- //----------------------------------------------------------------------------
- void A_BossDeath(mobj_t *actor)
- {
- mobj_t *mo;
- thinker_t *think;
- line_t dummyLine;
- static mobjtype_t bossType[6] =
- {
- MT_HEAD,
- MT_MINOTAUR,
- MT_SORCERER2,
- MT_HEAD,
- MT_MINOTAUR,
- -1
- };
- if(gamemap != 8)
- { // Not a boss level
- return;
- }
- if(actor->type != bossType[gameepisode-1])
- { // Not considered a boss in this episode
- return;
- }
- // Make sure all bosses are dead
- for(think = thinkercap.next; think != &thinkercap; think = think->next)
- {
- if(think->function != P_MobjThinker)
- { // Not a mobj thinker
- continue;
- }
- mo = (mobj_t *)think;
- if((mo != actor) && (mo->type == actor->type) && (mo->health > 0))
- { // Found a living boss
- return;
- }
- }
- if(gameepisode > 1)
- { // Kill any remaining monsters
- P_Massacre();
- }
- dummyLine.tag = 666;
- EV_DoFloor(&dummyLine, lowerFloor);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_ESound
- //
- //----------------------------------------------------------------------------
- void A_ESound(mobj_t *mo)
- {
- int sound;
- switch(mo->type)
- {
- case MT_SOUNDWATERFALL:
- sound = sfx_waterfl;
- break;
- case MT_SOUNDWIND:
- sound = sfx_wind;
- break;
- default:
- break;
- }
- S_StartSound(mo, sound);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_SpawnTeleGlitter
- //
- //----------------------------------------------------------------------------
- void A_SpawnTeleGlitter(mobj_t *actor)
- {
- mobj_t *mo;
- mo = P_SpawnMobj(actor->x+((P_Random()&31)-16)*FRACUNIT,
- actor->y+((P_Random()&31)-16)*FRACUNIT,
- actor->subsector->sector->floorheight, MT_TELEGLITTER);
- mo->momz = FRACUNIT/4;
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_SpawnTeleGlitter2
- //
- //----------------------------------------------------------------------------
- void A_SpawnTeleGlitter2(mobj_t *actor)
- {
- mobj_t *mo;
- mo = P_SpawnMobj(actor->x+((P_Random()&31)-16)*FRACUNIT,
- actor->y+((P_Random()&31)-16)*FRACUNIT,
- actor->subsector->sector->floorheight, MT_TELEGLITTER2);
- mo->momz = FRACUNIT/4;
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_AccTeleGlitter
- //
- //----------------------------------------------------------------------------
- void A_AccTeleGlitter(mobj_t *actor)
- {
- if(++actor->health > 35)
- {
- actor->momz += actor->momz/2;
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_InitKeyGizmo
- //
- //----------------------------------------------------------------------------
- void A_InitKeyGizmo(mobj_t *gizmo)
- {
- mobj_t *mo;
- statenum_t state;
- switch(gizmo->type)
- {
- case MT_KEYGIZMOBLUE:
- state = S_KGZ_BLUEFLOAT1;
- break;
- case MT_KEYGIZMOGREEN:
- state = S_KGZ_GREENFLOAT1;
- break;
- case MT_KEYGIZMOYELLOW:
- state = S_KGZ_YELLOWFLOAT1;
- break;
- default:
- break;
- }
- mo = P_SpawnMobj(gizmo->x, gizmo->y, gizmo->z+60*FRACUNIT,
- MT_KEYGIZMOFLOAT);
- P_SetMobjState(mo, state);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_VolcanoSet
- //
- //----------------------------------------------------------------------------
- void A_VolcanoSet(mobj_t *volcano)
- {
- volcano->tics = 105+(P_Random()&127);
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_VolcanoBlast
- //
- //----------------------------------------------------------------------------
- void A_VolcanoBlast(mobj_t *volcano)
- {
- int i;
- int count;
- mobj_t *blast;
- angle_t angle;
- count = 1+(P_Random()%3);
- for(i = 0; i < count; i++)
- {
- blast = P_SpawnMobj(volcano->x, volcano->y,
- volcano->z+44*FRACUNIT, MT_VOLCANOBLAST); // MT_VOLCANOBLAST
- blast->target = volcano;
- angle = P_Random()<<24;
- blast->angle = angle;
- angle >>= ANGLETOFINESHIFT;
- blast->momx = FixedMul(1*FRACUNIT, finecosine[angle]);
- blast->momy = FixedMul(1*FRACUNIT, finesine[angle]);
- blast->momz = (2.5*FRACUNIT)+(P_Random()<<10);
- S_StartSound(blast, sfx_volsht);
- P_CheckMissileSpawn(blast);
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_VolcBallImpact
- //
- //----------------------------------------------------------------------------
- void A_VolcBallImpact(mobj_t *ball)
- {
- int i;
- mobj_t *tiny;
- angle_t angle;
- if(ball->z <= ball->floorz)
- {
- ball->flags |= MF_NOGRAVITY;
- ball->flags2 &= ~MF2_LOGRAV;
- ball->z += 28*FRACUNIT;
- //ball->momz = 3*FRACUNIT;
- }
- P_RadiusAttack(ball, ball->target, 25);
- for(i = 0; i < 4; i++)
- {
- tiny = P_SpawnMobj(ball->x, ball->y, ball->z, MT_VOLCANOTBLAST);
- tiny->target = ball;
- angle = i*ANG90;
- tiny->angle = angle;
- angle >>= ANGLETOFINESHIFT;
- tiny->momx = FixedMul(FRACUNIT*.7, finecosine[angle]);
- tiny->momy = FixedMul(FRACUNIT*.7, finesine[angle]);
- tiny->momz = FRACUNIT+(P_Random()<<9);
- P_CheckMissileSpawn(tiny);
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_SkullPop
- //
- //----------------------------------------------------------------------------
- void A_SkullPop(mobj_t *actor)
- {
- mobj_t *mo;
- player_t *player;
- actor->flags &= ~MF_SOLID;
- mo = P_SpawnMobj(actor->x, actor->y, actor->z+48*FRACUNIT,
- MT_BLOODYSKULL);
- //mo->target = actor;
- mo->momx = (P_Random()-P_Random())<<9;
- mo->momy = (P_Random()-P_Random())<<9;
- mo->momz = FRACUNIT*2+(P_Random()<<6);
- // Attach player mobj to bloody skull
- player = actor->player;
- actor->player = NULL;
- mo->player = player;
- mo->health = actor->health;
- mo->angle = actor->angle;
- player->mo = mo;
- player->lookdir = 0;
- player->damagecount = 32;
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_CheckSkullFloor
- //
- //----------------------------------------------------------------------------
- void A_CheckSkullFloor(mobj_t *actor)
- {
- if(actor->z <= actor->floorz)
- {
- P_SetMobjState(actor, S_BLOODYSKULLX1);
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_CheckSkullDone
- //
- //----------------------------------------------------------------------------
- void A_CheckSkullDone(mobj_t *actor)
- {
- if(actor->special2 == 666)
- {
- P_SetMobjState(actor, S_BLOODYSKULLX2);
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_CheckBurnGone
- //
- //----------------------------------------------------------------------------
- void A_CheckBurnGone(mobj_t *actor)
- {
- if(actor->special2 == 666)
- {
- P_SetMobjState(actor, S_PLAY_FDTH20);
- }
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_FreeTargMobj
- //
- //----------------------------------------------------------------------------
- void A_FreeTargMobj(mobj_t *mo)
- {
- mo->momx = mo->momy = mo->momz = 0;
- mo->z = mo->ceilingz+4*FRACUNIT;
- mo->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY|MF_SOLID);
- mo->flags |= MF_CORPSE|MF_DROPOFF|MF_NOGRAVITY;
- mo->flags2 &= ~(MF2_PASSMOBJ|MF2_LOGRAV);
- mo->player = NULL;
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_AddPlayerCorpse
- //
- //----------------------------------------------------------------------------
- #define BODYQUESIZE 32
- mobj_t *bodyque[BODYQUESIZE];
- int bodyqueslot;
- void A_AddPlayerCorpse(mobj_t *actor)
- {
- if(bodyqueslot >= BODYQUESIZE)
- { // Too many player corpses - remove an old one
- P_RemoveMobj(bodyque[bodyqueslot%BODYQUESIZE]);
- }
- bodyque[bodyqueslot%BODYQUESIZE] = actor;
- bodyqueslot++;
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_FlameSnd
- //
- //----------------------------------------------------------------------------
- void A_FlameSnd(mobj_t *actor)
- {
- S_StartSound(actor, sfx_hedat1); // Burn sound
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_HideThing
- //
- //----------------------------------------------------------------------------
- void A_HideThing(mobj_t *actor)
- {
- //P_UnsetThingPosition(actor);
- actor->flags2 |= MF2_DONTDRAW;
- }
- //----------------------------------------------------------------------------
- //
- // PROC A_UnHideThing
- //
- //----------------------------------------------------------------------------
- void A_UnHideThing(mobj_t *actor)
- {
- //P_SetThingPosition(actor);
- actor->flags2 &= ~MF2_DONTDRAW;
- }
|