1 // Emacs style mode select   -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: p_heretic.c 1451 2019-08-03 07:02:00Z wesleyjohnson $
5 //
6 // Copyright (C) 1993-1996 by Raven Software, Corp.
7 // Portions Copyright (C) 1998-2000 by DooM Legacy Team.
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 //
20 // $Log: p_heretic.c,v $
21 // Revision 1.7  2001/07/16 22:35:41  bpereira
22 // - fixed crash of e3m8 in heretic
23 // - fixed crosshair not drawed bug
24 //
25 // Revision 1.6  2001/05/27 13:42:47  bpereira
26 // Revision 1.5  2001/03/30 17:12:50  bpereira
27 // Revision 1.4  2001/02/24 13:35:20  bpereira
28 // Revision 1.3  2001/02/10 13:20:55  hurdler
29 // update license
30 //
31 //
32 //
33 // DESCRIPTION:
34 //    Heretic sound and other specifics.
35 //
36 //-----------------------------------------------------------------------------
37 
38 #include "doomincl.h"
39 #include "g_game.h"
40 #include "p_local.h"
41 #include "r_main.h"
42 #include "r_state.h"
43 #include "s_sound.h"
44 #include "m_random.h"
45 #include "dstrings.h"
46 
47 //---------------------------------------------------------------------------
48 //
49 // PROC A_ContMobjSound
50 //
51 //---------------------------------------------------------------------------
52 
A_ContMobjSound(mobj_t * actor)53 void A_ContMobjSound(mobj_t *actor)
54 {
55     switch(actor->type)
56     {
57      case MT_KNIGHTAXE:
58         S_StartObjSound(actor, sfx_kgtatk);
59         break;
60      case MT_MUMMYFX1:
61         S_StartObjSound(actor, sfx_mumhed);
62         break;
63      default:
64         break;
65     }
66 }
67 
68 //----------------------------------------------------------------------------
69 //
70 // FUNC P_FaceMobj
71 //
72 // Returns 1 if 'source' needs to turn clockwise, or 0 if 'source' needs
73 // to turn counter clockwise.  'delta' is set to the amount 'source'
74 // needs to turn.
75 //
76 //----------------------------------------------------------------------------
P_FaceMobj(mobj_t * source,mobj_t * target,angle_t * delta)77 int P_FaceMobj(mobj_t *source, mobj_t *target, angle_t *delta)
78 {
79     angle_t angle1, angle2, diff;
80 
81     angle1 = source->angle;
82     angle2 = R_PointToAngle2(source->x, source->y, target->x, target->y);
83     if(angle2 > angle1)
84     {
85         diff = angle2 - angle1;
86         if(diff > ANG180)
87         {
88             *delta = ANGLE_MAX - diff;
89             return 0;
90         }
91         else
92         {
93             *delta = diff;
94             return 1;
95         }
96     }
97     else
98     {
99         diff = angle1 - angle2;
100         if(diff > ANG180)
101         {
102             *delta = ANGLE_MAX - diff;
103             return 1;
104         }
105         else
106         {
107             *delta = diff;
108             return 0;
109         }
110     }
111 }
112 
113 //----------------------------------------------------------------------------
114 //
115 // FUNC P_SeekerMissile
116 //
117 // The missile tracer field must be mobj_t *target.  Returns true if
118 // target was tracked, false if not.
119 //
120 //----------------------------------------------------------------------------
121 
P_SeekerMissile(mobj_t * actor,angle_t thresh,angle_t turnMax)122 boolean P_SeekerMissile(mobj_t *actor, angle_t thresh, angle_t turnMax)
123 {
124     int dir;
125     int dist;
126     angle_t delta;
127     mobj_t *target;
128 
129     target = actor->tracer;
130     if(target == NULL)
131     {
132         return false;
133     }
134     if(!(target->flags&MF_SHOOTABLE))
135     { // Target died
136         actor->tracer = 0;
137         return false;
138     }
139     dir = P_FaceMobj(actor, target, &delta);
140     if(delta > thresh)
141     {
142         delta >>= 1;
143         if(delta > turnMax)
144         {
145             delta = turnMax;
146         }
147     }
148     if(dir)
149     { // Turn clockwise
150         actor->angle += delta;
151     }
152     else
153     { // Turn counter clockwise
154         actor->angle -= delta;
155     }
156     int angf = ANGLE_TO_FINE(actor->angle);
157     actor->momx = FixedMul(actor->info->speed, finecosine[angf]);
158     actor->momy = FixedMul(actor->info->speed, finesine[angf]);
159     if(actor->z+actor->height < target->z ||
160        target->z+target->height < actor->z)
161     { // Need to seek vertically
162        dist = P_AproxDistance(target->x-actor->x, target->y-actor->y);
163        dist = dist/actor->info->speed;
164        if(dist < 1)
165           dist = 1;
166        actor->momz = (target->z+(target->height>>1)
167                       -(actor->z+(actor->height>>1)))/dist;
168     }
169     return true;
170 }
171 
172 //---------------------------------------------------------------------------
173 //
174 // FUNC P_SpawnMissileAngle
175 //
176 // Returns NULL if the missile exploded immediately, otherwise returns
177 // a mobj_t pointer to the missile.
178 //
179 //---------------------------------------------------------------------------
180 
P_SpawnMissileAngle(mobj_t * source,mobjtype_t type,angle_t angle,fixed_t momz)181 mobj_t *P_SpawnMissileAngle(mobj_t *source, mobjtype_t type,
182         angle_t angle, fixed_t momz)
183 {
184     fixed_t z;
185     mobj_t *mo;
186 
187     switch(type)
188     {
189      case MT_MNTRFX1: // Minotaur swing attack missile
190         z = source->z+40*FRACUNIT;
191         break;
192      case MT_MNTRFX2: // Minotaur floor fire missile
193         z = ONFLOORZ;
194         break;
195      case MT_SRCRFX1: // Sorcerer Demon fireball
196         z = source->z+48*FRACUNIT;
197         break;
198      default:
199         z = source->z+32*FRACUNIT;
200         break;
201     }
202     if(source->flags2&MF2_FEETARECLIPPED)
203     {
204         z -= FOOTCLIPSIZE;
205     }
206     mo = P_SpawnMobj(source->x, source->y, z, type);
207     if(mo->info->seesound)
208     {
209         S_StartObjSound(mo, mo->info->seesound);
210     }
211     mo->target = source; // Originator
212     mo->angle = angle;
213     // This one spot does not pull common expressions well, explicit is smaller.
214     int angf = ANGLE_TO_FINE( angle );
215     fixed_t speed = mo->info->speed;
216     mo->momx = FixedMul(speed, finecosine[angf]);
217     mo->momy = FixedMul(speed, finesine[angf]);
218     mo->momz = momz;
219     return (P_CheckMissileSpawn(mo) ? mo : NULL);
220 }
221 
222 
223 extern int GetWeaponAmmo[];
224 extern byte cheat_mus_seq[];
225 extern byte cheat_choppers_seq[];
226 extern byte cheat_god_seq[];
227 extern byte cheat_ammo_seq[];
228 extern byte cheat_ammonokey_seq[];
229 extern byte cheat_noclip_seq[];
230 extern byte cheat_commercial_noclip_seq[];
231 extern byte cheat_powerup_seq[7][10];
232 extern byte cheat_clev_seq[];
233 extern byte cheat_mypos_seq[];
234 extern byte cheat_amap_seq[];
235 
236 
237 // [WDJ] Reversible Heretic/Doom info table installation.
238 typedef struct {
239   uint16_t  doomednum;
240   uint16_t  doom_mt;
241   uint16_t  heretic_mt;
242 } doomednum_install_t;
243 
244 // Order is not important.  Only needs to include those doomednum that conflict.
245 static const doomednum_install_t  doomednum_install_table[] = {
246   {  7, MT_SPIDER, MT_SORCERER1 },  // SORCERER  (monster)
247   {  9, MT_SHOTGUY, MT_MINOTAUR },    // MINOTAUR  (monster)
248   { 16, MT_CYBORG, MT_AMMACEHEFTY },  // MACE BALL STACK (ammo M mace)
249   { 64, MT_VILE, MT_HKNIGHT },       // KNIGHT  (monster undead)
250   { 65, MT_CHAINGUY, MT_KNIGHTGHOST },  // KNIGHT GHOST  (monster undead)
251   { 66, MT_UNDEAD, MT_IMP },         // IMP (monster flying)
252   { 68, MT_BABY, MT_MUMMY },  // MUMMY (monster)
253   { 69, MT_KNIGHT, MT_MUMMYGHOST },  // MUMMY GHOST  (monster)
254   { 82, MT_SUPERSHOTGUN, MT_HMISC3 },  // QUARTZ FLASK  (health)
255   { 83, MT_MEGA, MT_ARTIFLY },  // WINGS  (artifact)
256   { 84, MT_WOLFSS, MT_ARTIINVULNERABILITY },  // INVULNERABLE  (artifact invul)
257   { 87, MT_BOSSTARGET, MT_HMISC12 },  // VOLCANO SPEWER
258   { 2001, MT_SHOTGUN, MT_HMISC15 },  // CROSSBOW  (weapon)
259   { 2002, MT_CHAINGUN, MT_WMACE },  // MACE  (weapon)
260   { 2003, MT_ROCKETLAUNCH, MT_WPHOENIXROD },  // PHOENIX ROD  (weapon)
261   { 2004, MT_PLASMAGUN, MT_WSKULLROD },  // SKULL ROD, HELLSTAFF  (weapon)
262   { 2005, MT_SHAINSAW, MT_HMISC13 },  // GAUNTLETS  (weapon)
263   { 2035, MT_BARREL, MT_POD },  //  POD  (exploding)
264   {  5, MT_MISC4, MT_IMPLEADER },  // IMP LEADER (monster flying)
265   { 13, MT_MISC5, MT_AMMACEWIMPY },  // MACE BALL  (ammo S mace)
266   {  6, MT_MISC6, MT_HHEAD },  // HEAD  (monster)
267   { 39, MT_MISC7, MT_STALACTITESMALL },  // STALACTITE SMALL
268   { 38, MT_MISC8, MT_STALAGMITELARGE },  // STALAGMITE LARGE
269   { 40, MT_MISC9, MT_STALACTITELARGE },  // STALACTITE LARGE
270   { 17, MT_MISC21, MT_SKULLHANG70 },  // HANGING SKULL 70
271   {  8, MT_MISC24, MT_HMISC1 },  // BAG OF HOLDING (knapsack)
272   { 85, MT_MISC29, MT_ITEMSHIELD1 },  // SILVER SHIELD  (armor)
273   { 86, MT_MISC30, MT_ARTITOMEOFPOWER },  // TOME  (artifact)
274   { 30, MT_MISC32, MT_ARTIEGG },  // EGG  (artifact)
275   { 31, MT_MISC33, MT_ITEMSHIELD2 },  // SHIELD MEGA  (armor)
276   { 32, MT_MISC34, MT_ARTISUPERHEAL },  // SUPER HEAL  (artifact health)
277   { 33, MT_MISC35, MT_HMISC4 },  // TORCH  (artifact torch)
278   { 37, MT_MISC36, MT_STALAGMITESMALL },  // STALAGMITE SMALL
279   { 36, MT_MISC37, MT_ARTITELEPORT },  //  (artifact teleport)
280   { 41, MT_MISC38, MT_SOUNDWATERFALL },  // SOUND WATERFALL  (ambience sound)
281   { 42, MT_MISC39, MT_SOUNDWIND },  // SOUND WIND  (ambience sound)
282   { 43, MT_MISC40, MT_PODGENERATOR },  // POD GENERATOR
283   { 44, MT_MISC41, MT_HBARREL },  // BARREL
284   { 45, MT_MISC42, MT_MUMMYLEADER },  // MUMMY LEADER (monster)
285   { 46, MT_MISC43, MT_MUMMYLEADERGHOST },  // MUMMY LEADER GHOST  (monster)
286   { 55, MT_MISC44, MT_AMBLSRHEFTY },  // ENERGY ORB LARGE  (ammo M claw)
287   { 56, MT_MISC45, 0xFFFF  },  // heretic use it for monster spawn
288   { 47, MT_MISC47, MT_HMISC7 },  // PILLAR BROWN
289   { 48, MT_MISC48, MT_HMISC8 },  // MOSS 1
290   { 34, MT_MISC49, MT_HMISC5 },  // BOMB  (exploding timed)
291   { 35, MT_MISC50, MT_HMISC2 },  // MAP   (special)
292   { 49, MT_MISC51, MT_HMISC9 },  // MOSS 2
293   { 50, MT_MISC52, MT_HMISC10 },  // WALL TORCH  (torch)
294   { 51, MT_MISC53, MT_HMISC11 },  // HANGING CORPSE
295   { 52, MT_MISC54, MT_TELEGLITGEN2 },  // TELEPORT GLITTER GENERATOR 2
296   { 53, MT_MISC55, MT_HMISC14 },  // DRAGON CLAW  (weapon)
297   { 22, MT_MISC61, MT_AMPHRDWIMPY },  // FLAME ORB  (ammo S phoenix rod)
298   { 15, MT_MISC62, MT_WIZARD },  // WIZARD (monster floating)
299   { 18, MT_MISC63, MT_AMCBOWWIMPY },  // ETHEREAL ARROWS (ammo S crossbow)
300   { 21, MT_MISC64, MT_AMSKRDHEFTY },  // GREATER RUNES  (ammo M skull rod)
301   { 23, MT_MISC65, MT_AMPHRDHEFTY },  // FLAME ORB LARGE  (ammo M phoenix rod)
302   { 20, MT_MISC66, MT_AMSKRDWIMPY },  // LESSER RUNES  (ammo S skull rod)
303   { 19, MT_MISC67, MT_AMCBOWHEFTY },  // ETHEREAL ARROWS QUIVER  (ammo M crossbow)
304   { 10, MT_MISC68, MT_AMGWNDWIMPY },  // WAND CRYSTAL (ammo S staff)
305   { 12, MT_MISC69, MT_AMGWNDHEFTY },  // WAND CRYSTAL LARGE (ammo M staff)
306   { 28, MT_MISC70, MT_CHANDELIER },  // CHANDELIER
307   { 24, MT_MISC71, MT_SKULLHANG60 },  // HANGING SKULL 60
308   { 27, MT_MISC72, MT_SERPTORCH },  // SERPENT TORCH (torch)
309   { 29, MT_MISC73, MT_SMALLPILLAR },  // PILLAR SMALL
310   { 25, MT_MISC74, MT_SKULLHANG45 },  // HANGING SKULL 45
311   { 26, MT_MISC75, MT_SKULLHANG35 },  // HANGING SKULL 35
312   { 54, MT_MISC76, MT_AMBLSRWIMPY },  //  CLAW ORB  (ammo S claw)
313   { 70, MT_MISC77, MT_BEAST },  // BEAST (monster)
314   { 73, MT_MISC78, MT_AKYY },  // GREEN KEY  (key)
315   { 74, MT_MISC79, MT_TELEGLITGEN },  // TELEPORT GLITTER GENERATOR 1
316   { 75, MT_MISC80, MT_ARTIINVISIBILITY },  // INVISIBLE  (artifact invis)
317   { 76, MT_MISC81, MT_HMISC6 },  // FIRE BRAZIER (torch)
318   { 79, MT_MISC84, MT_BKYY },  // BLUE KEY  (key)
319   { 80, MT_MISC85, MT_CKEY },  // YELLOW KEY  (key)
320   { 81, MT_MISC86, MT_HMISC0 },  // CRYSTAL VIAL  (health)
321   { 0xFFFF, 0xFFFF, 0xFFFF },  // END
322 };
323 
324 #if 0
325 void  doomednum_check( byte heretic_check )
326 {
327     doomednum_install_t * ii;
328     for( ii = & doomednum_install_table[0]; ii->doomednum < 0xFFFF; ii++ )
329     {
330         uint16_t mt = ( heretic_check )?  ii->heretic_mt : ii->doom_mt;
331         if( mt < NUMMOBJTYPES )
332           if( mobjinfo[ mt ].doomednum != ii->doomednum )
333             printf( "MOBJINFO[%i].doomednum=%i,  TABLE doomednum=%i, doom_mt=%i, heretic_mt=%i\n", mt, mobjinfo[mt].doomednum, ii->doomednum, ii->doom_mt, ii->heretic_mt );
334     }
335 }
336 #endif
337 
doomednum_install(byte set_heretic)338 void  doomednum_install( byte set_heretic )
339 {
340     const doomednum_install_t * ii;
341     uint16_t  cancel_mt, set_mt;
342     for( ii = & doomednum_install_table[0]; ii->doomednum < 0xFFFF; ii++ )
343     {
344         cancel_mt = ( set_heretic )?  ii->doom_mt : ii->heretic_mt;
345         set_mt = ( set_heretic )?  ii->heretic_mt : ii->doom_mt;
346         if( cancel_mt < NUMMOBJTYPES )
347         {
348             if( mobjinfo[ cancel_mt ].doomednum == ii->doomednum )
349                 mobjinfo[ cancel_mt ].doomednum = -1;
350         }
351         if( set_mt < NUMMOBJTYPES )
352             mobjinfo[ set_mt ].doomednum = ii->doomednum;
353     }
354 }
355 
356 
357 // [WDJ] Reversible Heretic/Doom Ammo table installation.
358 typedef struct {
359   uint16_t  max_val;
360   byte      clip_val;
361 } ammo_install_t;
362 
363 // Index by ammotype_t
364 static const ammo_install_t  heretic_ammo_table[NUMAMMO] = {
365    { 100,  5 }, // am_goldwand, clip used in deathmatch 1 & 3 mul by 5 (P_GiveWeapon)
366    {  50,  2 }, // am_crossbow
367    { 200,  6 }, // am_blaster
368    { 200, 10 }, // am_skullrod
369    {  20,  1 }, // am_phoenixrod
370    { 150, 10 }, // am_mace
371 };
372 
373 // Index by ammotype_t
374 static const ammo_install_t  doom_ammo_table[NUMAMMO] = {
375    { 200, 10 }, // am_clip
376    {  50,  4 }, // am_shell
377    { 300, 20 }, // am_cell
378    {  50,  1 }, // am_misl
379    {   0,  0 },
380    {   0,  0 },
381 };
382 
383 // Index by weapontype_t
384 static const byte  heretic_weapon_ammo_table[NUMWEAPONS] = {
385    0, // wp_staff
386   25, // wp_goldwand
387   10, // wp_crossbow
388   30, // wp_blaster
389   50, // wp_skullrod
390    2, // wp_phoenixrod
391   50, // wp_mace
392    0, // wp_gauntlets
393    0, // wp_beak
394 };
395 
396 // Index by weapontype_t
397 static const byte  doom_weapon_ammo_table[NUMWEAPONS] = {
398    0, // wp_fist
399   20, // wp_pistol
400    8, // wp_shotgun
401   20, // wp_chaingun
402    2, // wp_missle
403   40, // wp_plasma
404   40, // wp_bfg
405    0, // wp_chainsaw
406    8, // wp_supershotgun
407 };
408 
409 
410 // [WDJ] Reversible Heretic/Doom Sfx table installation.
411 typedef struct {
412     sfxid_t  sfxid;  // sfxenum_e
413     char *  name;
414     byte     priority;
415 } sfx_install_t;
416 
417 static const sfx_install_t  heretic_sfx_table[] = {
418   { sfx_oof, "plroof", 32 },
419   { sfx_swtchn, "switch", 40 },
420   { sfx_swtchx, "switch", 40 },
421   { sfx_telept, "telept", 50 },
422   { sfx_sawup, "gntact", 32 },  // gauntlets
423   { sfx_pistol, "keyup", 64 },  // for the menu
424   { sfx_tink, "chat", 100 },
425   { sfx_itmbk, "respawn", 10 },
426   { 0xFFFF, NULL, 0 }
427 };
428 
429 // To undo heretic install.
430 static const sfx_install_t  doom_sfx_table[] = {
431   { sfx_oof, "oof\0\0\0", 96 },
432   { sfx_swtchn, "swtchn", 78 },
433   { sfx_swtchx, "swtchx", 78 },
434   { sfx_telept, "telept", 32 },
435   { sfx_sawup, "sawup\0", 64 },  // chainsaw
436   { sfx_pistol, "pistol", 64 },  // pistol
437   { sfx_tink, "tink\0\0", 60 },
438   { sfx_itmbk, "itmbk\0", 100 },
439   { 0xFFFF, NULL, 0 }
440 };
441 
442 
443 // [WDJ] Reversible Heretic/Doom text table installation.
444 typedef struct {
445     uint16_t  textid;
446     char *    text;
447 } text_install_t;
448 
449 static const text_install_t  heretic_text_table[] = {
450   { PD_BLUEK_NUM,   "YOU NEED A BLUE KEY TO OPEN THIS DOOR" },
451   { PD_YELLOWK_NUM, "YOU NEED A YELLOW KEY TO OPEN THIS DOOR" },
452   { PD_REDK_NUM,    "YOU NEED A GREEN KEY TO OPEN THIS DOOR" },
453   { GOTBLUECARD_NUM, "BLUE KEY" },
454   { GOTYELWCARD_NUM, "YELLOW KEY" },
455   { GOTREDCARD_NUM,  "GREEN KEY" },
456   { GOTARMOR_NUM, "SILVER SHIELD" },
457   { GOTMEGA_NUM,  "ENCHANTED SHIELD" },
458   { GOTSTIM_NUM,  "CRYSTAL VIAL" },
459   { GOTMAP_NUM,  "MAP SCROLL" },
460   { 0xFFFF, NULL }
461 };
462 
463 static const text_install_t  doom_text_table[] = {
464   { PD_BLUEK_NUM,   "You need a blue key to open this door" },
465   { PD_YELLOWK_NUM, "You need a yellow key to open this door" },
466   { PD_REDK_NUM,    "You need a red key to open this door" },
467   { GOTBLUECARD_NUM, "Picked up a blue keycard." },
468   { GOTYELWCARD_NUM, "Picked up a yellow keycard." },
469   { GOTREDCARD_NUM,  "Picked up a red keycard." },
470   { GOTARMOR_NUM, "Picked up the armor." },
471   { GOTMEGA_NUM,  "Picked up the MegaArmor!" },
472   { GOTSTIM_NUM,  "Picked up a stimpack." },
473   { GOTMAP_NUM,  "Computer Area Map" },
474   { 0xFFFF, NULL }
475 };
476 
sfx_ammo_text_install(byte set_heretic)477 void  sfx_ammo_text_install( byte set_heretic )
478 {
479     const sfx_install_t * st = doom_sfx_table;
480     const ammo_install_t * aat = doom_ammo_table;
481     const byte * wat = doom_weapon_ammo_table;
482     const text_install_t * tt = doom_text_table;
483     int ai;
484 
485     // SFX
486     if( set_heretic )
487     {
488         ceilmovesound = sfx_dormov;
489         doorclosesound = sfx_doropn;
490 
491         st = heretic_sfx_table;
492         aat = heretic_ammo_table;
493         wat = heretic_weapon_ammo_table;
494         tt = heretic_text_table;
495     }
496     else
497     {
498         ceilmovesound = sfx_stnmov;
499         doorclosesound = sfx_dorcls;
500     }
501 
502     // SFX
503     for( ; st->sfxid < NUMSFX; st++ )
504     {
505         S_sfx[st->sfxid].priority = st->priority;
506         if( st->name )
507             S_sfx[st->sfxid].name = st->name;
508     }
509 
510 
511     // AMMO
512     for( ai = 0; ai < NUMAMMO; ai++ )  // index ammotype_t
513     {
514         maxammo[ ai ]  = aat[ai].max_val;
515         clipammo[ ai ] = aat[ai].clip_val;
516     }
517 
518     for( ai = 0; ai < NUMWEAPONS; ai++ )  // index weapontype_t
519     {
520         GetWeaponAmmo[ai] = wat[ai];
521     }
522 
523     // TEXT
524     for( ; tt->textid < NUMTEXT ; tt++ )
525     {
526         text[tt->textid] = tt->text;
527     }
528 }
529 
530 
531 
Heretic_PatchEngine(void)532 void Heretic_PatchEngine(void)
533 {
534     // we can put such thinks in a dehacked lump, maybe for later
535     mobjinfo[MT_TFOG].spawnstate = S_HTFOG1;
536     sprnames[SPR_BLUD] = "BLOD";
537 
538     S_music[mus_inter].name = "MUS_INTR";
539 
540     sfx_ammo_text_install( 1 ); // install heretic sfx, ammo
541 
542     // conflicting number for doomednum
543     // so disable doom mobjs and enable heretic's one
544     doomednum_install( 1 );  // install heretic doomednum
545 }
546 
547 mobj_t LavaInflictor;
548 
549 //----------------------------------------------------------------------------
550 //
551 // PROC P_Init_Lava
552 //
553 //----------------------------------------------------------------------------
554 
P_Init_Lava(void)555 void P_Init_Lava(void)
556 {
557     memset(&LavaInflictor, 0, sizeof(mobj_t));
558     LavaInflictor.type = MT_PHOENIXFX2;
559     LavaInflictor.flags2 = MF2_FIREDAMAGE|MF2_NODMGTHRUST;
560 }
561 
562 //----------------------------------------------------------------------------
563 //
564 // PROC P_HerePlayerInSpecialSector
565 //
566 // Called every tic frame that the player origin is in a special sector.
567 //
568 //----------------------------------------------------------------------------
569 
P_HerePlayerInSpecialSector(player_t * player)570 void P_HerePlayerInSpecialSector(player_t *player)
571 {
572     sector_t *sector;
573     static int pushTab[5] = {
574         2048*5,
575         2048*10,
576         2048*25,
577         2048*30,
578         2048*35
579     };
580 
581     sector = player->mo->subsector->sector;
582     // Player is not touching the floor
583     if( player->mo->z != sector->floorheight )
584         return;
585 
586     switch(sector->special)
587     {
588     case 7: // Damage_Sludge
589         if(!(leveltime&31))
590         {
591             P_DamageMobj(player->mo, NULL, NULL, 4);
592         }
593         break;
594     case 5: // Damage_LavaWimpy
595         if(!(leveltime&15))
596         {
597             P_DamageMobj(player->mo, &LavaInflictor, NULL, 5);
598             P_HitFloor(player->mo);
599         }
600         break;
601     case 16: // Damage_LavaHefty
602         if(!(leveltime&15))
603         {
604             P_DamageMobj(player->mo, &LavaInflictor, NULL, 8);
605             P_HitFloor(player->mo);
606         }
607         break;
608     case 4: // Scroll_EastLavaDamage
609         P_Thrust(player, 0, 2048*28);
610         if(!(leveltime&15))
611         {
612             P_DamageMobj(player->mo, &LavaInflictor, NULL, 5);
613             P_HitFloor(player->mo);
614         }
615         break;
616     case 9: // SecretArea
617         player->secretcount++;
618         sector->special = 0;
619         break;
620     case 11: // Exit_SuperDamage (DOOM E1M8 finale)
621              /*
622              player->cheats &= ~CF_GODMODE;
623              if(!(leveltime&0x1f))
624              {
625              P_DamageMobj(player->mo, NULL, NULL, 20);
626              }
627              if(player->health <= 10)
628              {
629              G_ExitLevel();
630              }
631         */
632         break;
633 
634     case 25: case 26: case 27: case 28: case 29: // Scroll_North
635         P_Thrust(player, ANG90, pushTab[sector->special-25]);
636         break;
637     case 20: case 21: case 22: case 23: case 24: // Scroll_East
638         P_Thrust(player, 0, pushTab[sector->special-20]);
639         break;
640     case 30: case 31: case 32: case 33: case 34: // Scroll_South
641         P_Thrust(player, ANG270, pushTab[sector->special-30]);
642         break;
643     case 35: case 36: case 37: case 38: case 39: // Scroll_West
644         P_Thrust(player, ANG180, pushTab[sector->special-35]);
645         break;
646 
647     case 40: case 41: case 42: case 43: case 44: case 45:
648     case 46: case 47: case 48: case 49: case 50: case 51:
649         // Wind specials are handled in (P_mobj):P_XYMovement
650         break;
651 
652     case 15: // Friction_Low
653         // Only used in (P_mobj):P_XYMovement and (P_user):P_Thrust
654         break;
655 
656     default:
657         I_SoftError( "P_PlayerInSpecialSector: "
658                     "unknown special %i\n", sector->special);
659     }
660 }
661 
662 //---------------------------------------------------------------------------
663 //
664 // FUNC P_GetThingFloorType
665 //
666 //---------------------------------------------------------------------------
P_GetThingFloorType(mobj_t * thing)667 int P_GetThingFloorType(mobj_t *thing)
668 {
669     return thing->subsector->sector->floortype;
670 }
671