DOOM64-RE

DOOM 64 Reverse Engineering
Log | Files | Refs | README | LICENSE

p_misc.c (19669B)


      1 /* p_misc.c */
      2 
      3 #include "doomdef.h"
      4 #include "p_local.h"
      5 #include "r_local.h"
      6 
      7 /*
      8 ==============================================================================
      9 
     10 							   AIM CAMERA
     11 
     12 ==============================================================================
     13 */
     14 
     15 #define CAMAIMANGLE ANG5
     16 
     17 void T_AimCamera(aimcamera_t *camera) // 8000DE60
     18 {
     19     angle_t delta;
     20     angle_t newangle;
     21     angle_t angle;
     22 
     23     if((cameratarget != camera->viewmobj) || (cameratarget == players[0].mo))
     24     {
     25         P_RemoveThinker(&camera->thinker);
     26         return;
     27     }
     28 
     29     /* adjust angle */
     30     newangle = R_PointToAngle2(cameratarget->x, cameratarget->y, players[0].mo->x, players[0].mo->y);
     31     angle  = cameratarget->angle;
     32     delta = (newangle - angle);
     33 
     34     if ((delta < CAMAIMANGLE) || (delta > -CAMAIMANGLE)) {
     35         cameratarget->angle = newangle;
     36     }
     37     else if (delta < ANG180) {
     38         cameratarget->angle = angle + CAMAIMANGLE;
     39     }
     40     else {
     41         cameratarget->angle = angle - CAMAIMANGLE;
     42     }
     43 }
     44 
     45 int P_SetAimCamera(line_t *line, boolean aim) // 8000DF20
     46 {
     47     aimcamera_t *camera;
     48     mobj_t *mo;
     49 
     50     if (demorecording == false)
     51     {
     52         for (mo = mobjhead.next; mo != &mobjhead; mo = mo->next)
     53         {
     54             if((line->tag != mo->tid))
     55                 continue;   /* not matching the tid */
     56 
     57             if(line->tag == cameratarget->tid)
     58                 continue; /* skip if cameratarget matches tag */
     59 
     60             cameratarget = mo;
     61             if ((cameratarget != players[0].mo) && (aim))
     62             {
     63                 mo->angle = R_PointToAngle2(mo->x, mo->y, players[0].mo->x, players[0].mo->y);
     64 
     65                 camera = Z_Malloc(sizeof(*camera), PU_LEVSPEC, NULL);
     66                 P_AddThinker(&camera->thinker);
     67                 camera->thinker.function = T_AimCamera;
     68                 camera->viewmobj = mo;
     69             }
     70 
     71             return 1;
     72         }
     73     }
     74 
     75     return 0;
     76 }
     77 
     78 /*
     79 ==============================================================================
     80 
     81                           EV_SpawnTrapMissile
     82 
     83 ==============================================================================
     84 */
     85 
     86 int EV_SpawnTrapMissile(line_t *line, mobj_t *target, mobjtype_t type) // 8000E02C
     87 {
     88     mobj_t* mo;
     89     mobj_t* th;
     90     int ok;
     91 
     92     ok = 0;
     93     for(mo = mobjhead.next; mo != &mobjhead; mo = mo->next)
     94     {
     95         if(mo->type != MT_DEST_PROJECTILE)
     96             continue;   /* not a dart projector */
     97 
     98         if((line->tag != mo->tid))
     99             continue;   /* not matching the tid */
    100 
    101         ok = 1;
    102 
    103         if(type == MT_PROJ_TRACER)
    104         {
    105             th = P_SpawnMissile(mo, target, 0, 0, (32*FRACUNIT), MT_PROJ_TRACER);
    106             th->x = (th->x + th->momx);
    107             th->y = (th->y + th->momy);
    108             th->tracer = target;
    109         }
    110         else if(type == MT_PROJ_DART)
    111         {
    112             th = P_SpawnMissile(mo, NULL, 0, 0, 0, MT_PROJ_DART);
    113         }
    114     }
    115 
    116     return ok;
    117 }
    118 
    119 /*
    120 ==============================================================================
    121 
    122 							   EXIT DELAY
    123 
    124 ==============================================================================
    125 */
    126 
    127 /*
    128 ================================================================================
    129 =
    130 = P_SpawnDelayTimer
    131 =
    132 = Exclusive Psx Doom / Doom 64
    133 =
    134 ===============================================================================
    135 */
    136 
    137 void P_SpawnDelayTimer(int tics, void(*action)()) // 8000E160
    138 {
    139 	delay_t *timer;
    140 
    141 	timer = Z_Malloc(sizeof(*timer), PU_LEVSPEC, NULL);
    142 	P_AddThinker(&timer->thinker);
    143 	timer->thinker.function = T_CountdownTimer;
    144 	timer->tics = tics;
    145 	timer->finishfunc = action;
    146 }
    147 
    148 /*
    149 ================================================================================
    150 =
    151 = T_CountdownTimer
    152 =
    153 = Exclusive Psx Doom / Doom 64
    154 =
    155 ===============================================================================
    156 */
    157 
    158 void T_CountdownTimer(delay_t *timer) // 8000E1CC
    159 {
    160     if((--timer->tics) <= 0)
    161 	{
    162 	    if (timer->finishfunc)
    163             timer->finishfunc();
    164 
    165 		P_RemoveThinker(&timer->thinker);
    166 	}
    167 }
    168 
    169 /*
    170 ================================================================================
    171 =
    172 = P_ExitLevel
    173 =
    174 = Exclusive Psx Doom / Doom 64
    175 =
    176 ===============================================================================
    177 */
    178 
    179 void P_ExitLevel(void) // 8000E220
    180 {
    181 	nextmap = gamemap + 1;
    182 	P_SpawnDelayTimer(15, G_CompleteLevel);
    183 }
    184 
    185 /*
    186 ================================================================================
    187 =
    188 = P_SecretExitLevel
    189 =
    190 = Exclusive Psx Doom / Doom 64
    191 =
    192 ===============================================================================
    193 */
    194 
    195 void P_SecretExitLevel(int map) // 8000E25C
    196 {
    197     int delaytics;
    198 
    199     if (map < LASTLEVEL)
    200         delaytics = 15;
    201     else
    202         delaytics = 120;
    203 
    204 	nextmap = map;
    205 	P_SpawnDelayTimer(delaytics, G_CompleteLevel);
    206 }
    207 
    208 /*
    209 ====================================================================
    210 
    211                         TELEPORTATION
    212  The teleportation functions for some reason, were in the middle of
    213  the other functions in this file, I move them in the corresponding
    214  file p_telept.c
    215 
    216 ====================================================================
    217 */
    218 
    219 //void P_Telefrag (mobj_t *thing, fixed_t x, fixed_t y) // 8000E29C
    220 //int	EV_Teleport( line_t *line, mobj_t *thing ) // 8000E3A0
    221 //int	EV_SilentTeleport( line_t *line, mobj_t *thing ) // 8000E5C0
    222 
    223 /* --------------------------------------------------------------------------------- */
    224 
    225 int P_ModifyLineFlags(line_t *line, int tag) // 8000E6BC
    226 {
    227     line_t *line1, *line2;
    228     int i;
    229 
    230     line2 = lines;
    231     for (i = 0; i < numlines; i++, line2++)
    232     {
    233         if (line2->tag == tag) break;
    234     }
    235 
    236     if (i < numlines)
    237     {
    238         line1 = lines;
    239         for (i = 0; i < numlines; i++, line1++)
    240         {
    241             if (line->tag == line1->tag)
    242             {
    243                 if (line1->flags & ML_TWOSIDED)
    244                 {
    245                     line1->flags = (line2->flags | ML_TWOSIDED);
    246                 }
    247                 else
    248                 {
    249                     line1->flags = line2->flags;
    250                     line1->flags &= ~ML_TWOSIDED;
    251                 }
    252             }
    253         }
    254 
    255         return 1;
    256     }
    257 
    258     return 0;
    259 }
    260 
    261 int P_ModifyLineData(line_t *line, int tag) // 8000E780
    262 {
    263     line_t *line1, *line2;
    264     int i;
    265 
    266     line2 = lines;
    267     for (i = 0; i < numlines; i++, line2++)
    268     {
    269         if (line2->tag == tag) break;
    270     }
    271 
    272     if (i < numlines)
    273     {
    274         line1 = lines;
    275         for (i = 0; i < numlines; i++, line1++)
    276         {
    277             if (line->tag == line1->tag)
    278             {
    279                 line1->special = line2->special;
    280             }
    281         }
    282 
    283         return 1;
    284     }
    285 
    286     return 0;
    287 }
    288 
    289 int P_ModifyLineTexture(line_t *line, int tag) // 8000E82C
    290 {
    291     line_t *line1, *line2;
    292     int i;
    293 
    294     line2 = lines;
    295     for (i = 0; i < numlines; i++, line2++)
    296     {
    297         if (line2->tag == tag) break;
    298     }
    299 
    300     if (i < numlines)
    301     {
    302         line1 = lines;
    303         for (i = 0; i < numlines; i++, line1++)
    304         {
    305             if (line->tag == line1->tag)
    306             {
    307                 sides[line1->sidenum[0]].toptexture    = sides[line2->sidenum[0]].toptexture;
    308                 sides[line1->sidenum[0]].bottomtexture = sides[line2->sidenum[0]].bottomtexture;
    309                 sides[line1->sidenum[0]].midtexture    = sides[line2->sidenum[0]].midtexture;
    310             }
    311         }
    312 
    313         return 1;
    314     }
    315 
    316     return 0;
    317 }
    318 
    319 int P_ModifySector(line_t *line, int tag, int type) // 8000E928
    320 {
    321     sector_t *sec1, *sec2;
    322     int secnum;
    323     int rtn;
    324 
    325     secnum = P_FindSectorFromLineTag(tag, 0);
    326 
    327     if(secnum == -1)
    328         return 0;
    329 
    330     sec2 = &sectors[secnum];
    331 
    332     secnum = -1;
    333     rtn = 0;
    334 
    335     while((secnum = P_FindSectorFromLineTag(line->tag, secnum)) >= 0)
    336     {
    337         sec1 = &sectors[secnum];
    338         rtn = 1;
    339 
    340         switch(type)
    341         {
    342         case mods_flags:
    343             sec1->flags = sec2->flags;
    344             break;
    345         case mods_special:
    346             if (sec1->special != sec2->special)
    347             {
    348                 sec1->special = sec2->special;
    349                 P_AddSectorSpecial(sec1);
    350             }
    351             break;
    352         case mods_flats:
    353             sec1->ceilingpic = sec2->ceilingpic;
    354             sec1->floorpic = sec2->floorpic;
    355             break;
    356         case mods_lights:
    357             sec1->colors[0] = sec2->colors[0];
    358             sec1->colors[1] = sec2->colors[1];
    359             sec1->colors[2] = sec2->colors[2];
    360             sec1->colors[3] = sec2->colors[3];
    361             sec1->colors[4] = sec2->colors[4];
    362             break;
    363         default:
    364             break;
    365         }
    366     }
    367 
    368     return rtn;
    369 }
    370 
    371 void T_FadeThinker(fade_t *fade) // 8000EACC
    372 {
    373     mobj_t *mo;
    374 
    375     mo = fade->mobj;
    376     mo->alpha += fade->amount;
    377 
    378     if (fade->amount > 0)
    379     {
    380         if (mo->alpha < fade->destAlpha)
    381             return;
    382 
    383         mo->alpha = fade->destAlpha;
    384         mo->flags |= fade->flagReserve;
    385         P_RemoveThinker(&fade->thinker);
    386     }
    387     else if ((fade->destAlpha < mo->alpha) == 0)
    388     {
    389         mo->alpha = fade->destAlpha;
    390         P_RemoveThinker(&fade->thinker);
    391 
    392         if (fade->destAlpha == 0)
    393             P_RemoveMobj(mo);
    394     }
    395 
    396     /*if (fade->amount <= 0)
    397     {
    398         if (mo->alpha <= fade->destAlpha)
    399         {
    400             mo->alpha = fade->destAlpha;
    401             P_RemoveThinker(&fade->thinker);
    402 
    403             if (fade->destAlpha == 0)
    404                 P_RemoveMobj(mo);
    405         }
    406     }
    407     else if (mo->alpha >= fade->destAlpha)
    408     {
    409         mo->alpha = fade->destAlpha;
    410         mo->flags |= fade->flagReserve;
    411         P_RemoveThinker(&fade->thinker);
    412     }*/
    413 }
    414 
    415 extern mobj_t *P_SpawnMapThing (mapthing_t *mthing);
    416 extern mapthing_t *spawnlist;   // 800A5D74
    417 extern int spawncount;          // 800A5D78
    418 
    419 int EV_SpawnMobjTemplate(int tag) // 8000EB8C
    420 {
    421     mobj_t *mobj;
    422     fade_t *fade;
    423     mapthing_t *mthing;
    424     int i;
    425     int rtn;
    426 
    427     rtn = 0;
    428     mthing = spawnlist;
    429     for (i = 0; i < spawncount; i++, mthing++)
    430     {
    431         if(mthing->tid != tag)
    432             continue; /* find matching tid */
    433 
    434         if(!(mobj = P_SpawnMapThing(mthing)))
    435             continue; /* setup spawning */
    436 
    437         rtn = 1;
    438         if (mobj->type == MT_DEMON2)
    439         {
    440             mobj->alpha = 48;
    441             mobj->flags |= MF_SHADOW;
    442         }
    443         else
    444         {
    445             fade = Z_Malloc (sizeof(*fade), PU_LEVSPEC, NULL);
    446             P_AddThinker (&fade->thinker);
    447             fade->thinker.function = T_FadeThinker;
    448             fade->mobj = mobj;
    449             fade->amount = 8;
    450             fade->destAlpha = mobj->alpha;
    451             fade->flagReserve = mobj->flags & (MF_SPECIAL|MF_SOLID|MF_SHOOTABLE);
    452 
    453             if (mobj->flags & MF_SHOOTABLE)
    454             {
    455                 mobj->flags &= ~MF_SHOOTABLE;
    456             }
    457             else
    458             {
    459                 mobj->flags &= ~(MF_SPECIAL|MF_SOLID|MF_SHOOTABLE);
    460             }
    461             mobj->alpha = 0;
    462         }
    463 
    464         S_StartSound(mobj, sfx_spawn);
    465     }
    466 
    467     return rtn;
    468 }
    469 
    470 int EV_FadeOutMobj(int tag) // 8000ED08
    471 {
    472     fade_t *fade;
    473     mobj_t *mo;
    474     mobj_t *pmVar1;
    475     int rtn;
    476 
    477     rtn = 0;
    478 
    479     for (mo=mobjhead.next ; mo != &mobjhead ; mo=mo->next)
    480     {
    481         if(tag != mo->tid)
    482             continue;   /* not matching the tid */
    483 
    484         rtn = 1;
    485         mo->flags &= ~(MF_SPECIAL|MF_SOLID|MF_SHOOTABLE);
    486 
    487         fade = Z_Malloc (sizeof(*fade), PU_LEVSPEC, 0);
    488         P_AddThinker (&fade->thinker);
    489         fade->thinker.function = T_FadeThinker;
    490         fade->mobj = mo;
    491         fade->amount = -8;
    492         fade->destAlpha = 0;
    493     }
    494 
    495     return rtn;
    496 }
    497 
    498 void T_Quake(quake_t *quake) // 8000EDE8
    499 {
    500     if((--quake->tics) == 0)
    501     {
    502         S_StopSound(NULL, sfx_quake);
    503         quakeviewy = 0;
    504         quakeviewx = 0;
    505         P_RemoveThinker(&quake->thinker);
    506         return;
    507     }
    508 
    509     quakeviewy = (((P_Random() & 1) << 18) - (2*FRACUNIT));
    510     quakeviewx = (((P_Random() & 1) << 24) - (128*FRACUNIT));
    511 }
    512 
    513 void P_SpawnQuake(int tics) // 8000EE7C
    514 {
    515     quake_t *quake;
    516 
    517     quake = Z_Malloc (sizeof(*quake), PU_LEVSPEC, 0);
    518     P_AddThinker (&quake->thinker);
    519     quake->thinker.function = T_Quake;
    520     quake->tics = tics;
    521 
    522     S_StopSound(NULL, sfx_quake);
    523 }
    524 
    525 int P_RandomLineTrigger(line_t *line,mobj_t *thing) // 8000EEE0
    526 {
    527     line_t *li;
    528     int line_idx[16];
    529     int i, count;
    530 
    531     if (activemacro)
    532         return 0;
    533 
    534     count = 0;
    535 
    536     li = lines;
    537     for(i = 0; ((i < numlines)&&(count < 16)); i++, li++)
    538     {
    539         /* special 240 -> Execute random line trigger */
    540         if(((line->tag == li->tag) && (li != line)) && (SPECIALMASK(li->special) != 240))
    541         {
    542             line_idx[count] = i;
    543             count++;
    544         }
    545     }
    546 
    547     if(!count)
    548         return 0;
    549 
    550     return P_UseSpecialLine(&lines[line_idx[P_Random()%count]], thing);
    551 }
    552 
    553 #define CAMMOVESPEED    164
    554 #define CAMTRACEANGLE   ANG1
    555 
    556 void T_MoveCamera(movecamera_t *camera) // 8000F014
    557 {
    558     angle_t delta;
    559     angle_t newangle;
    560     angle_t angle;
    561     int     dist;
    562     mobj_t  *mo;
    563 
    564     int iVar1;
    565 
    566     /* adjust angle */
    567     newangle = R_PointToAngle2(cameratarget->x, cameratarget->y, camera->x, camera->y);
    568     angle = cameratarget->angle;
    569     delta = newangle - angle;
    570     if ((delta < CAMTRACEANGLE) || (delta > -CAMTRACEANGLE)) {
    571         cameratarget->angle = newangle;
    572     }
    573     else if (delta < ANG180) {
    574         cameratarget->angle = angle + CAMTRACEANGLE;
    575     }
    576     else {
    577         cameratarget->angle = angle - CAMTRACEANGLE;
    578     }
    579 
    580     /* adjust pitch */
    581     dist = P_AproxDistance(cameratarget->x - camera->x, cameratarget->y - camera->y);
    582     if(dist >= (48*FRACUNIT))
    583     {
    584         newangle = R_PointToAngle2(0, cameratarget->z, dist, camera->z);
    585         angle = camviewpitch;
    586         delta = newangle - angle;
    587         if ((delta < CAMTRACEANGLE) || (delta > -CAMTRACEANGLE)) {
    588             camviewpitch = newangle;
    589         }
    590         else if (delta < ANG180) {
    591             camviewpitch = angle + CAMTRACEANGLE;
    592         }
    593         else {
    594             camviewpitch = angle - CAMTRACEANGLE;
    595         }
    596     }
    597 
    598     /* adjust camera position */
    599 
    600     camera->tic++;
    601     if (camera->tic < CAMMOVESPEED)
    602     {
    603         cameratarget->x = cameratarget->x + camera->slopex;
    604         cameratarget->y = cameratarget->y + camera->slopey;
    605         cameratarget->z = cameratarget->z + camera->slopez;
    606         return;
    607     }
    608 
    609     /* jump to next camera spot */
    610     for(mo = mobjhead.next; mo != &mobjhead; mo = mo->next)
    611     {
    612         if(camera->current != mo->tid)
    613             continue; /* must match tid */
    614 
    615         if(mo->type != MT_CAMERA)
    616             continue; /* not a camera */
    617 
    618         camera->slopex = (mo->x - cameratarget->x) / CAMMOVESPEED;
    619         camera->slopey = (mo->y - cameratarget->y) / CAMMOVESPEED;
    620         camera->slopez = (mo->z - cameratarget->z) / CAMMOVESPEED;
    621 
    622         camera->tic = 0;
    623         camera->current++;
    624         return;
    625     }
    626 }
    627 
    628 void P_SetMovingCamera(line_t *line) // 8000F2F8
    629 {
    630     movecamera_t *camera;
    631     mobj_t *mo;
    632 
    633     camera = Z_Malloc (sizeof(*camera), PU_LEVSPEC, 0);
    634     P_AddThinker (&camera->thinker);
    635     camera->thinker.function = T_MoveCamera;
    636 
    637     for(mo = mobjhead.next; mo != &mobjhead; mo = mo->next)
    638     {
    639         if(mo->tid != line->tag)
    640             continue; /* not matching the tid */
    641 
    642         if(mo->type != MT_CAMERA)
    643             continue; /* not a camera */
    644 
    645         /* setup moving camera */
    646         camera->x = mo->x;
    647         camera->y = mo->y;
    648         camera->z = mo->z;
    649         camera->tic = CAMMOVESPEED;
    650         camera->current = mo->tid + 1;
    651 
    652         /* set camera target */
    653         mo->angle = cameratarget->angle;
    654         mo->x = cameratarget->x;
    655         mo->y = cameratarget->y;
    656         cameratarget = mo;
    657         return;
    658     }
    659 }
    660 
    661 void P_RefreshBrightness(void) // 8000f410
    662 {
    663     int factor;
    664 
    665     factor = brightness + 100;
    666     if (factor < infraredFactor) {
    667         factor = infraredFactor;
    668     }
    669 
    670     P_SetLightFactor(factor);
    671 }
    672 
    673 extern maplights_t *maplights;     // 800A5EA4
    674 
    675 void P_SetLightFactor(int lightfactor) // 8000F458
    676 {
    677     register u32 fpstat, fpstatset;
    678 
    679     float l_flt;
    680     light_t *light;
    681     maplights_t *maplight;
    682     int base_r, base_g, base_b;
    683     int r, g, b;
    684     int h, s, v;
    685     int factor;
    686     int i;
    687 
    688     maplight = maplights;
    689     light = lights;
    690     for(i = 0; i < numlights; i++)
    691     {
    692         if (i > 255)
    693         {
    694             LightGetHSV(maplight->r, maplight->g, maplight->b, &h, &s, &v);
    695             maplight++;
    696             factor = v;
    697         }
    698         else
    699         {
    700             factor = i;
    701         }
    702 
    703         // fetch the current floating-point control/status register
    704         fpstat = __osGetFpcCsr();
    705         // enable round to negative infinity for floating point
    706         fpstatset = (fpstat | FPCSR_RM_RM) ^ 2;
    707         // _Disable_ unimplemented operation exception for floating point.
    708         __osSetFpcCsr(fpstatset);
    709 
    710         l_flt = (float)factor * ((float)lightfactor / 100.0);
    711 
    712         v = (int)l_flt;
    713         if (v > 255) {
    714             v = 255;
    715         }
    716 
    717         if (i > 255)
    718         {
    719             LightGetRGB(h, s, v, &r, &g, &b);
    720             base_r = r;
    721             base_g = g;
    722             base_b = b;
    723             /*base_r = maplight->r;
    724             base_g = maplight->g;
    725             base_b = maplight->b;
    726             maplight++;*/
    727         }
    728         else
    729         {
    730             base_r = v;
    731             base_g = v;
    732             base_b = v;
    733 
    734            /* base_r = i;
    735             base_g = i;
    736             base_b = i;*/
    737         }
    738 
    739         // [GEC] New Cheat Codes
    740         if (players[0].cheats & CF_FULLBRIGHT)
    741         {
    742             base_r = 255;
    743             base_g = 255;
    744             base_b = 255;
    745         }
    746         else if (players[0].cheats & CF_NOCOLORS)
    747         {
    748             base_r = v & 255;
    749             base_g = v & 255;
    750             base_b = v & 255;
    751         }
    752 
    753         light->rgba = PACKRGBA(base_r, base_g, base_b, 255);
    754         light++;
    755     }
    756 }
    757 
    758 void T_FadeInBrightness(fadebright_t *fb) // 8000f610
    759 {
    760     fb->factor += 2;
    761     if (fb->factor >= (brightness + 100))
    762     {
    763         fb->factor = (brightness + 100);
    764         P_RemoveThinker(&fb->thinker);
    765     }
    766 
    767     P_SetLightFactor(fb->factor);
    768 }
    769 
    770 int P_ModifyMobjFlags(int tid, int flags) // 8000F674
    771 {
    772     mobj_t *mo;
    773     int ok;
    774 
    775     ok = 0;
    776     for(mo = mobjhead.next; mo != &mobjhead; mo = mo->next)
    777     {
    778         if(mo->tid != tid)
    779             continue; /* not matching the tid */
    780 
    781         ok = 1;
    782         mo->flags &= ~flags;
    783     }
    784 
    785     return ok;
    786 }
    787 
    788 int P_AlertTaggedMobj(int tid, mobj_t *activator) // 8000F6C4
    789 {
    790     mobj_t  *mo;
    791     state_t *st;
    792     int     ok;
    793 
    794     ok = 0;
    795     for(mo = mobjhead.next; mo != &mobjhead; mo = mo->next)
    796     {
    797         if(mo->tid != tid)
    798             continue; /* not matching the tid */
    799 
    800         if(mo->info->seestate == S_000)
    801             continue;
    802 
    803         mo->threshold = 0;
    804         mo->target = activator;
    805         ok = 1;
    806 
    807         st = &states[mo->info->seestate];
    808 
    809         mo->state       = st;
    810         mo->tics        = st->tics;
    811         mo->sprite      = st->sprite;
    812         mo->frame       = st->frame;
    813     }
    814 
    815     return ok;
    816 }
    817 
    818 void T_MobjExplode(mobjexp_t *exp) // 8000F76C
    819 {
    820     fixed_t x;
    821     fixed_t y;
    822     fixed_t z;
    823     mobj_t *mo;
    824 
    825     if((--exp->delay) <= 0)
    826     {
    827         exp->delay = exp->delaydefault;
    828 
    829         x = (((P_Random() - P_Random()) << 14) + exp->mobj->x);
    830         y = (((P_Random() - P_Random()) << 14) + exp->mobj->y);
    831         z = (((P_Random() - P_Random()) << 14) + exp->mobj->z);
    832 
    833         mo = P_SpawnMobj(x, y, z + (exp->mobj->info->height >> 1), MT_EXPLOSION2);
    834 
    835         if((exp->lifetime & 1))
    836             S_StartSound(mo, sfx_explode);
    837 
    838         if((--exp->lifetime) == 0)
    839         {
    840             P_RemoveThinker(&exp->thinker);
    841         }
    842     }
    843 }