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 },
25 {20*FRACUNIT, 10*FRACUNIT, 25*FRACUNIT, 5*FRACUNIT },
30 int AutoArmorSave[NUMCLASSES] = { 15*FRACUNIT, 10*FRACUNIT, 5*FRACUNIT,
36 char *TextKeyMessages[] =
51 static void SetDormantArtifact(mobj_t *arti);
52 static void TryPickupArtifact(player_t *player, artitype_t artifactType,
54 static void TryPickupWeapon(player_t *player, pclass_t weaponClass,
55 weapontype_t weaponType, mobj_t *weapon, char *message);
56 static void TryPickupWeaponPiece(player_t *player, pclass_t matchClass,
57 int pieceValue, mobj_t *pieceMobj);
59 /* jim Linux needs this too */
61 #if defined(__NeXT__) || defined(__linux) || defined(__FreeBSD__)
62 extern void strupr(char *s);
65 //--------------------------------------------------------------------------
69 //--------------------------------------------------------------------------
71 void P_SetMessage(player_t *player, char *message, boolean ultmsg)
73 extern boolean messageson;
75 if((player->ultimateMessage || !messageson) && !ultmsg)
79 if(strlen(message) > 79)
81 memcpy(player->message, message, 80);
82 player->message[80] = 0;
86 strcpy(player->message, message);
88 strupr(player->message);
89 player->messageTics = MESSAGETICS;
90 player->yellowMessage = false;
93 player->ultimateMessage = true;
95 if(player == &players[consoleplayer])
97 BorderTopRefresh = true;
101 //==========================================================================
103 // P_SetYellowMessage
105 //==========================================================================
107 void P_SetYellowMessage(player_t *player, char *message, boolean ultmsg)
109 extern boolean messageson;
111 if((player->ultimateMessage || !messageson) && !ultmsg)
115 if(strlen(message) > 79)
117 memcpy(player->message, message, 80);
118 player->message[80] = 0;
122 strcpy(player->message, message);
124 player->messageTics = 5*MESSAGETICS; // Bold messages last longer
125 player->yellowMessage = true;
128 player->ultimateMessage = true;
130 if(player == &players[consoleplayer])
132 BorderTopRefresh = true;
136 //==========================================================================
140 //==========================================================================
142 void P_ClearMessage(player_t *player)
144 player->messageTics = 0;
145 if(player == &players[consoleplayer])
147 BorderTopRefresh = true;
151 //----------------------------------------------------------------------------
153 // PROC P_HideSpecialThing
155 //----------------------------------------------------------------------------
157 void P_HideSpecialThing(mobj_t *thing)
159 thing->flags &= ~MF_SPECIAL;
160 thing->flags2 |= MF2_DONTDRAW;
161 P_SetMobjState(thing, S_HIDESPECIAL1);
164 //--------------------------------------------------------------------------
168 // Returns true if the player accepted the mana, false if it was
169 // refused (player has MAX_MANA).
171 //--------------------------------------------------------------------------
173 boolean P_GiveMana(player_t *player, manatype_t mana, int count)
176 //weapontype_t changeWeapon;
178 if(mana == MANA_NONE || mana == MANA_BOTH)
182 if(mana < 0 || mana > NUMMANA)
184 I_Error("P_GiveMana: bad type %i", mana);
186 if(player->mana[mana] == MAX_MANA)
190 if(gameskill == sk_baby || gameskill == sk_nightmare)
191 { // extra mana in baby mode and nightmare mode
194 prevMana = player->mana[mana];
196 player->mana[mana] += count;
197 if(player->mana[mana] > MAX_MANA)
199 player->mana[mana] = MAX_MANA;
201 if(player->class == PCLASS_FIGHTER && player->readyweapon == WP_SECOND
202 && mana == MANA_1 && prevMana <= 0)
204 P_SetPsprite(player, ps_weapon, S_FAXEREADY_G);
209 //==========================================================================
213 //==========================================================================
215 static void TryPickupWeapon(player_t *player, pclass_t weaponClass,
216 weapontype_t weaponType, mobj_t *weapon, char *message)
223 if(player->class != weaponClass
225 && player->class != PCLASS_ASS
228 { // Wrong class, but try to pick up for mana
229 if(netgame && !deathmatch)
230 { // Can't pick up weapons for other classes in coop netplay
233 if(weaponType == WP_SECOND)
235 if(!P_GiveMana(player, MANA_1, 25))
242 if(!P_GiveMana(player, MANA_2, 25))
248 else if(netgame && !deathmatch)
249 { // Cooperative net-game
250 if(player->weaponowned[weaponType])
254 player->weaponowned[weaponType] = true;
255 if(weaponType == WP_SECOND)
257 P_GiveMana(player, MANA_1, 25);
261 P_GiveMana(player, MANA_2, 25);
263 player->pendingweapon = weaponType;
267 { // Deathmatch or single player game
268 if(weaponType == WP_SECOND)
270 gaveMana = P_GiveMana(player, MANA_1, 25);
274 gaveMana = P_GiveMana(player, MANA_2, 25);
276 if(player->weaponowned[weaponType])
283 player->weaponowned[weaponType] = true;
284 if(weaponType > player->readyweapon)
285 { // Only switch to more powerful weapons
286 player->pendingweapon = weaponType;
289 if(!(gaveWeapon || gaveMana))
290 { // Player didn't need the weapon or any mana
295 P_SetMessage(player, message, false);
298 P_ExecuteLineSpecial(weapon->special, weapon->args,
299 NULL, 0, player->mo);
305 if(deathmatch && !(weapon->flags2&MF2_DROPPED))
307 P_HideSpecialThing(weapon);
311 P_RemoveMobj(weapon);
315 player->bonuscount += BONUSADD;
316 if(player == &players[consoleplayer])
318 S_StartSound(NULL, SFX_PICKUP_WEAPON);
319 SB_PaletteFlash(false);
323 //--------------------------------------------------------------------------
327 // Returns true if the weapon or its mana was accepted.
329 //--------------------------------------------------------------------------
332 boolean P_GiveWeapon(player_t *player, pclass_t class, weapontype_t weapon)
337 if(player->class != class)
338 { // player cannot use this weapon, take it anyway, and get mana
339 if(netgame && !deathmatch)
340 { // Can't pick up weapons for other classes in coop netplay
343 if(weapon == WP_SECOND)
345 return P_GiveMana(player, MANA_1, 25);
349 return P_GiveMana(player, MANA_2, 25);
352 if(netgame && !deathmatch)
353 { // Cooperative net-game
354 if(player->weaponowned[weapon])
358 player->bonuscount += BONUSADD;
359 player->weaponowned[weapon] = true;
360 if(weapon == WP_SECOND)
362 P_GiveMana(player, MANA_1, 25);
366 P_GiveMana(player, MANA_2, 25);
368 player->pendingweapon = weapon;
369 if(player == &players[consoleplayer])
371 S_StartSound(NULL, SFX_PICKUP_WEAPON);
375 if(weapon == WP_SECOND)
377 gaveMana = P_GiveMana(player, MANA_1, 25);
381 gaveMana = P_GiveMana(player, MANA_2, 25);
383 if(player->weaponowned[weapon])
390 player->weaponowned[weapon] = true;
391 if(weapon > player->readyweapon)
392 { // Only switch to more powerful weapons
393 player->pendingweapon = weapon;
396 return(gaveWeapon || gaveMana);
400 //===========================================================================
404 //===========================================================================
407 boolean P_GiveWeaponPiece(player_t *player, pclass_t class, int piece)
409 P_GiveMana(player, MANA_1, 20);
410 P_GiveMana(player, MANA_2, 20);
411 if(player->class != class)
415 else if(player->pieces&piece)
416 { // player already has that weapon piece
419 player->pieces |= piece;
420 if(player->pieces == 7)
421 { // player has built the fourth weapon!
422 P_GiveWeapon(player, class, WP_FOURTH);
423 S_StartSound(player->mo, SFX_WEAPON_BUILD);
429 //==========================================================================
431 // TryPickupWeaponPiece
433 //==========================================================================
435 static void TryPickupWeaponPiece(player_t *player, pclass_t matchClass,
436 int pieceValue, mobj_t *pieceMobj)
439 boolean checkAssembled;
442 static char *fourthWeaponText[] =
451 static char *weaponPieceText[] =
454 TXT_WRAITHVERGE_PIECE,
455 TXT_BLOODSCOURGE_PIECE,
460 static int pieceValueTrans[] =
463 WPIECE1|WPIECE2|WPIECE3, // WPIECE1 (1)
464 WPIECE2|WPIECE3, // WPIECE2 (2)
466 WPIECE3 // WPIECE3 (4)
470 checkAssembled = true;
472 // Allow assassin to pick up any weapons
473 if(player->class != matchClass
475 && player->class != PCLASS_ASS
478 { // Wrong class, but try to pick up for mana
479 if(netgame && !deathmatch)
480 { // Can't pick up wrong-class weapons in coop netplay
483 checkAssembled = false;
484 gaveMana = P_GiveMana(player, MANA_1, 20)+
485 P_GiveMana(player, MANA_2, 20);
487 { // Didn't need the mana, so don't pick it up
491 else if(netgame && !deathmatch)
492 { // Cooperative net-game
493 if(player->pieces&pieceValue)
494 { // Already has the piece
497 pieceValue = pieceValueTrans[pieceValue];
498 P_GiveMana(player, MANA_1, 20);
499 P_GiveMana(player, MANA_2, 20);
503 { // Deathmatch or single player game
504 gaveMana = P_GiveMana(player, MANA_1, 20)+
505 P_GiveMana(player, MANA_2, 20);
506 if(player->pieces&pieceValue)
507 { // Already has the piece, check if mana needed
509 { // Didn't need the mana, so don't pick it up
512 checkAssembled = false;
516 // Pick up the weapon piece
517 if(pieceMobj->special)
519 P_ExecuteLineSpecial(pieceMobj->special, pieceMobj->args,
520 NULL, 0, player->mo);
521 pieceMobj->special = 0;
525 if(deathmatch && !(pieceMobj->flags2&MF2_DROPPED))
527 P_HideSpecialThing(pieceMobj);
531 P_RemoveMobj(pieceMobj);
534 player->bonuscount += BONUSADD;
535 if(player == &players[consoleplayer])
537 SB_PaletteFlash(false);
540 // Check if fourth weapon assembled
543 player->pieces |= pieceValue;
544 if(player->pieces == (WPIECE1|WPIECE2|WPIECE3))
547 player->weaponowned[WP_FOURTH] = true;
548 player->pendingweapon = WP_FOURTH;
554 P_SetMessage(player, fourthWeaponText[matchClass], false);
555 // Play the build-sound full volume for all players
556 S_StartSound(NULL, SFX_WEAPON_BUILD);
560 P_SetMessage(player, weaponPieceText[matchClass], false);
561 if(player == &players[consoleplayer])
563 S_StartSound(NULL, SFX_PICKUP_WEAPON);
568 //---------------------------------------------------------------------------
572 // Returns false if the body isn't needed at all.
574 //---------------------------------------------------------------------------
576 boolean P_GiveBody(player_t *player, int num)
581 if(player->morphTics)
583 max = MAXMORPHHEALTH;
585 if(player->health >= max)
589 player->health += num;
590 if(player->health > max)
592 player->health = max;
594 player->mo->health = player->health;
598 //---------------------------------------------------------------------------
602 // Returns false if the armor is worse than the current armor.
604 //---------------------------------------------------------------------------
606 boolean P_GiveArmor(player_t *player, armortype_t armortype, int amount)
611 extern int ArmorMax[NUMCLASSES];
615 hits = ArmorIncrement[player->class][armortype];
616 if(player->armorpoints[armortype] >= hits)
622 player->armorpoints[armortype] = hits;
627 hits = amount*5*FRACUNIT;
628 totalArmor = player->armorpoints[ARMOR_ARMOR]
629 +player->armorpoints[ARMOR_SHIELD]
630 +player->armorpoints[ARMOR_HELMET]
631 +player->armorpoints[ARMOR_AMULET]
632 +AutoArmorSave[player->class];
633 if(totalArmor < ArmorMax[player->class]*5*FRACUNIT)
635 player->armorpoints[armortype] += hits;
645 //---------------------------------------------------------------------------
649 //---------------------------------------------------------------------------
651 int P_GiveKey(player_t *player, keytype_t key)
653 if(player->keys&(1<<key))
657 player->bonuscount += BONUSADD;
658 player->keys |= 1<<key;
662 //---------------------------------------------------------------------------
666 // Returns true if power accepted.
668 //---------------------------------------------------------------------------
670 boolean P_GivePower(player_t *player, powertype_t power)
672 if(power == pw_invulnerability)
674 if(player->powers[power] > BLINKTHRESHOLD)
678 player->powers[power] = INVULNTICS;
679 player->mo->flags2 |= MF2_INVULNERABLE;
680 if(player->class == PCLASS_MAGE)
682 player->mo->flags2 |= MF2_REFLECTIVE;
686 if(power == pw_flight)
688 if(player->powers[power] > BLINKTHRESHOLD)
692 player->powers[power] = FLIGHTTICS;
693 player->mo->flags2 |= MF2_FLY;
694 player->mo->flags |= MF_NOGRAVITY;
695 if(player->mo->z <= player->mo->floorz)
697 player->flyheight = 10; // thrust the player in the air a bit
701 if(power == pw_infrared)
703 if(player->powers[power] > BLINKTHRESHOLD)
707 player->powers[power] = INFRATICS;
710 if(power == pw_speed)
712 if(player->powers[power] > BLINKTHRESHOLD)
716 player->powers[power] = SPEEDTICS;
719 if(power == pw_minotaur)
721 // Doesn't matter if already have power, renew ticker
722 player->powers[power] = MAULATORTICS;
726 if(power == pw_ironfeet)
728 player->powers[power] = IRONTICS;
731 if(power == pw_strength)
733 P_GiveBody(player, 100);
734 player->powers[power] = 1;
738 if(player->powers[power])
740 return(false); // already got it
742 player->powers[power] = 1;
746 //==========================================================================
750 //==========================================================================
752 static void TryPickupArtifact(player_t *player, artitype_t artifactType,
755 static char *artifactMessages[NUMARTIFACTS] =
758 TXT_ARTIINVULNERABILITY,
761 TXT_ARTIHEALINGRADIUS,
768 TXT_ARTITELEPORTOTHER,
776 TXT_ARTIPUZZGEMGREEN1,
777 TXT_ARTIPUZZGEMGREEN2,
778 TXT_ARTIPUZZGEMBLUE1,
779 TXT_ARTIPUZZGEMBLUE2,
786 TXT_ARTIPUZZGEAR, // All gear pickups use the same text
792 if(P_GiveArtifact(player, artifactType, artifact))
794 if(artifact->special)
796 P_ExecuteLineSpecial(artifact->special, artifact->args,
798 artifact->special = 0;
800 player->bonuscount += BONUSADD;
801 if(artifactType < arti_firstpuzzitem)
803 SetDormantArtifact(artifact);
804 S_StartSound(artifact, SFX_PICKUP_ARTIFACT);
805 P_SetMessage(player, artifactMessages[artifactType], false);
809 S_StartSound(NULL, SFX_PICKUP_ITEM);
810 P_SetMessage(player, artifactMessages[artifactType], true);
811 if(!netgame || deathmatch)
812 { // Remove puzzle items if not cooperative netplay
813 P_RemoveMobj(artifact);
819 //---------------------------------------------------------------------------
821 // FUNC P_GiveArtifact
823 // Returns true if artifact accepted.
825 //---------------------------------------------------------------------------
827 boolean P_GiveArtifact(player_t *player, artitype_t arti, mobj_t *mo)
831 boolean slidePointer;
833 slidePointer = false;
835 while(player->inventory[i].type != arti && i < player->inventorySlotNum)
839 if(i == player->inventorySlotNum)
841 if(arti < arti_firstpuzzitem)
844 while(player->inventory[i].type < arti_firstpuzzitem
845 && i < player->inventorySlotNum)
849 if(i != player->inventorySlotNum)
851 for(j = player->inventorySlotNum; j > i; j--)
853 player->inventory[j].count = player->inventory[j-1].count;
854 player->inventory[j].type = player->inventory[j-1].type;
859 player->inventory[i].count = 1;
860 player->inventory[i].type = arti;
861 player->inventorySlotNum++;
865 if(arti >= arti_firstpuzzitem && netgame && !deathmatch)
866 { // Can't carry more than 1 puzzle item in coop netplay
869 if(player->inventory[i].count >= 25)
870 { // Player already has 25 of this item
873 player->inventory[i].count++;
875 if(!player->artifactCount)
877 player->readyArtifact = arti;
879 else if(player == &players[consoleplayer] && slidePointer
889 player->artifactCount++;
893 //==========================================================================
895 // SetDormantArtifact
897 // Removes the MF_SPECIAL flag and initiates the artifact pickup
900 //==========================================================================
902 static void SetDormantArtifact(mobj_t *arti)
904 arti->flags &= ~MF_SPECIAL;
905 if(deathmatch && !(arti->flags2 & MF2_DROPPED))
907 if(arti->type == MT_ARTIINVULNERABILITY)
909 P_SetMobjState(arti, S_DORMANTARTI3_1);
911 else if(arti->type == MT_SUMMONMAULATOR
912 || arti->type == MT_ARTIFLY)
914 P_SetMobjState(arti, S_DORMANTARTI2_1);
918 P_SetMobjState(arti, S_DORMANTARTI1_1);
923 P_SetMobjState(arti, S_DEADARTI1);
927 //---------------------------------------------------------------------------
929 // PROC A_RestoreArtifact
931 //---------------------------------------------------------------------------
933 void A_RestoreArtifact(mobj_t *arti)
935 arti->flags |= MF_SPECIAL;
936 P_SetMobjState(arti, arti->info->spawnstate);
937 S_StartSound(arti, SFX_RESPAWN);
940 //---------------------------------------------------------------------------
942 // PROC A_RestoreSpecialThing1
944 // Make a special thing visible again.
946 //---------------------------------------------------------------------------
948 void A_RestoreSpecialThing1(mobj_t *thing)
950 thing->flags2 &= ~MF2_DONTDRAW;
951 S_StartSound(thing, SFX_RESPAWN);
954 //---------------------------------------------------------------------------
956 // PROC A_RestoreSpecialThing2
958 //---------------------------------------------------------------------------
960 void A_RestoreSpecialThing2(mobj_t *thing)
962 thing->flags |= MF_SPECIAL;
963 P_SetMobjState(thing, thing->info->spawnstate);
966 //---------------------------------------------------------------------------
968 // PROC P_TouchSpecialThing
970 //---------------------------------------------------------------------------
972 void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
979 delta = special->z-toucher->z;
980 if(delta > toucher->height || delta < -32*FRACUNIT)
984 if(toucher->health <= 0)
988 sound = SFX_PICKUP_ITEM;
989 player = toucher->player;
991 switch(special->sprite)
994 case SPR_PTN1: // Item_HealingPotion
995 if(!P_GiveBody(player, 10))
999 P_SetMessage(player, TXT_ITEMHEALTH, false);
1002 if(!P_GiveArmor(player, ARMOR_ARMOR, -1))
1006 P_SetMessage(player, TXT_ARMOR1, false);
1009 if(!P_GiveArmor(player, ARMOR_SHIELD, -1))
1013 P_SetMessage(player, TXT_ARMOR2, false);
1016 if(!P_GiveArmor(player, ARMOR_HELMET, -1))
1020 P_SetMessage(player, TXT_ARMOR3, false);
1023 if(!P_GiveArmor(player, ARMOR_AMULET, -1))
1027 P_SetMessage(player, TXT_ARMOR4, false);
1042 if(!P_GiveKey(player, special->sprite-SPR_KEY1))
1046 P_SetMessage(player, TextKeyMessages[special->sprite-SPR_KEY1],
1048 sound = SFX_PICKUP_KEY;
1050 // Check and process the special now in case the key doesn't
1051 // get removed for coop netplay
1052 if(special->special)
1054 P_ExecuteLineSpecial(special->special, special->args,
1056 special->special = 0;
1060 { // Only remove keys in single player game
1063 player->bonuscount += BONUSADD;
1064 if(player == &players[consoleplayer])
1066 S_StartSound(NULL, sound);
1067 SB_PaletteFlash(false);
1073 TryPickupArtifact(player, arti_health, special);
1076 TryPickupArtifact(player, arti_fly, special);
1079 TryPickupArtifact(player, arti_invulnerability, special);
1082 TryPickupArtifact(player, arti_summon, special);
1085 TryPickupArtifact(player, arti_egg, special);
1088 TryPickupArtifact(player, arti_superhealth, special);
1091 TryPickupArtifact(player, arti_healingradius, special);
1094 TryPickupArtifact(player, arti_torch, special);
1097 TryPickupArtifact(player, arti_teleport, special);
1100 TryPickupArtifact(player, arti_teleportother, special);
1103 TryPickupArtifact(player, arti_poisonbag, special);
1106 TryPickupArtifact(player, arti_speed, special);
1109 TryPickupArtifact(player, arti_boostmana, special);
1112 TryPickupArtifact(player, arti_boostarmor, special);
1115 TryPickupArtifact(player, arti_blastradius, special);
1120 TryPickupArtifact(player, arti_puzzskull, special);
1123 TryPickupArtifact(player, arti_puzzgembig, special);
1126 TryPickupArtifact(player, arti_puzzgemred, special);
1129 TryPickupArtifact(player, arti_puzzgemgreen1, special);
1132 TryPickupArtifact(player, arti_puzzgemgreen2, special);
1135 TryPickupArtifact(player, arti_puzzgemblue1, special);
1138 TryPickupArtifact(player, arti_puzzgemblue2, special);
1141 TryPickupArtifact(player, arti_puzzbook1, special);
1144 TryPickupArtifact(player, arti_puzzbook2, special);
1147 TryPickupArtifact(player, arti_puzzskull2, special);
1150 TryPickupArtifact(player, arti_puzzfweapon, special);
1153 TryPickupArtifact(player, arti_puzzcweapon, special);
1156 TryPickupArtifact(player, arti_puzzmweapon, special);
1159 TryPickupArtifact(player, arti_puzzgear1, special);
1162 TryPickupArtifact(player, arti_puzzgear2, special);
1165 TryPickupArtifact(player, arti_puzzgear3, special);
1168 TryPickupArtifact(player, arti_puzzgear4, special);
1173 if(!P_GiveMana(player, MANA_1, 15))
1177 P_SetMessage(player, TXT_MANA_1, false);
1180 if(!P_GiveMana(player, MANA_2, 15))
1184 P_SetMessage(player, TXT_MANA_2, false);
1186 case SPR_MAN3: // Double Mana Dodecahedron
1187 if(!P_GiveMana(player, MANA_1, 20))
1189 if(!P_GiveMana(player, MANA_2, 20))
1196 P_GiveMana(player, MANA_2, 20);
1198 P_SetMessage(player, TXT_MANA_BOTH, false);
1201 // 2nd and 3rd Mage Weapons
1202 case SPR_WMCS: // Frost Shards
1203 TryPickupWeapon(player, PCLASS_MAGE, WP_SECOND,
1204 special, TXT_WEAPON_M2);
1206 case SPR_WMLG: // Arc of Death
1207 TryPickupWeapon(player, PCLASS_MAGE, WP_THIRD,
1208 special, TXT_WEAPON_M3);
1211 // 2nd and 3rd Fighter Weapons
1212 case SPR_WFAX: // Timon's Axe
1213 TryPickupWeapon(player, PCLASS_FIGHTER, WP_SECOND,
1214 special, TXT_WEAPON_F2);
1216 case SPR_WFHM: // Hammer of Retribution
1217 TryPickupWeapon(player, PCLASS_FIGHTER, WP_THIRD,
1218 special, TXT_WEAPON_F3);
1221 // 2nd and 3rd Cleric Weapons
1222 case SPR_WCSS: // Serpent Staff
1223 TryPickupWeapon(player, PCLASS_CLERIC, WP_SECOND,
1224 special, TXT_WEAPON_C2);
1226 case SPR_WCFM: // Firestorm
1227 TryPickupWeapon(player, PCLASS_CLERIC, WP_THIRD,
1228 special, TXT_WEAPON_C3);
1231 // Fourth Weapon Pieces
1233 TryPickupWeaponPiece(player, PCLASS_FIGHTER, WPIECE1,
1237 TryPickupWeaponPiece(player, PCLASS_FIGHTER, WPIECE2,
1241 TryPickupWeaponPiece(player, PCLASS_FIGHTER, WPIECE3,
1245 TryPickupWeaponPiece(player, PCLASS_CLERIC, WPIECE1,
1249 TryPickupWeaponPiece(player, PCLASS_CLERIC, WPIECE2,
1253 TryPickupWeaponPiece(player, PCLASS_CLERIC, WPIECE3,
1257 TryPickupWeaponPiece(player, PCLASS_MAGE, WPIECE1,
1261 TryPickupWeaponPiece(player, PCLASS_MAGE, WPIECE2,
1265 TryPickupWeaponPiece(player, PCLASS_MAGE, WPIECE3,
1269 // Don't forget to fix this
1271 TryPickupWeaponPiece(player, PCLASS_ASS, WPIECE1,
1275 TryPickupWeaponPiece(player, PCLASS_ASS, WPIECE2,
1279 TryPickupWeaponPiece(player,PCLASS_ASS, WPIECE3,
1285 I_Error("P_SpecialThing: Unknown gettable thing");
1287 if(special->special)
1289 P_ExecuteLineSpecial(special->special, special->args, NULL,
1291 special->special = 0;
1293 if(deathmatch && respawn && !(special->flags2&MF2_DROPPED))
1295 P_HideSpecialThing(special);
1299 P_RemoveMobj(special);
1301 player->bonuscount += BONUSADD;
1302 if(player == &players[consoleplayer])
1304 S_StartSound(NULL, sound);
1305 SB_PaletteFlash(false);
1309 // Search thinker list for minotaur
1310 mobj_t *ActiveMinotaur(player_t *master)
1315 unsigned int *starttime;
1317 for(think = thinkercap.next; think != &thinkercap; think = think->next)
1319 if(think->function != P_MobjThinker) continue;
1320 mo = (mobj_t *)think;
1321 if(mo->type != MT_MINOTAUR) continue;
1322 if(mo->health <= 0) continue;
1323 if(!(mo->flags&MF_COUNTKILL)) continue; // for morphed minotaurs
1324 if(mo->flags&MF_CORPSE) continue;
1325 starttime = (unsigned int *)mo->args;
1326 if ((leveltime - *starttime) >= MAULATORTICS) continue;
1327 plr = ((mobj_t *)mo->special1)->player;
1328 if(plr == master) return(mo);
1334 //---------------------------------------------------------------------------
1338 //---------------------------------------------------------------------------
1340 void P_KillMobj(mobj_t *source, mobj_t *target)
1345 target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY|MF_NOGRAVITY);
1346 target->flags |= MF_CORPSE|MF_DROPOFF;
1347 target->flags2 &= ~MF2_PASSMOBJ;
1348 target->height >>= 2;
1349 if((target->flags&MF_COUNTKILL || target->type == MT_ZBELL)
1351 { // Initiate monster death actions
1352 if(target->type == MT_SORCBOSS)
1355 P_StartACS(target->special, 0, (byte *)&dummy, target,
1360 P_ExecuteLineSpecial(target->special, target->args,
1364 if(source && source->player)
1365 { // Check for frag changes
1368 if(target == source)
1370 target->player->frags[target->player-players]--;
1371 if(cmdfrag && netgame
1372 && source->player == &players[consoleplayer])
1373 { // Send out a frag count packet
1374 NET_SendFrags(source->player);
1379 source->player->frags[target->player-players]++;
1380 if(cmdfrag && netgame
1381 && source->player == &players[consoleplayer])
1382 { // Send out a frag count packet
1383 NET_SendFrags(source->player);
1392 target->player->frags[target->player-players]--;
1393 if(cmdfrag && netgame
1394 && target->player == &players[consoleplayer])
1395 { // Send out a frag count packet
1396 NET_SendFrags(target->player);
1399 target->flags &= ~MF_SOLID;
1400 target->flags2 &= ~MF2_FLY;
1401 target->player->powers[pw_flight] = 0;
1402 target->player->playerstate = PST_DEAD;
1403 P_DropWeapon(target->player);
1404 if(target->flags2&MF2_FIREDAMAGE)
1405 { // Player flame death
1406 switch(target->player->class)
1408 case PCLASS_FIGHTER:
1409 S_StartSound(target, SFX_PLAYER_FIGHTER_BURN_DEATH);
1410 P_SetMobjState(target, S_PLAY_F_FDTH1);
1413 S_StartSound(target, SFX_PLAYER_CLERIC_BURN_DEATH);
1414 P_SetMobjState(target, S_PLAY_C_FDTH1);
1417 S_StartSound(target, SFX_PLAYER_MAGE_BURN_DEATH);
1418 P_SetMobjState(target, S_PLAY_M_FDTH1);
1424 if(target->flags2&MF2_ICEDAMAGE)
1425 { // Player ice death
1426 target->flags &= ~(7<<MF_TRANSSHIFT); //no translation
1427 target->flags |= MF_ICECORPSE;
1428 switch(target->player->class)
1430 case PCLASS_FIGHTER:
1431 P_SetMobjState(target, S_FPLAY_ICE);
1434 P_SetMobjState(target, S_CPLAY_ICE);
1437 P_SetMobjState(target, S_MPLAY_ICE);
1440 P_SetMobjState(target, S_PIG_ICE);
1447 if(target->flags2&MF2_FIREDAMAGE)
1449 if(target->type == MT_FIGHTER_BOSS
1450 || target->type == MT_CLERIC_BOSS
1451 || target->type == MT_MAGE_BOSS)
1453 switch(target->type)
1455 case MT_FIGHTER_BOSS:
1456 S_StartSound(target, SFX_PLAYER_FIGHTER_BURN_DEATH);
1457 P_SetMobjState(target, S_PLAY_F_FDTH1);
1459 case MT_CLERIC_BOSS:
1460 S_StartSound(target, SFX_PLAYER_CLERIC_BURN_DEATH);
1461 P_SetMobjState(target, S_PLAY_C_FDTH1);
1464 S_StartSound(target, SFX_PLAYER_MAGE_BURN_DEATH);
1465 P_SetMobjState(target, S_PLAY_M_FDTH1);
1471 else if(target->type == MT_TREEDESTRUCTIBLE)
1473 P_SetMobjState(target, S_ZTREEDES_X1);
1474 target->height = 24*FRACUNIT;
1475 S_StartSound(target, SFX_TREE_EXPLODE);
1479 if(target->flags2&MF2_ICEDAMAGE)
1481 target->flags |= MF_ICECORPSE;
1482 switch(target->type)
1485 P_SetMobjState(target, S_BISHOP_ICE);
1488 case MT_CENTAURLEADER:
1489 P_SetMobjState(target, S_CENTAUR_ICE);
1493 P_SetMobjState(target, S_DEMON_ICE);
1496 case MT_SERPENTLEADER:
1497 P_SetMobjState(target, S_SERPENT_ICE);
1501 P_SetMobjState(target, S_WRAITH_ICE);
1504 P_SetMobjState(target, S_ETTIN_ICE1);
1507 P_SetMobjState(target, S_FIRED_ICE1);
1509 case MT_FIGHTER_BOSS:
1510 P_SetMobjState(target, S_FIGHTER_ICE);
1512 case MT_CLERIC_BOSS:
1513 P_SetMobjState(target, S_CLERIC_ICE);
1516 P_SetMobjState(target, S_MAGE_ICE);
1519 P_SetMobjState(target, S_PIG_ICE);
1522 target->flags &= ~MF_ICECORPSE;
1527 if(target->type == MT_MINOTAUR)
1529 master = (mobj_t *)target->special1;
1530 if(master->health > 0)
1532 if (!ActiveMinotaur(master->player))
1534 master->player->powers[pw_minotaur] = 0;
1538 else if(target->type == MT_TREEDESTRUCTIBLE)
1540 target->height = 24*FRACUNIT;
1542 if(target->health < -(target->info->spawnhealth>>1)
1543 && target->info->xdeathstate)
1545 P_SetMobjState(target, target->info->xdeathstate);
1549 if ((target->type==MT_FIREDEMON) &&
1550 (target->z <= target->floorz + 2*FRACUNIT) &&
1551 (target->info->xdeathstate))
1553 // This is to fix the imps' staying in fall state
1554 P_SetMobjState(target, target->info->xdeathstate);
1558 P_SetMobjState(target, target->info->deathstate);
1561 target->tics -= P_Random()&3;
1562 // I_StartSound(&actor->r, actor->info->deathsound);
1565 //---------------------------------------------------------------------------
1567 // FUNC P_MinotaurSlam
1569 //---------------------------------------------------------------------------
1571 void P_MinotaurSlam(mobj_t *source, mobj_t *target)
1576 angle = R_PointToAngle2(source->x, source->y, target->x, target->y);
1577 angle >>= ANGLETOFINESHIFT;
1578 thrust = 16*FRACUNIT+(P_Random()<<10);
1579 target->momx += FixedMul(thrust, finecosine[angle]);
1580 target->momy += FixedMul(thrust, finesine[angle]);
1581 P_DamageMobj(target, NULL, source, HITDICE(4));
1584 target->reactiontime = 14+(P_Random()&7);
1586 source->args[0] = 0; // Stop charging
1590 //---------------------------------------------------------------------------
1592 // FUNC P_MorphPlayer
1594 // Returns true if the player gets turned into a pig
1596 //---------------------------------------------------------------------------
1598 boolean P_MorphPlayer(player_t *player)
1609 if(player->powers[pw_invulnerability])
1610 { // Immune when invulnerable
1613 if(player->morphTics)
1614 { // Player is already a beast
1622 oldFlags2 = pmo->flags2;
1623 P_SetMobjState(pmo, S_FREETARGMOBJ);
1624 fog = P_SpawnMobj(x, y, z+TELEFOGHEIGHT, MT_TFOG);
1625 S_StartSound(fog, SFX_TELEPORT);
1626 beastMo = P_SpawnMobj(x, y, z, MT_PIGPLAYER);
1627 beastMo->special1 = player->readyweapon;
1628 beastMo->angle = angle;
1629 beastMo->player = player;
1630 player->health = beastMo->health = MAXMORPHHEALTH;
1631 player->mo = beastMo;
1632 memset(&player->armorpoints[0], 0, NUMARMOR*sizeof(int));
1633 player->class = PCLASS_PIG;
1634 if(oldFlags2&MF2_FLY)
1636 beastMo->flags2 |= MF2_FLY;
1638 player->morphTics = MORPHTICS;
1639 P_ActivateMorphWeapon(player);
1643 //---------------------------------------------------------------------------
1645 // FUNC P_MorphMonster
1647 //---------------------------------------------------------------------------
1649 boolean P_MorphMonster(mobj_t *actor)
1651 mobj_t *master, *monster, *fog;
1658 if(actor->player) return(false);
1659 if(!(actor->flags&MF_COUNTKILL)) return false;
1660 if(actor->flags2&MF2_BOSS) return false;
1661 moType = actor->type;
1666 case MT_FIGHTER_BOSS:
1667 case MT_CLERIC_BOSS:
1674 oldMonster = *actor;
1678 P_RemoveMobjFromTIDList(actor);
1679 P_SetMobjState(actor, S_FREETARGMOBJ);
1680 fog = P_SpawnMobj(x, y, z+TELEFOGHEIGHT, MT_TFOG);
1681 S_StartSound(fog, SFX_TELEPORT);
1682 monster = P_SpawnMobj(x, y, z, MT_PIG);
1683 monster->special2 = moType;
1684 monster->special1 = MORPHTICS+P_Random();
1685 monster->flags |= (oldMonster.flags&MF_SHADOW);
1686 monster->target = oldMonster.target;
1687 monster->angle = oldMonster.angle;
1688 monster->tid = oldMonster.tid;
1689 monster->special = oldMonster.special;
1690 P_InsertMobjIntoTIDList(monster, oldMonster.tid);
1691 memcpy(monster->args, oldMonster.args, 5);
1693 // check for turning off minotaur power for active icon
1694 if (moType==MT_MINOTAUR)
1696 master = (mobj_t *)oldMonster.special1;
1697 if(master->health > 0)
1699 if (!ActiveMinotaur(master->player))
1701 master->player->powers[pw_minotaur] = 0;
1708 //---------------------------------------------------------------------------
1710 // PROC P_AutoUseHealth
1712 //---------------------------------------------------------------------------
1714 void P_AutoUseHealth(player_t *player, int saveHealth)
1723 normalCount = superCount = 0;
1724 for(i = 0; i < player->inventorySlotNum; i++)
1726 if(player->inventory[i].type == arti_health)
1729 normalCount = player->inventory[i].count;
1731 else if(player->inventory[i].type == arti_superhealth)
1734 superCount = player->inventory[i].count;
1737 if((gameskill == sk_baby) && (normalCount*25 >= saveHealth))
1738 { // Use quartz flasks
1739 count = (saveHealth+24)/25;
1740 for(i = 0; i < count; i++)
1742 player->health += 25;
1743 P_PlayerRemoveArtifact(player, normalSlot);
1746 else if(superCount*100 >= saveHealth)
1747 { // Use mystic urns
1748 count = (saveHealth+99)/100;
1749 for(i = 0; i < count; i++)
1751 player->health += 100;
1752 P_PlayerRemoveArtifact(player, superSlot);
1755 else if((gameskill == sk_baby)
1756 && (superCount*100+normalCount*25 >= saveHealth))
1757 { // Use mystic urns and quartz flasks
1758 count = (saveHealth+24)/25;
1759 saveHealth -= count*25;
1760 for(i = 0; i < count; i++)
1762 player->health += 25;
1763 P_PlayerRemoveArtifact(player, normalSlot);
1765 count = (saveHealth+99)/100;
1766 for(i = 0; i < count; i++)
1768 player->health += 100;
1769 P_PlayerRemoveArtifact(player, normalSlot);
1772 player->mo->health = player->health;
1780 = Damages both enemies and players
1781 = inflictor is the thing that caused the damage
1782 = creature or missile, can be NULL (slime, etc)
1783 = source is the thing to target after taking damage
1785 = Source and inflictor are the same for melee attacks
1786 = source can be null for barrel explosions and other environmental stuff
1800 fixed_t savedPercent;
1807 if(!(target->flags&MF_SHOOTABLE))
1812 if(target->health <= 0)
1814 if (inflictor && inflictor->flags2&MF2_ICEDAMAGE)
1818 else if (target->flags&MF_ICECORPSE) // frozen
1821 target->momx = target->momy = 0;
1825 if ((target->flags2&MF2_INVULNERABLE) && damage < 10000)
1826 { // mobj is invulnerable
1827 if(target->player) return; // for player, no exceptions
1830 switch(inflictor->type)
1832 // These inflictors aren't foiled by invulnerability
1834 case MT_POISONCLOUD:
1848 if(damage < 1000 && ((target->player->cheats&CF_GODMODE)
1849 || target->player->powers[pw_invulnerability]))
1854 if(target->flags&MF_SKULLFLY)
1856 target->momx = target->momy = target->momz = 0;
1858 if(target->flags2&MF2_DORMANT)
1860 // Invulnerable, and won't wake up
1863 player = target->player;
1864 if(player && gameskill == sk_baby)
1866 // Take half damage in trainer mode
1869 // Special damage types
1872 switch(inflictor->type)
1877 P_MorphPlayer(player);
1881 P_MorphMonster(target);
1883 return; // Always return
1884 case MT_TELOTHER_FX1:
1885 case MT_TELOTHER_FX2:
1886 case MT_TELOTHER_FX3:
1887 case MT_TELOTHER_FX4:
1888 case MT_TELOTHER_FX5:
1889 if ((target->flags&MF_COUNTKILL) &&
1890 (target->type != MT_SERPENT) &&
1891 (target->type != MT_SERPENTLEADER) &&
1892 (!(target->flags2 & MF2_BOSS)))
1894 P_TeleportOther(target);
1898 if(inflictor->flags&MF_SKULLFLY)
1899 { // Slam only when in charge mode
1900 P_MinotaurSlam(inflictor, target);
1905 // Bishops are just too nasty
1909 switch(inflictor->special2)
1924 case MT_CSTAFF_MISSILE:
1925 // Cleric Serpent Staff does poison damage
1928 P_PoisonPlayer(target->player, source, 20);
1938 P_PoisonPlayer(target->player, source, 20);
1942 case MT_POISONCLOUD:
1945 if(target->player->poisoncount < 4)
1947 P_PoisonDamage(target->player, source,
1948 15+(P_Random()&15), false); // Don't play painsound
1949 P_PoisonPlayer(target->player, source, 50);
1950 S_StartSound(target, SFX_PLAYER_POISONCOUGH);
1954 else if(!(target->flags&MF_COUNTKILL))
1955 { // only damage monsters/players with the poison cloud
1959 case MT_FSWORD_MISSILE:
1962 damage -= damage>>2;
1969 // Push the target unless source is using the gauntlets
1970 if(inflictor && (!source || !source->player)
1971 && !(inflictor->flags2&MF2_NODMGTHRUST))
1973 ang = R_PointToAngle2(inflictor->x, inflictor->y,
1974 target->x, target->y);
1975 //thrust = damage*(FRACUNIT>>3)*100/target->info->mass;
1976 thrust = damage*(FRACUNIT>>3)*150/target->info->mass;
1977 // make fall forwards sometimes
1978 if((damage < 40) && (damage > target->health)
1979 && (target->z-inflictor->z > 64*FRACUNIT) && (P_Random()&1))
1984 ang >>= ANGLETOFINESHIFT;
1985 target->momx += FixedMul(thrust, finecosine[ang]);
1986 target->momy += FixedMul(thrust, finesine[ang]);
1994 savedPercent = AutoArmorSave[player->class]
1995 +player->armorpoints[ARMOR_ARMOR]+player->armorpoints[ARMOR_SHIELD]
1996 +player->armorpoints[ARMOR_HELMET]
1997 +player->armorpoints[ARMOR_AMULET];
1999 { // armor absorbed some damage
2000 if(savedPercent > 100*FRACUNIT)
2002 savedPercent = 100*FRACUNIT;
2004 for(i = 0; i < NUMARMOR; i++)
2006 if(player->armorpoints[i])
2008 player->armorpoints[i] -=
2009 FixedDiv(FixedMul(damage<<FRACBITS,
2010 ArmorIncrement[player->class][i]), 300*FRACUNIT);
2011 if(player->armorpoints[i] < 2*FRACUNIT)
2013 player->armorpoints[i] = 0;
2017 saved = FixedDiv(FixedMul(damage<<FRACBITS, savedPercent),
2019 if(saved > savedPercent*2)
2021 saved = savedPercent*2;
2023 damage -= saved>>FRACBITS;
2025 if(damage >= player->health
2026 && ((gameskill == sk_baby) || deathmatch)
2027 && !player->morphTics)
2028 { // Try to use some inventory health
2029 P_AutoUseHealth(player, damage-player->health+1);
2031 player->health -= damage; // mirror mobj health here for Dave
2032 if(player->health < 0)
2036 player->attacker = source;
2037 player->damagecount += damage; // add damage after armor / invuln
2038 if(player->damagecount > 100)
2040 player->damagecount = 100; // teleport stomp does 10k points...
2042 temp = damage < 100 ? damage : 100;
2043 if(player == &players[consoleplayer])
2045 //I_Tactile(40, 10, 40+temp*2);
2046 SB_PaletteFlash(false);
2053 target->health -= damage;
2054 if(target->health <= 0)
2057 { // check for special fire damage or ice damage deaths
2058 if(inflictor->flags2&MF2_FIREDAMAGE)
2060 if(player && !player->morphTics)
2061 { // Check for flame death
2062 if(target->health > -50 && damage > 25)
2064 target->flags2 |= MF2_FIREDAMAGE;
2069 target->flags2 |= MF2_FIREDAMAGE;
2072 else if(inflictor->flags2&MF2_ICEDAMAGE)
2074 target->flags2 |= MF2_ICEDAMAGE;
2077 if(source && (source->type == MT_MINOTAUR))
2078 { // Minotaur's kills go to his master
2079 master = (mobj_t *)(source->special1);
2080 // Make sure still alive and not a pointer to fighter head
2081 if (master->player && (master->player->mo == master))
2086 if(source && (source->player) &&
2087 (source->player->readyweapon == WP_FOURTH))
2089 // Always extreme death from fourth weapon
2090 target->health = -5000;
2092 P_KillMobj(source, target);
2095 if((P_Random() < target->info->painchance)
2096 && !(target->flags&MF_SKULLFLY))
2098 if(inflictor && (inflictor->type >= MT_LIGHTNING_FLOOR
2099 && inflictor->type <= MT_LIGHTNING_ZAP))
2103 target->flags |= MF_JUSTHIT; // fight back!
2104 P_SetMobjState(target, target->info->painstate);
2107 { // "electrocute" the target
2108 target->frame |= FF_FULLBRIGHT;
2109 if(target->flags&MF_COUNTKILL && P_Random() < 128
2110 && !S_GetSoundPlayingInfo(target, SFX_PUPPYBEAT))
2112 if ((target->type == MT_CENTAUR) ||
2113 (target->type == MT_CENTAURLEADER) ||
2114 (target->type == MT_ETTIN))
2116 S_StartSound(target, SFX_PUPPYBEAT);
2123 target->flags |= MF_JUSTHIT; // fight back!
2124 P_SetMobjState(target, target->info->painstate);
2125 if(inflictor && inflictor->type == MT_POISONCLOUD)
2127 if(target->flags&MF_COUNTKILL && P_Random() < 128
2128 && !S_GetSoundPlayingInfo(target, SFX_PUPPYBEAT))
2130 if ((target->type == MT_CENTAUR) ||
2131 (target->type == MT_CENTAURLEADER) ||
2132 (target->type == MT_ETTIN))
2134 S_StartSound(target, SFX_PUPPYBEAT);
2140 target->reactiontime = 0; // we're awake now...
2141 if(!target->threshold && source && !(source->flags2&MF2_BOSS)
2142 && !(target->type == MT_BISHOP) && !(target->type == MT_MINOTAUR))
2144 // Target actor is not intent on another actor,
2145 // so make him chase after source
2146 if((target->type == MT_CENTAUR && source->type == MT_CENTAURLEADER)
2147 || (target->type == MT_CENTAURLEADER
2148 && source->type == MT_CENTAUR))
2152 target->target = source;
2153 target->threshold = BASETHRESHOLD;
2154 if(target->state == &states[target->info->spawnstate]
2155 && target->info->seestate != S_NULL)
2157 P_SetMobjState(target, target->info->seestate);
2162 //==========================================================================
2166 //==========================================================================
2168 void P_FallingDamage(player_t *player)
2174 mom = abs(player->mo->momz);
2175 dist = FixedMul(mom, 16*FRACUNIT/23);
2177 if(mom >= 63*FRACUNIT)
2178 { // automatic death
2179 P_DamageMobj(player->mo, NULL, NULL, 10000);
2182 damage = ((FixedMul(dist, dist)/10)>>FRACBITS)-24;
2183 if(player->mo->momz > -39*FRACUNIT && damage > player->mo->health
2184 && player->mo->health != 1)
2185 { // No-death threshold
2186 damage = player->mo->health-1;
2188 S_StartSound(player->mo, SFX_PLAYER_LAND);
2189 P_DamageMobj(player->mo, NULL, NULL, damage);
2192 //==========================================================================
2194 // P_PoisonPlayer - Sets up all data concerning poisoning
2196 //==========================================================================
2198 void P_PoisonPlayer(player_t *player, mobj_t *poisoner, int poison)
2200 if((player->cheats&CF_GODMODE) || player->powers[pw_invulnerability])
2204 player->poisoncount += poison;
2205 player->poisoner = poisoner;
2206 if(player->poisoncount > 100)
2208 player->poisoncount = 100;
2212 //==========================================================================
2214 // P_PoisonDamage - Similar to P_DamageMobj
2216 //==========================================================================
2218 void P_PoisonDamage(player_t *player, mobj_t *source, int damage,
2219 boolean playPainSound)
2224 target = player->mo;
2226 if(target->health <= 0)
2230 if(target->flags2&MF2_INVULNERABLE && damage < 10000)
2231 { // mobj is invulnerable
2234 if(player && gameskill == sk_baby)
2236 // Take half damage in trainer mode
2239 if(damage < 1000 && ((player->cheats&CF_GODMODE)
2240 || player->powers[pw_invulnerability]))
2244 if(damage >= player->health
2245 && ((gameskill == sk_baby) || deathmatch)
2246 && !player->morphTics)
2247 { // Try to use some inventory health
2248 P_AutoUseHealth(player, damage-player->health+1);
2250 player->health -= damage; // mirror mobj health here for Dave
2251 if(player->health < 0)
2255 player->attacker = source;
2260 target->health -= damage;
2261 if(target->health <= 0)
2263 target->special1 = damage;
2264 if(player && inflictor && !player->morphTics)
2265 { // Check for flame death
2266 if((inflictor->flags2&MF2_FIREDAMAGE)
2267 && (target->health > -50) && (damage > 25))
2269 target->flags2 |= MF2_FIREDAMAGE;
2271 if(inflictor->flags2&MF2_ICEDAMAGE)
2273 target->flags2 |= MF2_ICEDAMAGE;
2276 P_KillMobj(source, target);
2279 if(!(leveltime&63) && playPainSound)
2281 P_SetMobjState(target, target->info->painstate);
2284 if((P_Random() < target->info->painchance)
2285 && !(target->flags&MF_SKULLFLY))
2287 target->flags |= MF_JUSTHIT; // fight back!
2288 P_SetMobjState(target, target->info->painstate);