2 //**************************************************************************
4 //** p_inter.c : Heretic 2 : Raven Software, Corp.
11 //**************************************************************************
19 int ArmorIncrement[NUMCLASSES][NUMARMOR] =
21 { 25*FRACUNIT, 20*FRACUNIT, 15*FRACUNIT, 5*FRACUNIT },
22 { 10*FRACUNIT, 25*FRACUNIT, 5*FRACUNIT, 20*FRACUNIT },
23 { 5*FRACUNIT, 15*FRACUNIT, 10*FRACUNIT, 25*FRACUNIT },
24 {20*FRACUNIT, 10*FRACUNIT, 25*FRACUNIT, 5*FRACUNIT },
28 int AutoArmorSave[NUMCLASSES] = { 15*FRACUNIT, 10*FRACUNIT, 5*FRACUNIT,
32 char *TextKeyMessages[] =
47 static void SetDormantArtifact(mobj_t *arti);
48 static void TryPickupArtifact(player_t *player, artitype_t artifactType,
50 static void TryPickupWeapon(player_t *player, pclass_t weaponClass,
51 weapontype_t weaponType, mobj_t *weapon, char *message);
52 static void TryPickupWeaponPiece(player_t *player, pclass_t matchClass,
53 int pieceValue, mobj_t *pieceMobj);
55 /* jim Linux needs this too */
57 #if defined(__NeXT__) || defined(__linux) || defined(__FreeBSD__)
58 extern void strupr(char *s);
61 //--------------------------------------------------------------------------
65 //--------------------------------------------------------------------------
67 void P_SetMessage(player_t *player, char *message, boolean ultmsg)
69 extern boolean messageson;
71 if((player->ultimateMessage || !messageson) && !ultmsg)
75 if(strlen(message) > 79)
77 memcpy(player->message, message, 80);
78 player->message[80] = 0;
82 strcpy(player->message, message);
84 strupr(player->message);
85 player->messageTics = MESSAGETICS;
86 player->yellowMessage = false;
89 player->ultimateMessage = true;
91 if(player == &players[consoleplayer])
93 BorderTopRefresh = true;
97 //==========================================================================
101 //==========================================================================
103 void P_SetYellowMessage(player_t *player, char *message, boolean ultmsg)
105 extern boolean messageson;
107 if((player->ultimateMessage || !messageson) && !ultmsg)
111 if(strlen(message) > 79)
113 memcpy(player->message, message, 80);
114 player->message[80] = 0;
118 strcpy(player->message, message);
120 player->messageTics = 5*MESSAGETICS; // Bold messages last longer
121 player->yellowMessage = true;
124 player->ultimateMessage = true;
126 if(player == &players[consoleplayer])
128 BorderTopRefresh = true;
132 //==========================================================================
136 //==========================================================================
138 void P_ClearMessage(player_t *player)
140 player->messageTics = 0;
141 if(player == &players[consoleplayer])
143 BorderTopRefresh = true;
147 //----------------------------------------------------------------------------
149 // PROC P_HideSpecialThing
151 //----------------------------------------------------------------------------
153 void P_HideSpecialThing(mobj_t *thing)
155 thing->flags &= ~MF_SPECIAL;
156 thing->flags2 |= MF2_DONTDRAW;
157 P_SetMobjState(thing, S_HIDESPECIAL1);
160 //--------------------------------------------------------------------------
164 // Returns true if the player accepted the mana, false if it was
165 // refused (player has MAX_MANA).
167 //--------------------------------------------------------------------------
169 boolean P_GiveMana(player_t *player, manatype_t mana, int count)
172 //weapontype_t changeWeapon;
174 if(mana == MANA_NONE || mana == MANA_BOTH)
178 if(mana < 0 || mana > NUMMANA)
180 I_Error("P_GiveMana: bad type %i", mana);
182 if(player->mana[mana] == MAX_MANA)
186 if(gameskill == sk_baby || gameskill == sk_nightmare)
187 { // extra mana in baby mode and nightmare mode
190 prevMana = player->mana[mana];
192 player->mana[mana] += count;
193 if(player->mana[mana] > MAX_MANA)
195 player->mana[mana] = MAX_MANA;
197 if(player->class == PCLASS_FIGHTER && player->readyweapon == WP_SECOND
198 && mana == MANA_1 && prevMana <= 0)
200 P_SetPsprite(player, ps_weapon, S_FAXEREADY_G);
205 //==========================================================================
209 //==========================================================================
211 static void TryPickupWeapon(player_t *player, pclass_t weaponClass,
212 weapontype_t weaponType, mobj_t *weapon, char *message)
219 if(player->class != weaponClass
220 && player->class != PCLASS_ASS
222 { // Wrong class, but try to pick up for mana
223 if(netgame && !deathmatch)
224 { // Can't pick up weapons for other classes in coop netplay
227 if(weaponType == WP_SECOND)
229 if(!P_GiveMana(player, MANA_1, 25))
236 if(!P_GiveMana(player, MANA_2, 25))
242 else if(netgame && !deathmatch)
243 { // Cooperative net-game
244 if(player->weaponowned[weaponType])
248 player->weaponowned[weaponType] = true;
249 if(weaponType == WP_SECOND)
251 P_GiveMana(player, MANA_1, 25);
255 P_GiveMana(player, MANA_2, 25);
257 player->pendingweapon = weaponType;
261 { // Deathmatch or single player game
262 if(weaponType == WP_SECOND)
264 gaveMana = P_GiveMana(player, MANA_1, 25);
268 gaveMana = P_GiveMana(player, MANA_2, 25);
270 if(player->weaponowned[weaponType])
277 player->weaponowned[weaponType] = true;
278 if(weaponType > player->readyweapon)
279 { // Only switch to more powerful weapons
280 player->pendingweapon = weaponType;
283 if(!(gaveWeapon || gaveMana))
284 { // Player didn't need the weapon or any mana
289 P_SetMessage(player, message, false);
292 P_ExecuteLineSpecial(weapon->special, weapon->args,
293 NULL, 0, player->mo);
299 if(deathmatch && !(weapon->flags2&MF2_DROPPED))
301 P_HideSpecialThing(weapon);
305 P_RemoveMobj(weapon);
309 player->bonuscount += BONUSADD;
310 if(player == &players[consoleplayer])
312 S_StartSound(NULL, SFX_PICKUP_WEAPON);
313 SB_PaletteFlash(false);
317 //--------------------------------------------------------------------------
321 // Returns true if the weapon or its mana was accepted.
323 //--------------------------------------------------------------------------
326 boolean P_GiveWeapon(player_t *player, pclass_t class, weapontype_t weapon)
331 if(player->class != class)
332 { // player cannot use this weapon, take it anyway, and get mana
333 if(netgame && !deathmatch)
334 { // Can't pick up weapons for other classes in coop netplay
337 if(weapon == WP_SECOND)
339 return P_GiveMana(player, MANA_1, 25);
343 return P_GiveMana(player, MANA_2, 25);
346 if(netgame && !deathmatch)
347 { // Cooperative net-game
348 if(player->weaponowned[weapon])
352 player->bonuscount += BONUSADD;
353 player->weaponowned[weapon] = true;
354 if(weapon == WP_SECOND)
356 P_GiveMana(player, MANA_1, 25);
360 P_GiveMana(player, MANA_2, 25);
362 player->pendingweapon = weapon;
363 if(player == &players[consoleplayer])
365 S_StartSound(NULL, SFX_PICKUP_WEAPON);
369 if(weapon == WP_SECOND)
371 gaveMana = P_GiveMana(player, MANA_1, 25);
375 gaveMana = P_GiveMana(player, MANA_2, 25);
377 if(player->weaponowned[weapon])
384 player->weaponowned[weapon] = true;
385 if(weapon > player->readyweapon)
386 { // Only switch to more powerful weapons
387 player->pendingweapon = weapon;
390 return(gaveWeapon || gaveMana);
394 //===========================================================================
398 //===========================================================================
401 boolean P_GiveWeaponPiece(player_t *player, pclass_t class, int piece)
403 P_GiveMana(player, MANA_1, 20);
404 P_GiveMana(player, MANA_2, 20);
405 if(player->class != class)
409 else if(player->pieces&piece)
410 { // player already has that weapon piece
413 player->pieces |= piece;
414 if(player->pieces == 7)
415 { // player has built the fourth weapon!
416 P_GiveWeapon(player, class, WP_FOURTH);
417 S_StartSound(player->mo, SFX_WEAPON_BUILD);
423 //==========================================================================
425 // TryPickupWeaponPiece
427 //==========================================================================
429 static void TryPickupWeaponPiece(player_t *player, pclass_t matchClass,
430 int pieceValue, mobj_t *pieceMobj)
433 boolean checkAssembled;
436 static char *fourthWeaponText[] =
443 static char *weaponPieceText[] =
446 TXT_WRAITHVERGE_PIECE,
447 TXT_BLOODSCOURGE_PIECE,
450 static int pieceValueTrans[] =
453 WPIECE1|WPIECE2|WPIECE3, // WPIECE1 (1)
454 WPIECE2|WPIECE3, // WPIECE2 (2)
456 WPIECE3 // WPIECE3 (4)
460 checkAssembled = true;
462 // Allow assassin to pick up any weapons
463 if(player->class != matchClass && player->class != PCLASS_ASS)
464 { // Wrong class, but try to pick up for mana
465 if(netgame && !deathmatch)
466 { // Can't pick up wrong-class weapons in coop netplay
469 checkAssembled = false;
470 gaveMana = P_GiveMana(player, MANA_1, 20)+
471 P_GiveMana(player, MANA_2, 20);
473 { // Didn't need the mana, so don't pick it up
477 else if(netgame && !deathmatch)
478 { // Cooperative net-game
479 if(player->pieces&pieceValue)
480 { // Already has the piece
483 pieceValue = pieceValueTrans[pieceValue];
484 P_GiveMana(player, MANA_1, 20);
485 P_GiveMana(player, MANA_2, 20);
489 { // Deathmatch or single player game
490 gaveMana = P_GiveMana(player, MANA_1, 20)+
491 P_GiveMana(player, MANA_2, 20);
492 if(player->pieces&pieceValue)
493 { // Already has the piece, check if mana needed
495 { // Didn't need the mana, so don't pick it up
498 checkAssembled = false;
502 // Pick up the weapon piece
503 if(pieceMobj->special)
505 P_ExecuteLineSpecial(pieceMobj->special, pieceMobj->args,
506 NULL, 0, player->mo);
507 pieceMobj->special = 0;
511 if(deathmatch && !(pieceMobj->flags2&MF2_DROPPED))
513 P_HideSpecialThing(pieceMobj);
517 P_RemoveMobj(pieceMobj);
520 player->bonuscount += BONUSADD;
521 if(player == &players[consoleplayer])
523 SB_PaletteFlash(false);
526 // Check if fourth weapon assembled
529 player->pieces |= pieceValue;
530 if(player->pieces == (WPIECE1|WPIECE2|WPIECE3))
533 player->weaponowned[WP_FOURTH] = true;
534 player->pendingweapon = WP_FOURTH;
540 P_SetMessage(player, fourthWeaponText[matchClass], false);
541 // Play the build-sound full volume for all players
542 S_StartSound(NULL, SFX_WEAPON_BUILD);
546 P_SetMessage(player, weaponPieceText[matchClass], false);
547 if(player == &players[consoleplayer])
549 S_StartSound(NULL, SFX_PICKUP_WEAPON);
554 //---------------------------------------------------------------------------
558 // Returns false if the body isn't needed at all.
560 //---------------------------------------------------------------------------
562 boolean P_GiveBody(player_t *player, int num)
567 if(player->morphTics)
569 max = MAXMORPHHEALTH;
571 if(player->health >= max)
575 player->health += num;
576 if(player->health > max)
578 player->health = max;
580 player->mo->health = player->health;
584 //---------------------------------------------------------------------------
588 // Returns false if the armor is worse than the current armor.
590 //---------------------------------------------------------------------------
592 boolean P_GiveArmor(player_t *player, armortype_t armortype, int amount)
597 extern int ArmorMax[NUMCLASSES];
601 hits = ArmorIncrement[player->class][armortype];
602 if(player->armorpoints[armortype] >= hits)
608 player->armorpoints[armortype] = hits;
613 hits = amount*5*FRACUNIT;
614 totalArmor = player->armorpoints[ARMOR_ARMOR]
615 +player->armorpoints[ARMOR_SHIELD]
616 +player->armorpoints[ARMOR_HELMET]
617 +player->armorpoints[ARMOR_AMULET]
618 +AutoArmorSave[player->class];
619 if(totalArmor < ArmorMax[player->class]*5*FRACUNIT)
621 player->armorpoints[armortype] += hits;
631 //---------------------------------------------------------------------------
635 //---------------------------------------------------------------------------
637 int P_GiveKey(player_t *player, keytype_t key)
639 if(player->keys&(1<<key))
643 player->bonuscount += BONUSADD;
644 player->keys |= 1<<key;
648 //---------------------------------------------------------------------------
652 // Returns true if power accepted.
654 //---------------------------------------------------------------------------
656 boolean P_GivePower(player_t *player, powertype_t power)
658 if(power == pw_invulnerability)
660 if(player->powers[power] > BLINKTHRESHOLD)
664 player->powers[power] = INVULNTICS;
665 player->mo->flags2 |= MF2_INVULNERABLE;
666 if(player->class == PCLASS_MAGE)
668 player->mo->flags2 |= MF2_REFLECTIVE;
672 if(power == pw_flight)
674 if(player->powers[power] > BLINKTHRESHOLD)
678 player->powers[power] = FLIGHTTICS;
679 player->mo->flags2 |= MF2_FLY;
680 player->mo->flags |= MF_NOGRAVITY;
681 if(player->mo->z <= player->mo->floorz)
683 player->flyheight = 10; // thrust the player in the air a bit
687 if(power == pw_infrared)
689 if(player->powers[power] > BLINKTHRESHOLD)
693 player->powers[power] = INFRATICS;
696 if(power == pw_speed)
698 if(player->powers[power] > BLINKTHRESHOLD)
702 player->powers[power] = SPEEDTICS;
705 if(power == pw_minotaur)
707 // Doesn't matter if already have power, renew ticker
708 player->powers[power] = MAULATORTICS;
712 if(power == pw_ironfeet)
714 player->powers[power] = IRONTICS;
717 if(power == pw_strength)
719 P_GiveBody(player, 100);
720 player->powers[power] = 1;
724 if(player->powers[power])
726 return(false); // already got it
728 player->powers[power] = 1;
732 //==========================================================================
736 //==========================================================================
738 static void TryPickupArtifact(player_t *player, artitype_t artifactType,
741 static char *artifactMessages[NUMARTIFACTS] =
744 TXT_ARTIINVULNERABILITY,
747 TXT_ARTIHEALINGRADIUS,
754 TXT_ARTITELEPORTOTHER,
762 TXT_ARTIPUZZGEMGREEN1,
763 TXT_ARTIPUZZGEMGREEN2,
764 TXT_ARTIPUZZGEMBLUE1,
765 TXT_ARTIPUZZGEMBLUE2,
772 TXT_ARTIPUZZGEAR, // All gear pickups use the same text
778 if(P_GiveArtifact(player, artifactType, artifact))
780 if(artifact->special)
782 P_ExecuteLineSpecial(artifact->special, artifact->args,
784 artifact->special = 0;
786 player->bonuscount += BONUSADD;
787 if(artifactType < arti_firstpuzzitem)
789 SetDormantArtifact(artifact);
790 S_StartSound(artifact, SFX_PICKUP_ARTIFACT);
791 P_SetMessage(player, artifactMessages[artifactType], false);
795 S_StartSound(NULL, SFX_PICKUP_ITEM);
796 P_SetMessage(player, artifactMessages[artifactType], true);
797 if(!netgame || deathmatch)
798 { // Remove puzzle items if not cooperative netplay
799 P_RemoveMobj(artifact);
805 //---------------------------------------------------------------------------
807 // FUNC P_GiveArtifact
809 // Returns true if artifact accepted.
811 //---------------------------------------------------------------------------
813 boolean P_GiveArtifact(player_t *player, artitype_t arti, mobj_t *mo)
817 boolean slidePointer;
819 slidePointer = false;
821 while(player->inventory[i].type != arti && i < player->inventorySlotNum)
825 if(i == player->inventorySlotNum)
827 if(arti < arti_firstpuzzitem)
830 while(player->inventory[i].type < arti_firstpuzzitem
831 && i < player->inventorySlotNum)
835 if(i != player->inventorySlotNum)
837 for(j = player->inventorySlotNum; j > i; j--)
839 player->inventory[j].count = player->inventory[j-1].count;
840 player->inventory[j].type = player->inventory[j-1].type;
845 player->inventory[i].count = 1;
846 player->inventory[i].type = arti;
847 player->inventorySlotNum++;
851 if(arti >= arti_firstpuzzitem && netgame && !deathmatch)
852 { // Can't carry more than 1 puzzle item in coop netplay
855 if(player->inventory[i].count >= 25)
856 { // Player already has 25 of this item
859 player->inventory[i].count++;
861 if(!player->artifactCount)
863 player->readyArtifact = arti;
865 else if(player == &players[consoleplayer] && slidePointer
875 player->artifactCount++;
879 //==========================================================================
881 // SetDormantArtifact
883 // Removes the MF_SPECIAL flag and initiates the artifact pickup
886 //==========================================================================
888 static void SetDormantArtifact(mobj_t *arti)
890 arti->flags &= ~MF_SPECIAL;
891 if(deathmatch && !(arti->flags2 & MF2_DROPPED))
893 if(arti->type == MT_ARTIINVULNERABILITY)
895 P_SetMobjState(arti, S_DORMANTARTI3_1);
897 else if(arti->type == MT_SUMMONMAULATOR
898 || arti->type == MT_ARTIFLY)
900 P_SetMobjState(arti, S_DORMANTARTI2_1);
904 P_SetMobjState(arti, S_DORMANTARTI1_1);
909 P_SetMobjState(arti, S_DEADARTI1);
913 //---------------------------------------------------------------------------
915 // PROC A_RestoreArtifact
917 //---------------------------------------------------------------------------
919 void A_RestoreArtifact(mobj_t *arti)
921 arti->flags |= MF_SPECIAL;
922 P_SetMobjState(arti, arti->info->spawnstate);
923 S_StartSound(arti, SFX_RESPAWN);
926 //---------------------------------------------------------------------------
928 // PROC A_RestoreSpecialThing1
930 // Make a special thing visible again.
932 //---------------------------------------------------------------------------
934 void A_RestoreSpecialThing1(mobj_t *thing)
936 thing->flags2 &= ~MF2_DONTDRAW;
937 S_StartSound(thing, SFX_RESPAWN);
940 //---------------------------------------------------------------------------
942 // PROC A_RestoreSpecialThing2
944 //---------------------------------------------------------------------------
946 void A_RestoreSpecialThing2(mobj_t *thing)
948 thing->flags |= MF_SPECIAL;
949 P_SetMobjState(thing, thing->info->spawnstate);
952 //---------------------------------------------------------------------------
954 // PROC P_TouchSpecialThing
956 //---------------------------------------------------------------------------
958 void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
965 delta = special->z-toucher->z;
966 if(delta > toucher->height || delta < -32*FRACUNIT)
970 if(toucher->health <= 0)
974 sound = SFX_PICKUP_ITEM;
975 player = toucher->player;
977 switch(special->sprite)
980 case SPR_PTN1: // Item_HealingPotion
981 if(!P_GiveBody(player, 10))
985 P_SetMessage(player, TXT_ITEMHEALTH, false);
988 if(!P_GiveArmor(player, ARMOR_ARMOR, -1))
992 P_SetMessage(player, TXT_ARMOR1, false);
995 if(!P_GiveArmor(player, ARMOR_SHIELD, -1))
999 P_SetMessage(player, TXT_ARMOR2, false);
1002 if(!P_GiveArmor(player, ARMOR_HELMET, -1))
1006 P_SetMessage(player, TXT_ARMOR3, false);
1009 if(!P_GiveArmor(player, ARMOR_AMULET, -1))
1013 P_SetMessage(player, TXT_ARMOR4, false);
1028 if(!P_GiveKey(player, special->sprite-SPR_KEY1))
1032 P_SetMessage(player, TextKeyMessages[special->sprite-SPR_KEY1],
1034 sound = SFX_PICKUP_KEY;
1036 // Check and process the special now in case the key doesn't
1037 // get removed for coop netplay
1038 if(special->special)
1040 P_ExecuteLineSpecial(special->special, special->args,
1042 special->special = 0;
1046 { // Only remove keys in single player game
1049 player->bonuscount += BONUSADD;
1050 if(player == &players[consoleplayer])
1052 S_StartSound(NULL, sound);
1053 SB_PaletteFlash(false);
1059 TryPickupArtifact(player, arti_health, special);
1062 TryPickupArtifact(player, arti_fly, special);
1065 TryPickupArtifact(player, arti_invulnerability, special);
1068 TryPickupArtifact(player, arti_summon, special);
1071 TryPickupArtifact(player, arti_egg, special);
1074 TryPickupArtifact(player, arti_superhealth, special);
1077 TryPickupArtifact(player, arti_healingradius, special);
1080 TryPickupArtifact(player, arti_torch, special);
1083 TryPickupArtifact(player, arti_teleport, special);
1086 TryPickupArtifact(player, arti_teleportother, special);
1089 TryPickupArtifact(player, arti_poisonbag, special);
1092 TryPickupArtifact(player, arti_speed, special);
1095 TryPickupArtifact(player, arti_boostmana, special);
1098 TryPickupArtifact(player, arti_boostarmor, special);
1101 TryPickupArtifact(player, arti_blastradius, special);
1106 TryPickupArtifact(player, arti_puzzskull, special);
1109 TryPickupArtifact(player, arti_puzzgembig, special);
1112 TryPickupArtifact(player, arti_puzzgemred, special);
1115 TryPickupArtifact(player, arti_puzzgemgreen1, special);
1118 TryPickupArtifact(player, arti_puzzgemgreen2, special);
1121 TryPickupArtifact(player, arti_puzzgemblue1, special);
1124 TryPickupArtifact(player, arti_puzzgemblue2, special);
1127 TryPickupArtifact(player, arti_puzzbook1, special);
1130 TryPickupArtifact(player, arti_puzzbook2, special);
1133 TryPickupArtifact(player, arti_puzzskull2, special);
1136 TryPickupArtifact(player, arti_puzzfweapon, special);
1139 TryPickupArtifact(player, arti_puzzcweapon, special);
1142 TryPickupArtifact(player, arti_puzzmweapon, special);
1145 TryPickupArtifact(player, arti_puzzgear1, special);
1148 TryPickupArtifact(player, arti_puzzgear2, special);
1151 TryPickupArtifact(player, arti_puzzgear3, special);
1154 TryPickupArtifact(player, arti_puzzgear4, special);
1159 if(!P_GiveMana(player, MANA_1, 15))
1163 P_SetMessage(player, TXT_MANA_1, false);
1166 if(!P_GiveMana(player, MANA_2, 15))
1170 P_SetMessage(player, TXT_MANA_2, false);
1172 case SPR_MAN3: // Double Mana Dodecahedron
1173 if(!P_GiveMana(player, MANA_1, 20))
1175 if(!P_GiveMana(player, MANA_2, 20))
1182 P_GiveMana(player, MANA_2, 20);
1184 P_SetMessage(player, TXT_MANA_BOTH, false);
1187 // 2nd and 3rd Mage Weapons
1188 case SPR_WMCS: // Frost Shards
1189 TryPickupWeapon(player, PCLASS_MAGE, WP_SECOND,
1190 special, TXT_WEAPON_M2);
1192 case SPR_WMLG: // Arc of Death
1193 TryPickupWeapon(player, PCLASS_MAGE, WP_THIRD,
1194 special, TXT_WEAPON_M3);
1197 // 2nd and 3rd Fighter Weapons
1198 case SPR_WFAX: // Timon's Axe
1199 TryPickupWeapon(player, PCLASS_FIGHTER, WP_SECOND,
1200 special, TXT_WEAPON_F2);
1202 case SPR_WFHM: // Hammer of Retribution
1203 TryPickupWeapon(player, PCLASS_FIGHTER, WP_THIRD,
1204 special, TXT_WEAPON_F3);
1207 // 2nd and 3rd Cleric Weapons
1208 case SPR_WCSS: // Serpent Staff
1209 TryPickupWeapon(player, PCLASS_CLERIC, WP_SECOND,
1210 special, TXT_WEAPON_C2);
1212 case SPR_WCFM: // Firestorm
1213 TryPickupWeapon(player, PCLASS_CLERIC, WP_THIRD,
1214 special, TXT_WEAPON_C3);
1217 // Fourth Weapon Pieces
1219 TryPickupWeaponPiece(player, PCLASS_FIGHTER, WPIECE1,
1223 TryPickupWeaponPiece(player, PCLASS_FIGHTER, WPIECE2,
1227 TryPickupWeaponPiece(player, PCLASS_FIGHTER, WPIECE3,
1231 TryPickupWeaponPiece(player, PCLASS_CLERIC, WPIECE1,
1235 TryPickupWeaponPiece(player, PCLASS_CLERIC, WPIECE2,
1239 TryPickupWeaponPiece(player, PCLASS_CLERIC, WPIECE3,
1243 TryPickupWeaponPiece(player, PCLASS_MAGE, WPIECE1,
1247 TryPickupWeaponPiece(player, PCLASS_MAGE, WPIECE2,
1251 TryPickupWeaponPiece(player, PCLASS_MAGE, WPIECE3,
1254 // Don't forget to fix this
1256 TryPickupWeaponPiece(player, PCLASS_ASS, WPIECE1,
1260 TryPickupWeaponPiece(player, PCLASS_ASS, WPIECE2,
1264 TryPickupWeaponPiece(player,PCLASS_ASS, WPIECE3,
1270 I_Error("P_SpecialThing: Unknown gettable thing");
1272 if(special->special)
1274 P_ExecuteLineSpecial(special->special, special->args, NULL,
1276 special->special = 0;
1278 if(deathmatch && respawn && !(special->flags2&MF2_DROPPED))
1280 P_HideSpecialThing(special);
1284 P_RemoveMobj(special);
1286 player->bonuscount += BONUSADD;
1287 if(player == &players[consoleplayer])
1289 S_StartSound(NULL, sound);
1290 SB_PaletteFlash(false);
1294 // Search thinker list for minotaur
1295 mobj_t *ActiveMinotaur(player_t *master)
1300 unsigned int *starttime;
1302 for(think = thinkercap.next; think != &thinkercap; think = think->next)
1304 if(think->function != P_MobjThinker) continue;
1305 mo = (mobj_t *)think;
1306 if(mo->type != MT_MINOTAUR) continue;
1307 if(mo->health <= 0) continue;
1308 if(!(mo->flags&MF_COUNTKILL)) continue; // for morphed minotaurs
1309 if(mo->flags&MF_CORPSE) continue;
1310 starttime = (unsigned int *)mo->args;
1311 if ((leveltime - *starttime) >= MAULATORTICS) continue;
1312 plr = ((mobj_t *)mo->special1)->player;
1313 if(plr == master) return(mo);
1319 //---------------------------------------------------------------------------
1323 //---------------------------------------------------------------------------
1325 void P_KillMobj(mobj_t *source, mobj_t *target)
1330 target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY|MF_NOGRAVITY);
1331 target->flags |= MF_CORPSE|MF_DROPOFF;
1332 target->flags2 &= ~MF2_PASSMOBJ;
1333 target->height >>= 2;
1334 if((target->flags&MF_COUNTKILL || target->type == MT_ZBELL)
1336 { // Initiate monster death actions
1337 if(target->type == MT_SORCBOSS)
1340 P_StartACS(target->special, 0, (byte *)&dummy, target,
1345 P_ExecuteLineSpecial(target->special, target->args,
1349 if(source && source->player)
1350 { // Check for frag changes
1353 if(target == source)
1355 target->player->frags[target->player-players]--;
1356 if(cmdfrag && netgame
1357 && source->player == &players[consoleplayer])
1358 { // Send out a frag count packet
1359 NET_SendFrags(source->player);
1364 source->player->frags[target->player-players]++;
1365 if(cmdfrag && netgame
1366 && source->player == &players[consoleplayer])
1367 { // Send out a frag count packet
1368 NET_SendFrags(source->player);
1377 target->player->frags[target->player-players]--;
1378 if(cmdfrag && netgame
1379 && target->player == &players[consoleplayer])
1380 { // Send out a frag count packet
1381 NET_SendFrags(target->player);
1384 target->flags &= ~MF_SOLID;
1385 target->flags2 &= ~MF2_FLY;
1386 target->player->powers[pw_flight] = 0;
1387 target->player->playerstate = PST_DEAD;
1388 P_DropWeapon(target->player);
1389 if(target->flags2&MF2_FIREDAMAGE)
1390 { // Player flame death
1391 switch(target->player->class)
1393 case PCLASS_FIGHTER:
1394 S_StartSound(target, SFX_PLAYER_FIGHTER_BURN_DEATH);
1395 P_SetMobjState(target, S_PLAY_F_FDTH1);
1398 S_StartSound(target, SFX_PLAYER_CLERIC_BURN_DEATH);
1399 P_SetMobjState(target, S_PLAY_C_FDTH1);
1402 S_StartSound(target, SFX_PLAYER_MAGE_BURN_DEATH);
1403 P_SetMobjState(target, S_PLAY_M_FDTH1);
1409 if(target->flags2&MF2_ICEDAMAGE)
1410 { // Player ice death
1411 target->flags &= ~(7<<MF_TRANSSHIFT); //no translation
1412 target->flags |= MF_ICECORPSE;
1413 switch(target->player->class)
1415 case PCLASS_FIGHTER:
1416 P_SetMobjState(target, S_FPLAY_ICE);
1419 P_SetMobjState(target, S_CPLAY_ICE);
1422 P_SetMobjState(target, S_MPLAY_ICE);
1425 P_SetMobjState(target, S_PIG_ICE);
1432 if(target->flags2&MF2_FIREDAMAGE)
1434 if(target->type == MT_FIGHTER_BOSS
1435 || target->type == MT_CLERIC_BOSS
1436 || target->type == MT_MAGE_BOSS)
1438 switch(target->type)
1440 case MT_FIGHTER_BOSS:
1441 S_StartSound(target, SFX_PLAYER_FIGHTER_BURN_DEATH);
1442 P_SetMobjState(target, S_PLAY_F_FDTH1);
1444 case MT_CLERIC_BOSS:
1445 S_StartSound(target, SFX_PLAYER_CLERIC_BURN_DEATH);
1446 P_SetMobjState(target, S_PLAY_C_FDTH1);
1449 S_StartSound(target, SFX_PLAYER_MAGE_BURN_DEATH);
1450 P_SetMobjState(target, S_PLAY_M_FDTH1);
1456 else if(target->type == MT_TREEDESTRUCTIBLE)
1458 P_SetMobjState(target, S_ZTREEDES_X1);
1459 target->height = 24*FRACUNIT;
1460 S_StartSound(target, SFX_TREE_EXPLODE);
1464 if(target->flags2&MF2_ICEDAMAGE)
1466 target->flags |= MF_ICECORPSE;
1467 switch(target->type)
1470 P_SetMobjState(target, S_BISHOP_ICE);
1473 case MT_CENTAURLEADER:
1474 P_SetMobjState(target, S_CENTAUR_ICE);
1478 P_SetMobjState(target, S_DEMON_ICE);
1481 case MT_SERPENTLEADER:
1482 P_SetMobjState(target, S_SERPENT_ICE);
1486 P_SetMobjState(target, S_WRAITH_ICE);
1489 P_SetMobjState(target, S_ETTIN_ICE1);
1492 P_SetMobjState(target, S_FIRED_ICE1);
1494 case MT_FIGHTER_BOSS:
1495 P_SetMobjState(target, S_FIGHTER_ICE);
1497 case MT_CLERIC_BOSS:
1498 P_SetMobjState(target, S_CLERIC_ICE);
1501 P_SetMobjState(target, S_MAGE_ICE);
1504 P_SetMobjState(target, S_PIG_ICE);
1507 target->flags &= ~MF_ICECORPSE;
1512 if(target->type == MT_MINOTAUR)
1514 master = (mobj_t *)target->special1;
1515 if(master->health > 0)
1517 if (!ActiveMinotaur(master->player))
1519 master->player->powers[pw_minotaur] = 0;
1523 else if(target->type == MT_TREEDESTRUCTIBLE)
1525 target->height = 24*FRACUNIT;
1527 if(target->health < -(target->info->spawnhealth>>1)
1528 && target->info->xdeathstate)
1530 P_SetMobjState(target, target->info->xdeathstate);
1534 if ((target->type==MT_FIREDEMON) &&
1535 (target->z <= target->floorz + 2*FRACUNIT) &&
1536 (target->info->xdeathstate))
1538 // This is to fix the imps' staying in fall state
1539 P_SetMobjState(target, target->info->xdeathstate);
1543 P_SetMobjState(target, target->info->deathstate);
1546 target->tics -= P_Random()&3;
1547 // I_StartSound(&actor->r, actor->info->deathsound);
1550 //---------------------------------------------------------------------------
1552 // FUNC P_MinotaurSlam
1554 //---------------------------------------------------------------------------
1556 void P_MinotaurSlam(mobj_t *source, mobj_t *target)
1561 angle = R_PointToAngle2(source->x, source->y, target->x, target->y);
1562 angle >>= ANGLETOFINESHIFT;
1563 thrust = 16*FRACUNIT+(P_Random()<<10);
1564 target->momx += FixedMul(thrust, finecosine[angle]);
1565 target->momy += FixedMul(thrust, finesine[angle]);
1566 P_DamageMobj(target, NULL, source, HITDICE(4));
1569 target->reactiontime = 14+(P_Random()&7);
1571 source->args[0] = 0; // Stop charging
1575 //---------------------------------------------------------------------------
1577 // FUNC P_MorphPlayer
1579 // Returns true if the player gets turned into a pig
1581 //---------------------------------------------------------------------------
1583 boolean P_MorphPlayer(player_t *player)
1594 if(player->powers[pw_invulnerability])
1595 { // Immune when invulnerable
1598 if(player->morphTics)
1599 { // Player is already a beast
1607 oldFlags2 = pmo->flags2;
1608 P_SetMobjState(pmo, S_FREETARGMOBJ);
1609 fog = P_SpawnMobj(x, y, z+TELEFOGHEIGHT, MT_TFOG);
1610 S_StartSound(fog, SFX_TELEPORT);
1611 beastMo = P_SpawnMobj(x, y, z, MT_PIGPLAYER);
1612 beastMo->special1 = player->readyweapon;
1613 beastMo->angle = angle;
1614 beastMo->player = player;
1615 player->health = beastMo->health = MAXMORPHHEALTH;
1616 player->mo = beastMo;
1617 memset(&player->armorpoints[0], 0, NUMARMOR*sizeof(int));
1618 player->class = PCLASS_PIG;
1619 if(oldFlags2&MF2_FLY)
1621 beastMo->flags2 |= MF2_FLY;
1623 player->morphTics = MORPHTICS;
1624 P_ActivateMorphWeapon(player);
1628 //---------------------------------------------------------------------------
1630 // FUNC P_MorphMonster
1632 //---------------------------------------------------------------------------
1634 boolean P_MorphMonster(mobj_t *actor)
1636 mobj_t *master, *monster, *fog;
1643 if(actor->player) return(false);
1644 if(!(actor->flags&MF_COUNTKILL)) return false;
1645 if(actor->flags2&MF2_BOSS) return false;
1646 moType = actor->type;
1651 case MT_FIGHTER_BOSS:
1652 case MT_CLERIC_BOSS:
1659 oldMonster = *actor;
1663 P_RemoveMobjFromTIDList(actor);
1664 P_SetMobjState(actor, S_FREETARGMOBJ);
1665 fog = P_SpawnMobj(x, y, z+TELEFOGHEIGHT, MT_TFOG);
1666 S_StartSound(fog, SFX_TELEPORT);
1667 monster = P_SpawnMobj(x, y, z, MT_PIG);
1668 monster->special2 = moType;
1669 monster->special1 = MORPHTICS+P_Random();
1670 monster->flags |= (oldMonster.flags&MF_SHADOW);
1671 monster->target = oldMonster.target;
1672 monster->angle = oldMonster.angle;
1673 monster->tid = oldMonster.tid;
1674 monster->special = oldMonster.special;
1675 P_InsertMobjIntoTIDList(monster, oldMonster.tid);
1676 memcpy(monster->args, oldMonster.args, 5);
1678 // check for turning off minotaur power for active icon
1679 if (moType==MT_MINOTAUR)
1681 master = (mobj_t *)oldMonster.special1;
1682 if(master->health > 0)
1684 if (!ActiveMinotaur(master->player))
1686 master->player->powers[pw_minotaur] = 0;
1693 //---------------------------------------------------------------------------
1695 // PROC P_AutoUseHealth
1697 //---------------------------------------------------------------------------
1699 void P_AutoUseHealth(player_t *player, int saveHealth)
1708 normalCount = superCount = 0;
1709 for(i = 0; i < player->inventorySlotNum; i++)
1711 if(player->inventory[i].type == arti_health)
1714 normalCount = player->inventory[i].count;
1716 else if(player->inventory[i].type == arti_superhealth)
1719 superCount = player->inventory[i].count;
1722 if((gameskill == sk_baby) && (normalCount*25 >= saveHealth))
1723 { // Use quartz flasks
1724 count = (saveHealth+24)/25;
1725 for(i = 0; i < count; i++)
1727 player->health += 25;
1728 P_PlayerRemoveArtifact(player, normalSlot);
1731 else if(superCount*100 >= saveHealth)
1732 { // Use mystic urns
1733 count = (saveHealth+99)/100;
1734 for(i = 0; i < count; i++)
1736 player->health += 100;
1737 P_PlayerRemoveArtifact(player, superSlot);
1740 else if((gameskill == sk_baby)
1741 && (superCount*100+normalCount*25 >= saveHealth))
1742 { // Use mystic urns and quartz flasks
1743 count = (saveHealth+24)/25;
1744 saveHealth -= count*25;
1745 for(i = 0; i < count; i++)
1747 player->health += 25;
1748 P_PlayerRemoveArtifact(player, normalSlot);
1750 count = (saveHealth+99)/100;
1751 for(i = 0; i < count; i++)
1753 player->health += 100;
1754 P_PlayerRemoveArtifact(player, normalSlot);
1757 player->mo->health = player->health;
1765 = Damages both enemies and players
1766 = inflictor is the thing that caused the damage
1767 = creature or missile, can be NULL (slime, etc)
1768 = source is the thing to target after taking damage
1770 = Source and inflictor are the same for melee attacks
1771 = source can be null for barrel explosions and other environmental stuff
1785 fixed_t savedPercent;
1792 if(!(target->flags&MF_SHOOTABLE))
1797 if(target->health <= 0)
1799 if (inflictor && inflictor->flags2&MF2_ICEDAMAGE)
1803 else if (target->flags&MF_ICECORPSE) // frozen
1806 target->momx = target->momy = 0;
1810 if ((target->flags2&MF2_INVULNERABLE) && damage < 10000)
1811 { // mobj is invulnerable
1812 if(target->player) return; // for player, no exceptions
1815 switch(inflictor->type)
1817 // These inflictors aren't foiled by invulnerability
1819 case MT_POISONCLOUD:
1833 if(damage < 1000 && ((target->player->cheats&CF_GODMODE)
1834 || target->player->powers[pw_invulnerability]))
1839 if(target->flags&MF_SKULLFLY)
1841 target->momx = target->momy = target->momz = 0;
1843 if(target->flags2&MF2_DORMANT)
1845 // Invulnerable, and won't wake up
1848 player = target->player;
1849 if(player && gameskill == sk_baby)
1851 // Take half damage in trainer mode
1854 // Special damage types
1857 switch(inflictor->type)
1862 P_MorphPlayer(player);
1866 P_MorphMonster(target);
1868 return; // Always return
1869 case MT_TELOTHER_FX1:
1870 case MT_TELOTHER_FX2:
1871 case MT_TELOTHER_FX3:
1872 case MT_TELOTHER_FX4:
1873 case MT_TELOTHER_FX5:
1874 if ((target->flags&MF_COUNTKILL) &&
1875 (target->type != MT_SERPENT) &&
1876 (target->type != MT_SERPENTLEADER) &&
1877 (!(target->flags2 & MF2_BOSS)))
1879 P_TeleportOther(target);
1883 if(inflictor->flags&MF_SKULLFLY)
1884 { // Slam only when in charge mode
1885 P_MinotaurSlam(inflictor, target);
1890 // Bishops are just too nasty
1894 switch(inflictor->special2)
1909 case MT_CSTAFF_MISSILE:
1910 // Cleric Serpent Staff does poison damage
1913 P_PoisonPlayer(target->player, source, 20);
1923 P_PoisonPlayer(target->player, source, 20);
1927 case MT_POISONCLOUD:
1930 if(target->player->poisoncount < 4)
1932 P_PoisonDamage(target->player, source,
1933 15+(P_Random()&15), false); // Don't play painsound
1934 P_PoisonPlayer(target->player, source, 50);
1935 S_StartSound(target, SFX_PLAYER_POISONCOUGH);
1939 else if(!(target->flags&MF_COUNTKILL))
1940 { // only damage monsters/players with the poison cloud
1944 case MT_FSWORD_MISSILE:
1947 damage -= damage>>2;
1954 // Push the target unless source is using the gauntlets
1955 if(inflictor && (!source || !source->player)
1956 && !(inflictor->flags2&MF2_NODMGTHRUST))
1958 ang = R_PointToAngle2(inflictor->x, inflictor->y,
1959 target->x, target->y);
1960 //thrust = damage*(FRACUNIT>>3)*100/target->info->mass;
1961 thrust = damage*(FRACUNIT>>3)*150/target->info->mass;
1962 // make fall forwards sometimes
1963 if((damage < 40) && (damage > target->health)
1964 && (target->z-inflictor->z > 64*FRACUNIT) && (P_Random()&1))
1969 ang >>= ANGLETOFINESHIFT;
1970 target->momx += FixedMul(thrust, finecosine[ang]);
1971 target->momy += FixedMul(thrust, finesine[ang]);
1979 savedPercent = AutoArmorSave[player->class]
1980 +player->armorpoints[ARMOR_ARMOR]+player->armorpoints[ARMOR_SHIELD]
1981 +player->armorpoints[ARMOR_HELMET]
1982 +player->armorpoints[ARMOR_AMULET];
1984 { // armor absorbed some damage
1985 if(savedPercent > 100*FRACUNIT)
1987 savedPercent = 100*FRACUNIT;
1989 for(i = 0; i < NUMARMOR; i++)
1991 if(player->armorpoints[i])
1993 player->armorpoints[i] -=
1994 FixedDiv(FixedMul(damage<<FRACBITS,
1995 ArmorIncrement[player->class][i]), 300*FRACUNIT);
1996 if(player->armorpoints[i] < 2*FRACUNIT)
1998 player->armorpoints[i] = 0;
2002 saved = FixedDiv(FixedMul(damage<<FRACBITS, savedPercent),
2004 if(saved > savedPercent*2)
2006 saved = savedPercent*2;
2008 damage -= saved>>FRACBITS;
2010 if(damage >= player->health
2011 && ((gameskill == sk_baby) || deathmatch)
2012 && !player->morphTics)
2013 { // Try to use some inventory health
2014 P_AutoUseHealth(player, damage-player->health+1);
2016 player->health -= damage; // mirror mobj health here for Dave
2017 if(player->health < 0)
2021 player->attacker = source;
2022 player->damagecount += damage; // add damage after armor / invuln
2023 if(player->damagecount > 100)
2025 player->damagecount = 100; // teleport stomp does 10k points...
2027 temp = damage < 100 ? damage : 100;
2028 if(player == &players[consoleplayer])
2030 //I_Tactile(40, 10, 40+temp*2);
2031 SB_PaletteFlash(false);
2038 target->health -= damage;
2039 if(target->health <= 0)
2042 { // check for special fire damage or ice damage deaths
2043 if(inflictor->flags2&MF2_FIREDAMAGE)
2045 if(player && !player->morphTics)
2046 { // Check for flame death
2047 if(target->health > -50 && damage > 25)
2049 target->flags2 |= MF2_FIREDAMAGE;
2054 target->flags2 |= MF2_FIREDAMAGE;
2057 else if(inflictor->flags2&MF2_ICEDAMAGE)
2059 target->flags2 |= MF2_ICEDAMAGE;
2062 if(source && (source->type == MT_MINOTAUR))
2063 { // Minotaur's kills go to his master
2064 master = (mobj_t *)(source->special1);
2065 // Make sure still alive and not a pointer to fighter head
2066 if (master->player && (master->player->mo == master))
2071 if(source && (source->player) &&
2072 (source->player->readyweapon == WP_FOURTH))
2074 // Always extreme death from fourth weapon
2075 target->health = -5000;
2077 P_KillMobj(source, target);
2080 if((P_Random() < target->info->painchance)
2081 && !(target->flags&MF_SKULLFLY))
2083 if(inflictor && (inflictor->type >= MT_LIGHTNING_FLOOR
2084 && inflictor->type <= MT_LIGHTNING_ZAP))
2088 target->flags |= MF_JUSTHIT; // fight back!
2089 P_SetMobjState(target, target->info->painstate);
2092 { // "electrocute" the target
2093 target->frame |= FF_FULLBRIGHT;
2094 if(target->flags&MF_COUNTKILL && P_Random() < 128
2095 && !S_GetSoundPlayingInfo(target, SFX_PUPPYBEAT))
2097 if ((target->type == MT_CENTAUR) ||
2098 (target->type == MT_CENTAURLEADER) ||
2099 (target->type == MT_ETTIN))
2101 S_StartSound(target, SFX_PUPPYBEAT);
2108 target->flags |= MF_JUSTHIT; // fight back!
2109 P_SetMobjState(target, target->info->painstate);
2110 if(inflictor && inflictor->type == MT_POISONCLOUD)
2112 if(target->flags&MF_COUNTKILL && P_Random() < 128
2113 && !S_GetSoundPlayingInfo(target, SFX_PUPPYBEAT))
2115 if ((target->type == MT_CENTAUR) ||
2116 (target->type == MT_CENTAURLEADER) ||
2117 (target->type == MT_ETTIN))
2119 S_StartSound(target, SFX_PUPPYBEAT);
2125 target->reactiontime = 0; // we're awake now...
2126 if(!target->threshold && source && !(source->flags2&MF2_BOSS)
2127 && !(target->type == MT_BISHOP) && !(target->type == MT_MINOTAUR))
2129 // Target actor is not intent on another actor,
2130 // so make him chase after source
2131 if((target->type == MT_CENTAUR && source->type == MT_CENTAURLEADER)
2132 || (target->type == MT_CENTAURLEADER
2133 && source->type == MT_CENTAUR))
2137 target->target = source;
2138 target->threshold = BASETHRESHOLD;
2139 if(target->state == &states[target->info->spawnstate]
2140 && target->info->seestate != S_NULL)
2142 P_SetMobjState(target, target->info->seestate);
2147 //==========================================================================
2151 //==========================================================================
2153 void P_FallingDamage(player_t *player)
2159 mom = abs(player->mo->momz);
2160 dist = FixedMul(mom, 16*FRACUNIT/23);
2162 if(mom >= 63*FRACUNIT)
2163 { // automatic death
2164 P_DamageMobj(player->mo, NULL, NULL, 10000);
2167 damage = ((FixedMul(dist, dist)/10)>>FRACBITS)-24;
2168 if(player->mo->momz > -39*FRACUNIT && damage > player->mo->health
2169 && player->mo->health != 1)
2170 { // No-death threshold
2171 damage = player->mo->health-1;
2173 S_StartSound(player->mo, SFX_PLAYER_LAND);
2174 P_DamageMobj(player->mo, NULL, NULL, damage);
2177 //==========================================================================
2179 // P_PoisonPlayer - Sets up all data concerning poisoning
2181 //==========================================================================
2183 void P_PoisonPlayer(player_t *player, mobj_t *poisoner, int poison)
2185 if((player->cheats&CF_GODMODE) || player->powers[pw_invulnerability])
2189 player->poisoncount += poison;
2190 player->poisoner = poisoner;
2191 if(player->poisoncount > 100)
2193 player->poisoncount = 100;
2197 //==========================================================================
2199 // P_PoisonDamage - Similar to P_DamageMobj
2201 //==========================================================================
2203 void P_PoisonDamage(player_t *player, mobj_t *source, int damage,
2204 boolean playPainSound)
2209 target = player->mo;
2211 if(target->health <= 0)
2215 if(target->flags2&MF2_INVULNERABLE && damage < 10000)
2216 { // mobj is invulnerable
2219 if(player && gameskill == sk_baby)
2221 // Take half damage in trainer mode
2224 if(damage < 1000 && ((player->cheats&CF_GODMODE)
2225 || player->powers[pw_invulnerability]))
2229 if(damage >= player->health
2230 && ((gameskill == sk_baby) || deathmatch)
2231 && !player->morphTics)
2232 { // Try to use some inventory health
2233 P_AutoUseHealth(player, damage-player->health+1);
2235 player->health -= damage; // mirror mobj health here for Dave
2236 if(player->health < 0)
2240 player->attacker = source;
2245 target->health -= damage;
2246 if(target->health <= 0)
2248 target->special1 = damage;
2249 if(player && inflictor && !player->morphTics)
2250 { // Check for flame death
2251 if((inflictor->flags2&MF2_FIREDAMAGE)
2252 && (target->health > -50) && (damage > 25))
2254 target->flags2 |= MF2_FIREDAMAGE;
2256 if(inflictor->flags2&MF2_ICEDAMAGE)
2258 target->flags2 |= MF2_ICEDAMAGE;
2261 P_KillMobj(source, target);
2264 if(!(leveltime&63) && playPainSound)
2266 P_SetMobjState(target, target->info->painstate);
2269 if((P_Random() < target->info->painchance)
2270 && !(target->flags&MF_SKULLFLY))
2272 target->flags |= MF_JUSTHIT; // fight back!
2273 P_SetMobjState(target, target->info->painstate);