23 int maxammo[NUMAMMO] =
33 static int GetWeaponAmmo[NUMWEAPONS] =
46 static weapontype_t GetAmmoChange[] =
57 static boolean GetAmmoChangePL1[NUMWEAPONS][NUMAMMO] =
60 {wp_goldwand, wp_crossbow, wp_blaster, wp_skullrod, -1, wp_mace},
62 {-1, wp_crossbow, wp_blaster, wp_skullrod, -1, wp_mace},
64 {-1, -1, wp_blaster, wp_skullrod, -1, -1},
66 {-1, -1, -1, -1, -1, -1},
68 {-1, -1, -1, -1, -1, -1},
70 {-1, -1, -1, -1, -1, -1},
72 {-1, wp_crossbow, wp_blaster, wp_skullrod, -1, -1},
74 {-1, wp_crossbow, wp_blaster, wp_skullrod, -1, wp_mace}
79 static boolean GetAmmoChangePL2[NUMWEAPONS][NUMAMMO] =
82 {wp_goldwand, wp_crossbow, wp_blaster, wp_skullrod, wp_phoenixrod,
85 {-1, wp_crossbow, wp_blaster, wp_skullrod, wp_phoenixrod, wp_mace},
87 {-1, -1, wp_blaster, wp_skullrod, wp_phoenixrod, -1},
89 {-1, -1, -1, wp_skullrod, wp_phoenixrod, -1},
91 {-1, -1, -1, -1, -1, -1},
93 {-1, -1, -1, -1, -1, -1},
95 {-1, wp_crossbow, wp_blaster, wp_skullrod, -1, -1},
97 {-1, -1, -1, wp_skullrod, wp_phoenixrod, wp_mace}
101 //--------------------------------------------------------------------------
105 //--------------------------------------------------------------------------
109 void P_SetMessage(player_t *player, char *message, boolean ultmsg)
111 extern boolean messageson;
113 if((ultimatemsg || !messageson) && !ultmsg)
117 player->message = message;
118 player->messageTics = MESSAGETICS;
119 BorderTopRefresh = true;
126 //--------------------------------------------------------------------------
130 // Returns true if the player accepted the ammo, false if it was
131 // refused (player has maxammo[ammo]).
133 //--------------------------------------------------------------------------
135 boolean P_GiveAmmo(player_t *player, ammotype_t ammo, int count)
138 //weapontype_t changeWeapon;
140 if(ammo == am_noammo)
144 if(ammo < 0 || ammo > NUMAMMO)
146 I_Error("P_GiveAmmo: bad type %i", ammo);
148 if(player->ammo[ammo] == player->maxammo[ammo])
152 if(gameskill == sk_baby || gameskill == sk_nightmare)
153 { // extra ammo in baby mode and nightmare mode
156 prevAmmo = player->ammo[ammo];
158 player->ammo[ammo] += count;
159 if(player->ammo[ammo] > player->maxammo[ammo])
161 player->ammo[ammo] = player->maxammo[ammo];
165 // Don't attempt to change weapons if the player already had
166 // ammo of the type just given
169 if(player->readyweapon == wp_staff
170 || player->readyweapon == wp_gauntlets)
172 if(player->weaponowned[GetAmmoChange[ammo]])
174 player->pendingweapon = GetAmmoChange[ammo];
178 if(player->powers[pw_weaponlevel2])
180 changeWeapon = GetAmmoChangePL2[player->readyweapon][ammo];
184 changeWeapon = GetAmmoChangePL1[player->readyweapon][ammo];
186 if(changeWeapon != -1)
188 if(player->weaponowned[changeWeapon])
190 player->pendingweapon = changeWeapon;
197 //--------------------------------------------------------------------------
201 // Returns true if the weapon or its ammo was accepted.
203 //--------------------------------------------------------------------------
205 boolean P_GiveWeapon(player_t *player, weapontype_t weapon)
210 if(netgame && !deathmatch)
211 { // Cooperative net-game
212 if(player->weaponowned[weapon])
216 player->bonuscount += BONUSADD;
217 player->weaponowned[weapon] = true;
218 P_GiveAmmo(player, wpnlev1info[weapon].ammo,
219 GetWeaponAmmo[weapon]);
220 player->pendingweapon = weapon;
221 if(player == &players[consoleplayer])
223 S_StartSound(NULL, sfx_wpnup);
227 gaveAmmo = P_GiveAmmo(player, wpnlev1info[weapon].ammo,
228 GetWeaponAmmo[weapon]);
229 if(player->weaponowned[weapon])
236 player->weaponowned[weapon] = true;
237 if(WeaponValue[weapon] > WeaponValue[player->readyweapon])
238 { // Only switch to more powerful weapons
239 player->pendingweapon = weapon;
242 return(gaveWeapon || gaveAmmo);
245 //---------------------------------------------------------------------------
249 // Returns false if the body isn't needed at all.
251 //---------------------------------------------------------------------------
253 boolean P_GiveBody(player_t *player, int num)
258 if(player->chickenTics)
260 max = MAXCHICKENHEALTH;
262 if(player->health >= max)
266 player->health += num;
267 if(player->health > max)
269 player->health = max;
271 player->mo->health = player->health;
275 //---------------------------------------------------------------------------
279 // Returns false if the armor is worse than the current armor.
281 //---------------------------------------------------------------------------
283 boolean P_GiveArmor(player_t *player, int armortype)
287 hits = armortype*100;
288 if(player->armorpoints >= hits)
292 player->armortype = armortype;
293 player->armorpoints = hits;
297 //---------------------------------------------------------------------------
301 //---------------------------------------------------------------------------
303 void P_GiveKey(player_t *player, keytype_t key)
305 extern int playerkeys;
306 extern vertex_t KeyPoints[];
308 if(player->keys[key])
312 if(player == &players[consoleplayer])
314 playerkeys |= 1<<key;
315 KeyPoints[key].x = 0;
316 KeyPoints[key].y = 0;
318 player->bonuscount = BONUSADD;
319 player->keys[key] = true;
322 //---------------------------------------------------------------------------
326 // Returns true if power accepted.
328 //---------------------------------------------------------------------------
330 boolean P_GivePower(player_t *player, powertype_t power)
332 if(power == pw_invulnerability)
334 if(player->powers[power] > BLINKTHRESHOLD)
338 player->powers[power] = INVULNTICS;
341 if(power == pw_weaponlevel2)
343 if(player->powers[power] > BLINKTHRESHOLD)
347 player->powers[power] = WPNLEV2TICS;
350 if(power == pw_invisibility)
352 if(player->powers[power] > BLINKTHRESHOLD)
356 player->powers[power] = INVISTICS;
357 player->mo->flags |= MF_SHADOW;
360 if(power == pw_flight)
362 if(player->powers[power] > BLINKTHRESHOLD)
366 player->powers[power] = FLIGHTTICS;
367 player->mo->flags2 |= MF2_FLY;
368 player->mo->flags |= MF_NOGRAVITY;
369 if(player->mo->z <= player->mo->floorz)
371 player->flyheight = 10; // thrust the player in the air a bit
375 if(power == pw_infrared)
377 if(player->powers[power] > BLINKTHRESHOLD)
381 player->powers[power] = INFRATICS;
385 if(power == pw_ironfeet)
387 player->powers[power] = IRONTICS;
390 if(power == pw_strength)
392 P_GiveBody(player, 100);
393 player->powers[power] = 1;
397 if(player->powers[power])
399 return(false); // already got it
401 player->powers[power] = 1;
405 //---------------------------------------------------------------------------
407 // FUNC P_GiveArtifact
409 // Returns true if artifact accepted.
411 //---------------------------------------------------------------------------
413 boolean P_GiveArtifact(player_t *player, artitype_t arti, mobj_t *mo)
418 while(player->inventory[i].type != arti && i < player->inventorySlotNum)
422 if(i == player->inventorySlotNum)
424 player->inventory[i].count = 1;
425 player->inventory[i].type = arti;
426 player->inventorySlotNum++;
430 if(player->inventory[i].count >= 16)
431 { // Player already has 16 of this item
434 player->inventory[i].count++;
436 if(player->artifactCount == 0)
438 player->readyArtifact = arti;
440 player->artifactCount++;
441 if(mo && (mo->flags&MF_COUNTITEM))
448 //---------------------------------------------------------------------------
450 // PROC P_SetDormantArtifact
452 // Removes the MF_SPECIAL flag, and initiates the artifact pickup
455 //---------------------------------------------------------------------------
457 void P_SetDormantArtifact(mobj_t *arti)
459 arti->flags &= ~MF_SPECIAL;
460 if(deathmatch && (arti->type != MT_ARTIINVULNERABILITY)
461 && (arti->type != MT_ARTIINVISIBILITY))
463 P_SetMobjState(arti, S_DORMANTARTI1);
467 P_SetMobjState(arti, S_DEADARTI1);
469 S_StartSound(arti, sfx_artiup);
472 //---------------------------------------------------------------------------
474 // PROC A_RestoreArtifact
476 //---------------------------------------------------------------------------
478 void A_RestoreArtifact(mobj_t *arti)
480 arti->flags |= MF_SPECIAL;
481 P_SetMobjState(arti, arti->info->spawnstate);
482 S_StartSound(arti, sfx_respawn);
485 //----------------------------------------------------------------------------
487 // PROC P_HideSpecialThing
489 //----------------------------------------------------------------------------
491 void P_HideSpecialThing(mobj_t *thing)
493 thing->flags &= ~MF_SPECIAL;
494 thing->flags2 |= MF2_DONTDRAW;
495 P_SetMobjState(thing, S_HIDESPECIAL1);
498 //---------------------------------------------------------------------------
500 // PROC A_RestoreSpecialThing1
502 // Make a special thing visible again.
504 //---------------------------------------------------------------------------
506 void A_RestoreSpecialThing1(mobj_t *thing)
508 if(thing->type == MT_WMACE)
509 { // Do random mace placement
510 P_RepositionMace(thing);
512 thing->flags2 &= ~MF2_DONTDRAW;
513 S_StartSound(thing, sfx_respawn);
516 //---------------------------------------------------------------------------
518 // PROC A_RestoreSpecialThing2
520 //---------------------------------------------------------------------------
522 void A_RestoreSpecialThing2(mobj_t *thing)
524 thing->flags |= MF_SPECIAL;
525 P_SetMobjState(thing, thing->info->spawnstate);
528 //---------------------------------------------------------------------------
530 // PROC P_TouchSpecialThing
532 //---------------------------------------------------------------------------
534 void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
542 delta = special->z-toucher->z;
543 if(delta > toucher->height || delta < -32*FRACUNIT)
547 if(toucher->health <= 0)
552 player = toucher->player;
554 switch(special->sprite)
557 case SPR_PTN1: // Item_HealingPotion
558 if(!P_GiveBody(player, 10))
562 P_SetMessage(player, TXT_ITEMHEALTH, false);
564 case SPR_SHLD: // Item_Shield1
565 if(!P_GiveArmor(player, 1))
569 P_SetMessage(player, TXT_ITEMSHIELD1, false);
571 case SPR_SHD2: // Item_Shield2
572 if(!P_GiveArmor(player, 2))
576 P_SetMessage(player, TXT_ITEMSHIELD2, false);
578 case SPR_BAGH: // Item_BagOfHolding
579 if(!player->backpack)
581 for(i = 0; i < NUMAMMO; i++)
583 player->maxammo[i] *= 2;
585 player->backpack = true;
587 P_GiveAmmo(player, am_goldwand, AMMO_GWND_WIMPY);
588 P_GiveAmmo(player, am_blaster, AMMO_BLSR_WIMPY);
589 P_GiveAmmo(player, am_crossbow, AMMO_CBOW_WIMPY);
590 P_GiveAmmo(player, am_skullrod, AMMO_SKRD_WIMPY);
591 P_GiveAmmo(player, am_phoenixrod, AMMO_PHRD_WIMPY);
592 P_SetMessage(player, TXT_ITEMBAGOFHOLDING, false);
594 case SPR_SPMP: // Item_SuperMap
595 if(!P_GivePower(player, pw_allmap))
599 P_SetMessage(player, TXT_ITEMSUPERMAP, false);
603 case SPR_BKYY: // Key_Blue
604 if(!player->keys[key_blue])
606 P_SetMessage(player, TXT_GOTBLUEKEY, false);
608 P_GiveKey(player, key_blue);
615 case SPR_CKYY: // Key_Yellow
616 if(!player->keys[key_yellow])
618 P_SetMessage(player, TXT_GOTYELLOWKEY, false);
621 P_GiveKey(player, key_yellow);
627 case SPR_AKYY: // Key_Green
628 if(!player->keys[key_green])
630 P_SetMessage(player, TXT_GOTGREENKEY, false);
633 P_GiveKey(player, key_green);
641 case SPR_PTN2: // Arti_HealingPotion
642 if(P_GiveArtifact(player, arti_health, special))
644 P_SetMessage(player, TXT_ARTIHEALTH, false);
645 P_SetDormantArtifact(special);
648 case SPR_SOAR: // Arti_Fly
649 if(P_GiveArtifact(player, arti_fly, special))
651 P_SetMessage(player, TXT_ARTIFLY, false);
652 P_SetDormantArtifact(special);
655 case SPR_INVU: // Arti_Invulnerability
656 if(P_GiveArtifact(player, arti_invulnerability, special))
658 P_SetMessage(player, TXT_ARTIINVULNERABILITY, false);
659 P_SetDormantArtifact(special);
662 case SPR_PWBK: // Arti_TomeOfPower
663 if(P_GiveArtifact(player, arti_tomeofpower, special))
665 P_SetMessage(player, TXT_ARTITOMEOFPOWER, false);
666 P_SetDormantArtifact(special);
669 case SPR_INVS: // Arti_Invisibility
670 if(P_GiveArtifact(player, arti_invisibility, special))
672 P_SetMessage(player, TXT_ARTIINVISIBILITY, false);
673 P_SetDormantArtifact(special);
676 case SPR_EGGC: // Arti_Egg
677 if(P_GiveArtifact(player, arti_egg, special))
679 P_SetMessage(player, TXT_ARTIEGG, false);
680 P_SetDormantArtifact(special);
683 case SPR_SPHL: // Arti_SuperHealth
684 if(P_GiveArtifact(player, arti_superhealth, special))
686 P_SetMessage(player, TXT_ARTISUPERHEALTH, false);
687 P_SetDormantArtifact(special);
690 case SPR_TRCH: // Arti_Torch
691 if(P_GiveArtifact(player, arti_torch, special))
693 P_SetMessage(player, TXT_ARTITORCH, false);
694 P_SetDormantArtifact(special);
697 case SPR_FBMB: // Arti_FireBomb
698 if(P_GiveArtifact(player, arti_firebomb, special))
700 P_SetMessage(player, TXT_ARTIFIREBOMB, false);
701 P_SetDormantArtifact(special);
704 case SPR_ATLP: // Arti_Teleport
705 if(P_GiveArtifact(player, arti_teleport, special))
707 P_SetMessage(player, TXT_ARTITELEPORT, false);
708 P_SetDormantArtifact(special);
713 case SPR_AMG1: // Ammo_GoldWandWimpy
714 if(!P_GiveAmmo(player, am_goldwand, special->health))
718 P_SetMessage(player, TXT_AMMOGOLDWAND1, false);
720 case SPR_AMG2: // Ammo_GoldWandHefty
721 if(!P_GiveAmmo(player, am_goldwand, special->health))
725 P_SetMessage(player, TXT_AMMOGOLDWAND2, false);
727 case SPR_AMM1: // Ammo_MaceWimpy
728 if(!P_GiveAmmo(player, am_mace, special->health))
732 P_SetMessage(player, TXT_AMMOMACE1, false);
734 case SPR_AMM2: // Ammo_MaceHefty
735 if(!P_GiveAmmo(player, am_mace, special->health))
739 P_SetMessage(player, TXT_AMMOMACE2, false);
741 case SPR_AMC1: // Ammo_CrossbowWimpy
742 if(!P_GiveAmmo(player, am_crossbow, special->health))
746 P_SetMessage(player, TXT_AMMOCROSSBOW1, false);
748 case SPR_AMC2: // Ammo_CrossbowHefty
749 if(!P_GiveAmmo(player, am_crossbow, special->health))
753 P_SetMessage(player, TXT_AMMOCROSSBOW2, false);
755 case SPR_AMB1: // Ammo_BlasterWimpy
756 if(!P_GiveAmmo(player, am_blaster, special->health))
760 P_SetMessage(player, TXT_AMMOBLASTER1, false);
762 case SPR_AMB2: // Ammo_BlasterHefty
763 if(!P_GiveAmmo(player, am_blaster, special->health))
767 P_SetMessage(player, TXT_AMMOBLASTER2, false);
769 case SPR_AMS1: // Ammo_SkullRodWimpy
770 if(!P_GiveAmmo(player, am_skullrod, special->health))
774 P_SetMessage(player, TXT_AMMOSKULLROD1, false);
776 case SPR_AMS2: // Ammo_SkullRodHefty
777 if(!P_GiveAmmo(player, am_skullrod, special->health))
781 P_SetMessage(player, TXT_AMMOSKULLROD2, false);
783 case SPR_AMP1: // Ammo_PhoenixRodWimpy
784 if(!P_GiveAmmo(player, am_phoenixrod, special->health))
788 P_SetMessage(player, TXT_AMMOPHOENIXROD1, false);
790 case SPR_AMP2: // Ammo_PhoenixRodHefty
791 if(!P_GiveAmmo(player, am_phoenixrod, special->health))
795 P_SetMessage(player, TXT_AMMOPHOENIXROD2, false);
799 case SPR_WMCE: // Weapon_Mace
800 if(!P_GiveWeapon(player, wp_mace))
804 P_SetMessage(player, TXT_WPNMACE, false);
807 case SPR_WBOW: // Weapon_Crossbow
808 if(!P_GiveWeapon(player, wp_crossbow))
812 P_SetMessage(player, TXT_WPNCROSSBOW, false);
815 case SPR_WBLS: // Weapon_Blaster
816 if(!P_GiveWeapon(player, wp_blaster))
820 P_SetMessage(player, TXT_WPNBLASTER, false);
823 case SPR_WSKL: // Weapon_SkullRod
824 if(!P_GiveWeapon(player, wp_skullrod))
828 P_SetMessage(player, TXT_WPNSKULLROD, false);
831 case SPR_WPHX: // Weapon_PhoenixRod
832 if(!P_GiveWeapon(player, wp_phoenixrod))
836 P_SetMessage(player, TXT_WPNPHOENIXROD, false);
839 case SPR_WGNT: // Weapon_Gauntlets
840 if(!P_GiveWeapon(player, wp_gauntlets))
844 P_SetMessage(player, TXT_WPNGAUNTLETS, false);
848 I_Error("P_SpecialThing: Unknown gettable thing");
850 if(special->flags&MF_COUNTITEM)
854 if(deathmatch && respawn && !(special->flags&MF_DROPPED))
856 P_HideSpecialThing(special);
860 P_RemoveMobj(special);
862 player->bonuscount += BONUSADD;
863 if(player == &players[consoleplayer])
865 S_StartSound(NULL, sound);
870 //---------------------------------------------------------------------------
874 //---------------------------------------------------------------------------
876 void P_KillMobj(mobj_t *source, mobj_t *target)
878 target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY|MF_NOGRAVITY);
879 target->flags |= MF_CORPSE|MF_DROPOFF;
880 target->flags2 &= ~MF2_PASSMOBJ;
881 target->height >>= 2;
882 if(source && source->player)
884 if(target->flags&MF_COUNTKILL)
885 { // Count for intermission
886 source->player->killcount++;
892 target->player->frags[target->player-players]--;
896 source->player->frags[target->player-players]++;
897 if(source->player == &players[consoleplayer])
899 S_StartSound(NULL, sfx_gfrag);
901 if(source->player->chickenTics)
902 { // Make a super chicken
903 P_GivePower(source->player, pw_weaponlevel2);
908 else if(!netgame && (target->flags&MF_COUNTKILL))
909 { // Count all monster deaths
910 players[0].killcount++;
916 target->player->frags[target->player-players]--;
918 target->flags &= ~MF_SOLID;
919 target->flags2 &= ~MF2_FLY;
920 target->player->powers[pw_flight] = 0;
921 target->player->powers[pw_weaponlevel2] = 0;
922 target->player->playerstate = PST_DEAD;
923 P_DropWeapon(target->player);
924 if(target->flags2&MF2_FIREDAMAGE)
925 { // Player flame death
926 P_SetMobjState(target, S_PLAY_FDTH1);
927 //S_StartSound(target, sfx_hedat1); // Burn sound
931 if(target->health < -(target->info->spawnhealth>>1)
932 && target->info->xdeathstate)
934 P_SetMobjState(target, target->info->xdeathstate);
938 P_SetMobjState(target, target->info->deathstate);
940 target->tics -= P_Random()&3;
941 // I_StartSound(&actor->r, actor->info->deathsound);
944 //---------------------------------------------------------------------------
946 // FUNC P_MinotaurSlam
948 //---------------------------------------------------------------------------
950 void P_MinotaurSlam(mobj_t *source, mobj_t *target)
955 angle = R_PointToAngle2(source->x, source->y, target->x, target->y);
956 angle >>= ANGLETOFINESHIFT;
957 thrust = 16*FRACUNIT+(P_Random()<<10);
958 target->momx += FixedMul(thrust, finecosine[angle]);
959 target->momy += FixedMul(thrust, finesine[angle]);
960 P_DamageMobj(target, NULL, NULL, HITDICE(6));
963 target->reactiontime = 14+(P_Random()&7);
967 //---------------------------------------------------------------------------
969 // FUNC P_TouchWhirlwind
971 //---------------------------------------------------------------------------
973 void P_TouchWhirlwind(mobj_t *target)
977 target->angle += (P_Random()-P_Random())<<20;
978 target->momx += (P_Random()-P_Random())<<10;
979 target->momy += (P_Random()-P_Random())<<10;
980 if(leveltime&16 && !(target->flags2&MF2_BOSS))
982 randVal = P_Random();
987 target->momz += randVal<<10;
988 if(target->momz > 12*FRACUNIT)
990 target->momz = 12*FRACUNIT;
995 P_DamageMobj(target, NULL, NULL, 3);
999 //---------------------------------------------------------------------------
1001 // FUNC P_ChickenMorphPlayer
1003 // Returns true if the player gets turned into a chicken.
1005 //---------------------------------------------------------------------------
1007 boolean P_ChickenMorphPlayer(player_t *player)
1018 if(player->chickenTics)
1020 if((player->chickenTics < CHICKENTICS-TICSPERSEC)
1021 && !player->powers[pw_weaponlevel2])
1022 { // Make a super chicken
1023 P_GivePower(player, pw_weaponlevel2);
1027 if(player->powers[pw_invulnerability])
1028 { // Immune when invulnerable
1036 oldFlags2 = pmo->flags2;
1037 P_SetMobjState(pmo, S_FREETARGMOBJ);
1038 fog = P_SpawnMobj(x, y, z+TELEFOGHEIGHT, MT_TFOG);
1039 S_StartSound(fog, sfx_telept);
1040 chicken = P_SpawnMobj(x, y, z, MT_CHICPLAYER);
1041 chicken->special1 = player->readyweapon;
1042 chicken->angle = angle;
1043 chicken->player = player;
1044 player->health = chicken->health = MAXCHICKENHEALTH;
1045 player->mo = chicken;
1046 player->armorpoints = player->armortype = 0;
1047 player->powers[pw_invisibility] = 0;
1048 player->powers[pw_weaponlevel2] = 0;
1049 if(oldFlags2&MF2_FLY)
1051 chicken->flags2 |= MF2_FLY;
1053 player->chickenTics = CHICKENTICS;
1054 P_ActivateBeak(player);
1058 //---------------------------------------------------------------------------
1060 // FUNC P_ChickenMorph
1062 //---------------------------------------------------------------------------
1064 boolean P_ChickenMorph(mobj_t *actor)
1080 moType = actor->type;
1096 angle = actor->angle;
1097 ghost = actor->flags&MF_SHADOW;
1098 target = actor->target;
1099 P_SetMobjState(actor, S_FREETARGMOBJ);
1100 fog = P_SpawnMobj(x, y, z+TELEFOGHEIGHT, MT_TFOG);
1101 S_StartSound(fog, sfx_telept);
1102 chicken = P_SpawnMobj(x, y, z, MT_CHICKEN);
1103 chicken->special2 = moType;
1104 chicken->special1 = CHICKENTICS+P_Random();
1105 chicken->flags |= ghost;
1106 chicken->target = target;
1107 chicken->angle = angle;
1111 //---------------------------------------------------------------------------
1113 // FUNC P_AutoUseChaosDevice
1115 //---------------------------------------------------------------------------
1117 boolean P_AutoUseChaosDevice(player_t *player)
1121 for(i = 0; i < player->inventorySlotNum; i++)
1123 if(player->inventory[i].type == arti_teleport)
1125 P_PlayerUseArtifact(player, arti_teleport);
1126 player->health = player->mo->health = (player->health+1)/2;
1133 //---------------------------------------------------------------------------
1135 // PROC P_AutoUseHealth
1137 //---------------------------------------------------------------------------
1139 void P_AutoUseHealth(player_t *player, int saveHealth)
1148 normalCount = superCount = 0;
1149 for(i = 0; i < player->inventorySlotNum; i++)
1151 if(player->inventory[i].type == arti_health)
1154 normalCount = player->inventory[i].count;
1156 else if(player->inventory[i].type == arti_superhealth)
1159 superCount = player->inventory[i].count;
1162 if((gameskill == sk_baby) && (normalCount*25 >= saveHealth))
1163 { // Use quartz flasks
1164 count = (saveHealth+24)/25;
1165 for(i = 0; i < count; i++)
1167 player->health += 25;
1168 P_PlayerRemoveArtifact(player, normalSlot);
1171 else if(superCount*100 >= saveHealth)
1172 { // Use mystic urns
1173 count = (saveHealth+99)/100;
1174 for(i = 0; i < count; i++)
1176 player->health += 100;
1177 P_PlayerRemoveArtifact(player, superSlot);
1180 else if((gameskill == sk_baby)
1181 && (superCount*100+normalCount*25 >= saveHealth))
1182 { // Use mystic urns and quartz flasks
1183 count = (saveHealth+24)/25;
1184 saveHealth -= count*25;
1185 for(i = 0; i < count; i++)
1187 player->health += 25;
1188 P_PlayerRemoveArtifact(player, normalSlot);
1190 count = (saveHealth+99)/100;
1191 for(i = 0; i < count; i++)
1193 player->health += 100;
1194 P_PlayerRemoveArtifact(player, normalSlot);
1197 player->mo->health = player->health;
1205 = Damages both enemies and players
1206 = inflictor is the thing that caused the damage
1207 = creature or missile, can be NULL (slime, etc)
1208 = source is the thing to target after taking damage
1210 = Source and inflictor are the same for melee attacks
1211 = source can be null for barrel explosions and other environmental stuff
1229 if(!(target->flags&MF_SHOOTABLE))
1234 if(target->health <= 0)
1238 if(target->flags&MF_SKULLFLY)
1240 if(target->type == MT_MINOTAUR)
1241 { // Minotaur is invulnerable during charge attack
1244 target->momx = target->momy = target->momz = 0;
1246 player = target->player;
1247 if(player && gameskill == sk_baby)
1249 // Take half damage in trainer mode
1252 // Special damage types
1255 switch(inflictor->type)
1260 P_ChickenMorphPlayer(player);
1264 P_ChickenMorph(target);
1266 return; // Always return
1268 P_TouchWhirlwind(target);
1271 if(inflictor->flags&MF_SKULLFLY)
1272 { // Slam only when in charge mode
1273 P_MinotaurSlam(inflictor, target);
1277 case MT_MACEFX4: // Death ball
1278 if((target->flags2&MF2_BOSS) || target->type == MT_HEAD)
1279 { // Don't allow cheap boss kills
1282 else if(target->player)
1283 { // Player specific checks
1284 if(target->player->powers[pw_invulnerability])
1285 { // Can't hurt invulnerable players
1288 if(P_AutoUseChaosDevice(target->player))
1289 { // Player was saved using chaos device
1293 damage = 10000; // Something's gonna die
1295 case MT_PHOENIXFX2: // Flame thrower
1296 if(target->player && P_Random() < 128)
1297 { // Freeze player for a bit
1298 target->reactiontime += 4;
1301 case MT_RAINPLR1: // Rain missiles
1305 if(target->flags2&MF2_BOSS)
1306 { // Decrease damage for bosses
1307 damage = (P_Random()&7)+1;
1312 if(target->type == MT_SORCERER2 && P_Random() < 96)
1313 { // D'Sparil teleports away
1314 P_DSparilTeleport(target);
1320 if(target->type == MT_HEAD)
1321 { // Less damage to Ironlich bosses
1322 damage = P_Random()&1;
1333 // Push the target unless source is using the gauntlets
1334 if(inflictor && (!source || !source->player
1335 || source->player->readyweapon != wp_gauntlets)
1336 && !(inflictor->flags2&MF2_NODMGTHRUST))
1338 ang = R_PointToAngle2(inflictor->x, inflictor->y,
1339 target->x, target->y);
1340 //thrust = damage*(FRACUNIT>>3)*100/target->info->mass;
1341 thrust = damage*(FRACUNIT>>3)*150/target->info->mass;
1342 // make fall forwards sometimes
1343 if((damage < 40) && (damage > target->health)
1344 && (target->z-inflictor->z > 64*FRACUNIT) && (P_Random()&1))
1349 ang >>= ANGLETOFINESHIFT;
1350 if(source && source->player && (source == inflictor)
1351 && source->player->powers[pw_weaponlevel2]
1352 && source->player->readyweapon == wp_staff)
1354 // Staff power level 2
1355 target->momx += FixedMul(10*FRACUNIT, finecosine[ang]);
1356 target->momy += FixedMul(10*FRACUNIT, finesine[ang]);
1357 if(!(target->flags&MF_NOGRAVITY))
1359 target->momz += 5*FRACUNIT;
1364 target->momx += FixedMul(thrust, finecosine[ang]);
1365 target->momy += FixedMul(thrust, finesine[ang]);
1374 // end of game hell hack
1375 //if(target->subsector->sector->special == 11
1376 // && damage >= target->health)
1378 // damage = target->health - 1;
1381 if(damage < 1000 && ((player->cheats&CF_GODMODE)
1382 || player->powers[pw_invulnerability]))
1386 if(player->armortype)
1388 if(player->armortype == 1)
1394 saved = (damage>>1)+(damage>>2);
1396 if(player->armorpoints <= saved)
1399 saved = player->armorpoints;
1400 player->armortype = 0;
1402 player->armorpoints -= saved;
1405 if(damage >= player->health
1406 && ((gameskill == sk_baby) || deathmatch)
1407 && !player->chickenTics)
1408 { // Try to use some inventory health
1409 P_AutoUseHealth(player, damage-player->health+1);
1411 player->health -= damage; // mirror mobj health here for Dave
1412 if(player->health < 0)
1416 player->attacker = source;
1417 player->damagecount += damage; // add damage after armor / invuln
1418 if(player->damagecount > 100)
1420 player->damagecount = 100; // teleport stomp does 10k points...
1422 temp = damage < 100 ? damage : 100;
1423 if(player == &players[consoleplayer])
1432 target->health -= damage;
1433 if(target->health <= 0)
1435 target->special1 = damage;
1436 if(target->type == MT_POD && source && source->type != MT_POD)
1437 { // Make sure players get frags for chain-reaction kills
1438 target->target = source;
1440 if(player && inflictor && !player->chickenTics)
1441 { // Check for flame death
1442 if((inflictor->flags2&MF2_FIREDAMAGE)
1443 || ((inflictor->type == MT_PHOENIXFX1)
1444 && (target->health > -50) && (damage > 25)))
1446 target->flags2 |= MF2_FIREDAMAGE;
1449 P_KillMobj(source, target);
1452 if((P_Random() < target->info->painchance)
1453 && !(target->flags&MF_SKULLFLY))
1455 target->flags |= MF_JUSTHIT; // fight back!
1456 P_SetMobjState(target, target->info->painstate);
1458 target->reactiontime = 0; // we're awake now...
1459 if(!target->threshold && source && !(source->flags2&MF2_BOSS)
1460 && !(target->type == MT_SORCERER2 && source->type == MT_WIZARD))
1462 // Target actor is not intent on another actor,
1463 // so make him chase after source
1464 target->target = source;
1465 target->threshold = BASETHRESHOLD;
1466 if(target->state == &states[target->info->spawnstate]
1467 && target->info->seestate != S_NULL)
1469 P_SetMobjState(target, target->info->seestate);