]> icculus.org git repositories - theoddone33/hhexen.git/blob - base/p_inter.c
osezer patch 003
[theoddone33/hhexen.git] / base / p_inter.c
1
2 //**************************************************************************
3 //**
4 //** p_inter.c : Heretic 2 : Raven Software, Corp.
5 //**
6 //** $RCSfile$
7 //** $Revision$
8 //** $Date$
9 //** $Author$
10 //**
11 //**************************************************************************
12
13 #include "h2def.h"
14 #include "p_local.h"
15 #include "soundst.h"
16
17 #define BONUSADD 6
18
19 int ArmorIncrement[NUMCLASSES][NUMARMOR] =
20 {
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 #ifdef ASSASSIN
25         {20*FRACUNIT, 10*FRACUNIT, 25*FRACUNIT, 5*FRACUNIT },
26 #endif
27         { 0, 0, 0, 0 }
28 };
29
30 int AutoArmorSave[NUMCLASSES] = { 15*FRACUNIT, 10*FRACUNIT, 5*FRACUNIT,
31 #ifdef ASSASSIN
32  10*FRACUNIT,
33 #endif
34  0 };
35
36 char *TextKeyMessages[] = 
37 {
38         TXT_KEY_STEEL,
39         TXT_KEY_CAVE,
40         TXT_KEY_AXE,
41         TXT_KEY_FIRE,
42         TXT_KEY_EMERALD,
43         TXT_KEY_DUNGEON,
44         TXT_KEY_SILVER,
45         TXT_KEY_RUSTED,
46         TXT_KEY_HORN,
47         TXT_KEY_SWAMP,
48         TXT_KEY_CASTLE
49 };
50
51 static void SetDormantArtifact(mobj_t *arti);
52 static void TryPickupArtifact(player_t *player, artitype_t artifactType,
53         mobj_t *artifact);
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);
58
59 /* jim Linux needs this too */
60 /*  #ifdef __NeXT__ */
61 #if defined(__NeXT__) || defined(__linux) || defined(__FreeBSD__)
62 extern void strupr(char *s);
63 #endif
64
65 //--------------------------------------------------------------------------
66 //
67 // PROC P_SetMessage
68 //
69 //--------------------------------------------------------------------------
70
71 void P_SetMessage(player_t *player, char *message, boolean ultmsg)
72 {
73         extern boolean messageson;
74         
75         if((player->ultimateMessage || !messageson) && !ultmsg)
76         {
77                 return;
78         }
79         if(strlen(message) > 79)
80         {
81                 memcpy(player->message, message, 80);
82                 player->message[80] = 0;
83         }
84         else
85         {
86                 strcpy(player->message, message);
87         }
88         strupr(player->message);
89         player->messageTics = MESSAGETICS;
90         player->yellowMessage = false;
91         if(ultmsg)
92         {
93                 player->ultimateMessage = true;
94         }
95         if(player == &players[consoleplayer])
96         {
97                 BorderTopRefresh = true;
98         }
99 }
100
101 //==========================================================================
102 //
103 // P_SetYellowMessage
104 //
105 //==========================================================================
106
107 void P_SetYellowMessage(player_t *player, char *message, boolean ultmsg)
108 {
109         extern boolean messageson;
110         
111         if((player->ultimateMessage || !messageson) && !ultmsg)
112         {
113                 return;
114         }
115         if(strlen(message) > 79)
116         {
117                 memcpy(player->message, message, 80);
118                 player->message[80] = 0;
119         }
120         else
121         {
122                 strcpy(player->message, message);
123         }
124         player->messageTics = 5*MESSAGETICS; // Bold messages last longer
125         player->yellowMessage = true;
126         if(ultmsg)
127         {
128                 player->ultimateMessage = true;
129         }
130         if(player == &players[consoleplayer])
131         {
132                 BorderTopRefresh = true;
133         }
134 }
135
136 //==========================================================================
137 //
138 // P_ClearMessage
139 //
140 //==========================================================================
141
142 void P_ClearMessage(player_t *player)
143 {
144         player->messageTics = 0;
145         if(player == &players[consoleplayer])
146         {
147                 BorderTopRefresh = true;
148         }
149 }
150
151 //----------------------------------------------------------------------------
152 //
153 // PROC P_HideSpecialThing
154 //
155 //----------------------------------------------------------------------------
156
157 void P_HideSpecialThing(mobj_t *thing)
158 {
159         thing->flags &= ~MF_SPECIAL;
160         thing->flags2 |= MF2_DONTDRAW;
161         P_SetMobjState(thing, S_HIDESPECIAL1);
162 }
163
164 //--------------------------------------------------------------------------
165 //
166 // FUNC P_GiveMana
167 //
168 // Returns true if the player accepted the mana, false if it was
169 // refused (player has MAX_MANA).
170 //
171 //--------------------------------------------------------------------------
172
173 boolean P_GiveMana(player_t *player, manatype_t mana, int count)
174 {
175         int prevMana;
176         //weapontype_t changeWeapon;
177
178         if(mana == MANA_NONE || mana == MANA_BOTH)
179         {
180                 return(false);
181         }
182         if(mana < 0 || mana > NUMMANA)
183         {
184                 I_Error("P_GiveMana: bad type %i", mana);
185         }
186         if(player->mana[mana] == MAX_MANA)
187         {
188                 return(false);
189         }
190         if(gameskill == sk_baby || gameskill == sk_nightmare)
191         { // extra mana in baby mode and nightmare mode
192                 count += count>>1;
193         }
194         prevMana = player->mana[mana];
195
196         player->mana[mana] += count;
197         if(player->mana[mana] > MAX_MANA)
198         {
199                 player->mana[mana] = MAX_MANA;
200         }
201         if(player->class == PCLASS_FIGHTER && player->readyweapon == WP_SECOND
202         && mana == MANA_1 && prevMana <= 0)
203         {
204                 P_SetPsprite(player, ps_weapon, S_FAXEREADY_G);
205         }
206         return(true);
207 }
208
209 //==========================================================================
210 //
211 // TryPickupWeapon
212 //
213 //==========================================================================
214
215 static void TryPickupWeapon(player_t *player, pclass_t weaponClass,
216         weapontype_t weaponType, mobj_t *weapon, char *message)
217 {
218         boolean remove;
219         boolean gaveMana;
220         boolean gaveWeapon;
221
222         remove = true;
223         if(player->class != weaponClass
224 #ifdef ASSASSIN
225                 && player->class != PCLASS_ASS
226 #endif
227                 )
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
231                         return;
232                 }
233                 if(weaponType == WP_SECOND)
234                 {
235                         if(!P_GiveMana(player, MANA_1, 25))
236                         {
237                                 return;
238                         }
239                 }
240                 else
241                 {
242                         if(!P_GiveMana(player, MANA_2, 25))
243                         {
244                                 return;
245                         }
246                 }
247         }
248         else if(netgame && !deathmatch)
249         { // Cooperative net-game
250                 if(player->weaponowned[weaponType])
251                 {
252                         return;
253                 }
254                 player->weaponowned[weaponType] = true;
255                 if(weaponType == WP_SECOND)
256                 {
257                         P_GiveMana(player, MANA_1, 25);
258                 }
259                 else
260                 {
261                         P_GiveMana(player, MANA_2, 25);
262                 }
263                 player->pendingweapon = weaponType;
264                 remove = false;
265         }
266         else
267         { // Deathmatch or single player game
268                 if(weaponType == WP_SECOND)
269                 {
270                         gaveMana = P_GiveMana(player, MANA_1, 25);
271                 }
272                 else 
273                 {
274                         gaveMana = P_GiveMana(player, MANA_2, 25);
275                 }
276                 if(player->weaponowned[weaponType])
277                 {
278                         gaveWeapon = false;
279                 }
280                 else
281                 {
282                         gaveWeapon = true;
283                         player->weaponowned[weaponType] = true;
284                         if(weaponType > player->readyweapon)
285                         { // Only switch to more powerful weapons
286                                 player->pendingweapon = weaponType;
287                         }
288                 }
289                 if(!(gaveWeapon || gaveMana))
290                 { // Player didn't need the weapon or any mana
291                         return;
292                 }
293         }
294
295         P_SetMessage(player, message, false);
296         if(weapon->special)
297         {
298                 P_ExecuteLineSpecial(weapon->special, weapon->args,
299                         NULL, 0, player->mo);
300                 weapon->special = 0;
301         }
302
303         if(remove)
304         {
305                 if(deathmatch && !(weapon->flags2&MF2_DROPPED))
306                 {
307                         P_HideSpecialThing(weapon);
308                 }
309                 else
310                 {
311                         P_RemoveMobj(weapon);
312                 }
313         }
314
315         player->bonuscount += BONUSADD;
316         if(player == &players[consoleplayer])
317         {
318                 S_StartSound(NULL, SFX_PICKUP_WEAPON);
319                 SB_PaletteFlash(false);
320         }
321 }
322
323 //--------------------------------------------------------------------------
324 //
325 // FUNC P_GiveWeapon
326 //
327 // Returns true if the weapon or its mana was accepted.
328 //
329 //--------------------------------------------------------------------------
330
331 /*
332 boolean P_GiveWeapon(player_t *player, pclass_t class, weapontype_t weapon)
333 {
334         boolean gaveMana;
335         boolean gaveWeapon;
336
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
341                         return false;
342                 }
343                 if(weapon == WP_SECOND)
344                 {
345                         return P_GiveMana(player, MANA_1, 25);
346                 }
347                 else
348                 {
349                         return P_GiveMana(player, MANA_2, 25);
350                 }               
351         }
352         if(netgame && !deathmatch)
353         { // Cooperative net-game
354                 if(player->weaponowned[weapon])
355                 {
356                         return(false);
357                 }
358                 player->bonuscount += BONUSADD;
359                 player->weaponowned[weapon] = true;
360                 if(weapon == WP_SECOND)
361                 {
362                         P_GiveMana(player, MANA_1, 25);
363                 }
364                 else 
365                 {
366                         P_GiveMana(player, MANA_2, 25);
367                 }
368                 player->pendingweapon = weapon;
369                 if(player == &players[consoleplayer])
370                 {
371                         S_StartSound(NULL, SFX_PICKUP_WEAPON);
372                 }
373                 return(false);
374         }
375         if(weapon == WP_SECOND)
376         {
377                 gaveMana = P_GiveMana(player, MANA_1, 25);
378         }
379         else 
380         {
381                 gaveMana = P_GiveMana(player, MANA_2, 25);
382         }
383         if(player->weaponowned[weapon])
384         {
385                 gaveWeapon = false;
386         }
387         else
388         {
389                 gaveWeapon = true;
390                 player->weaponowned[weapon] = true;
391                 if(weapon > player->readyweapon)
392                 { // Only switch to more powerful weapons
393                         player->pendingweapon = weapon;
394                 }
395         }
396         return(gaveWeapon || gaveMana);
397 }
398 */
399
400 //===========================================================================
401 //
402 // P_GiveWeaponPiece
403 //
404 //===========================================================================
405
406 /*
407 boolean P_GiveWeaponPiece(player_t *player, pclass_t class, int piece)
408 {
409         P_GiveMana(player, MANA_1, 20);
410         P_GiveMana(player, MANA_2, 20);
411         if(player->class != class)
412         {
413                 return true;
414         }
415         else if(player->pieces&piece)
416         { // player already has that weapon piece
417                 return true;
418         }
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);
424         }
425         return true;
426 }
427 */
428
429 //==========================================================================
430 //
431 // TryPickupWeaponPiece
432 //
433 //==========================================================================
434
435 static void TryPickupWeaponPiece(player_t *player, pclass_t matchClass,
436         int pieceValue, mobj_t *pieceMobj)
437 {
438         boolean remove;
439         boolean checkAssembled;
440         boolean gaveWeapon;
441         int gaveMana;
442         static char *fourthWeaponText[] =
443         {
444                 TXT_WEAPON_F4,
445                 TXT_WEAPON_C4,
446                 TXT_WEAPON_M4,
447 #ifdef ASSASSIN
448                 TXT_WEAPON_A4
449 #endif
450         };
451         static char *weaponPieceText[] =
452         {
453                 TXT_QUIETUS_PIECE,
454                 TXT_WRAITHVERGE_PIECE,
455                 TXT_BLOODSCOURGE_PIECE,
456 #ifdef ASSASSIN
457                 TXT_STAFFOFSET_PIECE
458 #endif
459         };
460         static int pieceValueTrans[] =
461         {
462                 0,                                                      // 0: never
463                 WPIECE1|WPIECE2|WPIECE3,        // WPIECE1 (1)
464                 WPIECE2|WPIECE3,                        // WPIECE2 (2)
465                 0,                                                      // 3: never
466                 WPIECE3                                         // WPIECE3 (4)
467         };
468
469         remove = true;
470         checkAssembled = true;
471         gaveWeapon = false;
472         // Allow assassin to pick up any weapons
473         if(player->class != matchClass
474 #ifdef ASSASSIN
475                 && player->class != PCLASS_ASS
476 #endif
477                 )
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
481                         return;
482                 }
483                 checkAssembled = false;
484                 gaveMana = P_GiveMana(player, MANA_1, 20)+
485                         P_GiveMana(player, MANA_2, 20);
486                 if(!gaveMana)
487                 { // Didn't need the mana, so don't pick it up
488                         return;
489                 }
490         }
491         else if(netgame && !deathmatch)
492         { // Cooperative net-game
493                 if(player->pieces&pieceValue)
494                 { // Already has the piece
495                         return;
496                 }
497                 pieceValue = pieceValueTrans[pieceValue];
498                 P_GiveMana(player, MANA_1, 20);
499                 P_GiveMana(player, MANA_2, 20);
500                 remove = false;
501         }
502         else
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
508                         if(!gaveMana)
509                         { // Didn't need the mana, so don't pick it up
510                                 return;
511                         }
512                         checkAssembled = false;
513                 }
514         }
515
516         // Pick up the weapon piece
517         if(pieceMobj->special)
518         {
519                 P_ExecuteLineSpecial(pieceMobj->special, pieceMobj->args,
520                         NULL, 0, player->mo);
521                 pieceMobj->special = 0;
522         }
523         if(remove)
524         {
525                 if(deathmatch && !(pieceMobj->flags2&MF2_DROPPED))
526                 {
527                         P_HideSpecialThing(pieceMobj);
528                 }
529                 else
530                 {
531                         P_RemoveMobj(pieceMobj);
532                 }
533         }
534         player->bonuscount += BONUSADD;
535         if(player == &players[consoleplayer])
536         {
537                 SB_PaletteFlash(false);
538         }
539
540         // Check if fourth weapon assembled
541         if(checkAssembled)
542         {
543                 player->pieces |= pieceValue;
544                 if(player->pieces == (WPIECE1|WPIECE2|WPIECE3))
545                 {
546                         gaveWeapon = true;
547                         player->weaponowned[WP_FOURTH] = true;
548                         player->pendingweapon = WP_FOURTH;
549                 }
550         }
551
552         if(gaveWeapon)
553         {
554                 P_SetMessage(player, fourthWeaponText[matchClass], false);
555                 // Play the build-sound full volume for all players
556                 S_StartSound(NULL, SFX_WEAPON_BUILD);
557         }
558         else
559         {
560                 P_SetMessage(player, weaponPieceText[matchClass], false);
561                 if(player == &players[consoleplayer])
562                 {
563                         S_StartSound(NULL, SFX_PICKUP_WEAPON);
564                 }
565         }
566 }
567
568 //---------------------------------------------------------------------------
569 //
570 // FUNC P_GiveBody
571 //
572 // Returns false if the body isn't needed at all.
573 //
574 //---------------------------------------------------------------------------
575
576 boolean P_GiveBody(player_t *player, int num)
577 {
578         int max;
579
580         max = MAXHEALTH;
581         if(player->morphTics)
582         {
583                 max = MAXMORPHHEALTH;
584         }
585         if(player->health >= max)
586         {
587                 return(false);
588         }
589         player->health += num;
590         if(player->health > max)
591         {
592                 player->health = max;
593         }
594         player->mo->health = player->health;
595         return(true);
596 }
597
598 //---------------------------------------------------------------------------
599 //
600 // FUNC P_GiveArmor
601 //
602 // Returns false if the armor is worse than the current armor.
603 //
604 //---------------------------------------------------------------------------
605
606 boolean P_GiveArmor(player_t *player, armortype_t armortype, int amount)
607 {
608         int hits;
609         int totalArmor;
610
611         extern int ArmorMax[NUMCLASSES];
612
613         if(amount == -1)
614         {
615                 hits = ArmorIncrement[player->class][armortype];
616                 if(player->armorpoints[armortype] >= hits)
617                 {
618                         return false;
619                 }
620                 else
621                 {
622                         player->armorpoints[armortype] = hits;
623                 }
624         }
625         else
626         {
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)
634                 {
635                         player->armorpoints[armortype] += hits;
636                 }
637                 else
638                 {
639                         return false;
640                 }
641         }
642         return true;
643 }
644
645 //---------------------------------------------------------------------------
646 //
647 // PROC P_GiveKey
648 //
649 //---------------------------------------------------------------------------
650
651 int P_GiveKey(player_t *player, keytype_t key)
652 {
653         if(player->keys&(1<<key))
654         {
655                 return false;
656         }
657         player->bonuscount += BONUSADD;
658         player->keys |= 1<<key;
659         return true;
660 }
661
662 //---------------------------------------------------------------------------
663 //
664 // FUNC P_GivePower
665 //
666 // Returns true if power accepted.
667 //
668 //---------------------------------------------------------------------------
669
670 boolean P_GivePower(player_t *player, powertype_t power)
671 {
672         if(power == pw_invulnerability)
673         {
674                 if(player->powers[power] > BLINKTHRESHOLD)
675                 { // Already have it
676                         return(false);
677                 }
678                 player->powers[power] = INVULNTICS;
679                 player->mo->flags2 |= MF2_INVULNERABLE;
680                 if(player->class == PCLASS_MAGE)
681                 {
682                         player->mo->flags2 |= MF2_REFLECTIVE;
683                 }
684                 return(true);
685         }
686         if(power == pw_flight)
687         {
688                 if(player->powers[power] > BLINKTHRESHOLD)
689                 { // Already have it
690                         return(false);
691                 }
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)
696                 {
697                         player->flyheight = 10; // thrust the player in the air a bit
698                 }
699                 return(true);
700         }
701         if(power == pw_infrared)
702         {
703                 if(player->powers[power] > BLINKTHRESHOLD)
704                 { // Already have it
705                         return(false);
706                 }
707                 player->powers[power] = INFRATICS;
708                 return(true);
709         }
710         if(power == pw_speed)
711         {
712                 if(player->powers[power] > BLINKTHRESHOLD)
713                 { // Already have it
714                         return(false);
715                 }
716                 player->powers[power] = SPEEDTICS;
717                 return(true);
718         }
719         if(power == pw_minotaur)
720         {
721                 // Doesn't matter if already have power, renew ticker
722                 player->powers[power] = MAULATORTICS;
723                 return(true);
724         }
725 /*
726         if(power == pw_ironfeet)
727         {
728                 player->powers[power] = IRONTICS;
729                 return(true);
730         }
731         if(power == pw_strength)
732         {
733                 P_GiveBody(player, 100);
734                 player->powers[power] = 1;
735                 return(true);
736         }
737 */
738         if(player->powers[power])
739         {
740                 return(false); // already got it
741         }
742         player->powers[power] = 1;
743         return(true);
744 }
745
746 //==========================================================================
747 //
748 // TryPickupArtifact
749 //
750 //==========================================================================
751
752 static void TryPickupArtifact(player_t *player, artitype_t artifactType,
753         mobj_t *artifact)
754 {
755         static char *artifactMessages[NUMARTIFACTS] =
756         {
757                 NULL,
758                 TXT_ARTIINVULNERABILITY,
759                 TXT_ARTIHEALTH,
760                 TXT_ARTISUPERHEALTH,
761                 TXT_ARTIHEALINGRADIUS,
762                 TXT_ARTISUMMON,
763                 TXT_ARTITORCH,
764                 TXT_ARTIEGG,
765                 TXT_ARTIFLY,
766                 TXT_ARTIBLASTRADIUS,
767                 TXT_ARTIPOISONBAG,
768                 TXT_ARTITELEPORTOTHER,
769                 TXT_ARTISPEED,
770                 TXT_ARTIBOOSTMANA,
771                 TXT_ARTIBOOSTARMOR,
772                 TXT_ARTITELEPORT,
773                 TXT_ARTIPUZZSKULL,
774                 TXT_ARTIPUZZGEMBIG,
775                 TXT_ARTIPUZZGEMRED,
776                 TXT_ARTIPUZZGEMGREEN1,
777                 TXT_ARTIPUZZGEMGREEN2,
778                 TXT_ARTIPUZZGEMBLUE1,
779                 TXT_ARTIPUZZGEMBLUE2,
780                 TXT_ARTIPUZZBOOK1,
781                 TXT_ARTIPUZZBOOK2,
782                 TXT_ARTIPUZZSKULL2,
783                 TXT_ARTIPUZZFWEAPON,
784                 TXT_ARTIPUZZCWEAPON,
785                 TXT_ARTIPUZZMWEAPON,
786                 TXT_ARTIPUZZGEAR,       // All gear pickups use the same text
787                 TXT_ARTIPUZZGEAR,
788                 TXT_ARTIPUZZGEAR,
789                 TXT_ARTIPUZZGEAR
790         };
791
792         if(P_GiveArtifact(player, artifactType, artifact))
793         {
794                 if(artifact->special)
795                 {
796                         P_ExecuteLineSpecial(artifact->special, artifact->args,
797                                 NULL, 0, NULL);
798                         artifact->special = 0;
799                 }
800                 player->bonuscount += BONUSADD;
801                 if(artifactType < arti_firstpuzzitem)
802                 {
803                         SetDormantArtifact(artifact);
804                         S_StartSound(artifact, SFX_PICKUP_ARTIFACT);
805                         P_SetMessage(player, artifactMessages[artifactType], false);
806                 }
807                 else
808                 { // Puzzle item
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);
814                         }
815                 }
816         }
817 }
818
819 //---------------------------------------------------------------------------
820 //
821 // FUNC P_GiveArtifact
822 //
823 // Returns true if artifact accepted.
824 //
825 //---------------------------------------------------------------------------
826
827 boolean P_GiveArtifact(player_t *player, artitype_t arti, mobj_t *mo)
828 {
829         int i;
830         int j;
831         boolean slidePointer;
832
833         slidePointer = false;
834         i = 0;
835         while(player->inventory[i].type != arti && i < player->inventorySlotNum)
836         {
837                 i++;
838         }
839         if(i == player->inventorySlotNum)
840         {
841                 if(arti < arti_firstpuzzitem)
842                 {
843                         i = 0;
844                         while(player->inventory[i].type < arti_firstpuzzitem
845                         && i < player->inventorySlotNum)
846                         {
847                                 i++;
848                         }
849                         if(i != player->inventorySlotNum)
850                         {
851                                 for(j = player->inventorySlotNum; j > i; j--)
852                                 {
853                                         player->inventory[j].count = player->inventory[j-1].count;
854                                         player->inventory[j].type = player->inventory[j-1].type;
855                                         slidePointer = true;
856                                 }
857                         }
858                 }
859                 player->inventory[i].count = 1;
860                 player->inventory[i].type = arti;
861                 player->inventorySlotNum++;
862         }
863         else
864         {
865                 if(arti >= arti_firstpuzzitem && netgame && !deathmatch)
866                 { // Can't carry more than 1 puzzle item in coop netplay
867                         return false;
868                 }
869                 if(player->inventory[i].count >= 25)
870                 { // Player already has 25 of this item
871                         return false;
872                 }
873                 player->inventory[i].count++;
874         }
875         if(!player->artifactCount)
876         {
877                 player->readyArtifact = arti;
878         }
879         else if(player == &players[consoleplayer] && slidePointer
880                 && i <= inv_ptr)
881         {
882                 inv_ptr++;
883                 curpos++;
884                 if(curpos > 6)
885                 {
886                         curpos = 6;
887                 }
888         }
889         player->artifactCount++;
890         return(true);
891 }
892
893 //==========================================================================
894 //
895 // SetDormantArtifact
896 //
897 // Removes the MF_SPECIAL flag and initiates the artifact pickup
898 // animation.
899 //
900 //==========================================================================
901
902 static void SetDormantArtifact(mobj_t *arti)
903 {
904         arti->flags &= ~MF_SPECIAL;
905         if(deathmatch && !(arti->flags2 & MF2_DROPPED))
906         {
907                 if(arti->type == MT_ARTIINVULNERABILITY)
908                 {
909                         P_SetMobjState(arti, S_DORMANTARTI3_1);
910                 }
911                 else if(arti->type == MT_SUMMONMAULATOR
912                         || arti->type == MT_ARTIFLY)
913                 {
914                         P_SetMobjState(arti, S_DORMANTARTI2_1);
915                 }
916                 else
917                 {
918                         P_SetMobjState(arti, S_DORMANTARTI1_1);
919                 }
920         }
921         else
922         { // Don't respawn
923                 P_SetMobjState(arti, S_DEADARTI1);
924         }
925 }
926
927 //---------------------------------------------------------------------------
928 //
929 // PROC A_RestoreArtifact
930 //
931 //---------------------------------------------------------------------------
932
933 void A_RestoreArtifact(mobj_t *arti)
934 {
935         arti->flags |= MF_SPECIAL;
936         P_SetMobjState(arti, arti->info->spawnstate);
937         S_StartSound(arti, SFX_RESPAWN);
938 }
939
940 //---------------------------------------------------------------------------
941 //
942 // PROC A_RestoreSpecialThing1
943 //
944 // Make a special thing visible again.
945 //
946 //---------------------------------------------------------------------------
947
948 void A_RestoreSpecialThing1(mobj_t *thing)
949 {
950         thing->flags2 &= ~MF2_DONTDRAW;
951         S_StartSound(thing, SFX_RESPAWN);
952 }
953
954 //---------------------------------------------------------------------------
955 //
956 // PROC A_RestoreSpecialThing2
957 //
958 //---------------------------------------------------------------------------
959
960 void A_RestoreSpecialThing2(mobj_t *thing)
961 {
962         thing->flags |= MF_SPECIAL;
963         P_SetMobjState(thing, thing->info->spawnstate);
964 }
965
966 //---------------------------------------------------------------------------
967 //
968 // PROC P_TouchSpecialThing
969 //
970 //---------------------------------------------------------------------------
971
972 void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
973 {
974         player_t *player;
975         fixed_t delta;
976         int sound;
977         boolean respawn;
978
979         delta = special->z-toucher->z;
980         if(delta > toucher->height || delta < -32*FRACUNIT)
981         { // Out of reach
982                 return;
983         }
984         if(toucher->health <= 0)
985         { // Toucher is dead
986                 return;
987         }
988         sound = SFX_PICKUP_ITEM;
989         player = toucher->player;
990         respawn = true;
991         switch(special->sprite)
992         {
993                 // Items
994                 case SPR_PTN1: // Item_HealingPotion
995                         if(!P_GiveBody(player, 10))
996                         {
997                                 return;
998                         }
999                         P_SetMessage(player, TXT_ITEMHEALTH, false);
1000                         break;
1001                 case SPR_ARM1:
1002                         if(!P_GiveArmor(player, ARMOR_ARMOR, -1))
1003                         {
1004                                 return;
1005                         }
1006                         P_SetMessage(player, TXT_ARMOR1, false);
1007                         break;
1008                 case SPR_ARM2:
1009                         if(!P_GiveArmor(player, ARMOR_SHIELD, -1))
1010                         {
1011                                 return;
1012                         }
1013                         P_SetMessage(player, TXT_ARMOR2, false);
1014                         break;
1015                 case SPR_ARM3:
1016                         if(!P_GiveArmor(player, ARMOR_HELMET, -1))
1017                         {
1018                                 return;
1019                         }
1020                         P_SetMessage(player, TXT_ARMOR3, false);
1021                         break;
1022                 case SPR_ARM4:
1023                         if(!P_GiveArmor(player, ARMOR_AMULET, -1))
1024                         {
1025                                 return;
1026                         }
1027                         P_SetMessage(player, TXT_ARMOR4, false);
1028                         break;
1029
1030                 // Keys
1031                 case SPR_KEY1:
1032                 case SPR_KEY2:
1033                 case SPR_KEY3:
1034                 case SPR_KEY4:
1035                 case SPR_KEY5:
1036                 case SPR_KEY6:
1037                 case SPR_KEY7:
1038                 case SPR_KEY8:
1039                 case SPR_KEY9:
1040                 case SPR_KEYA:
1041                 case SPR_KEYB:
1042                         if(!P_GiveKey(player, special->sprite-SPR_KEY1))
1043                         {
1044                                 return;
1045                         }
1046                         P_SetMessage(player, TextKeyMessages[special->sprite-SPR_KEY1],
1047                                 true);
1048                         sound = SFX_PICKUP_KEY;
1049
1050                         // Check and process the special now in case the key doesn't
1051                         // get removed for coop netplay
1052                         if(special->special)
1053                         {
1054                                 P_ExecuteLineSpecial(special->special, special->args,
1055                                         NULL, 0, toucher);
1056                                 special->special = 0;
1057                         }
1058
1059                         if(!netgame)
1060                         { // Only remove keys in single player game
1061                                 break;
1062                         }
1063                         player->bonuscount += BONUSADD;
1064                         if(player == &players[consoleplayer])
1065                         {
1066                                 S_StartSound(NULL, sound);
1067                                 SB_PaletteFlash(false);
1068                         }
1069                         return;
1070
1071                 // Artifacts
1072                 case SPR_PTN2:
1073                         TryPickupArtifact(player, arti_health, special);
1074                         return;
1075                 case SPR_SOAR:
1076                         TryPickupArtifact(player, arti_fly, special);
1077                         return;
1078                 case SPR_INVU:
1079                         TryPickupArtifact(player, arti_invulnerability, special);
1080                         return;
1081                 case SPR_SUMN:
1082                         TryPickupArtifact(player, arti_summon, special);
1083                         return;
1084                 case SPR_PORK:
1085                         TryPickupArtifact(player, arti_egg, special);
1086                         return;
1087                 case SPR_SPHL:
1088                         TryPickupArtifact(player, arti_superhealth, special);
1089                         return;
1090                 case SPR_HRAD:
1091                         TryPickupArtifact(player, arti_healingradius, special);
1092                         return;
1093                 case SPR_TRCH:
1094                         TryPickupArtifact(player, arti_torch, special);
1095                         return;
1096                 case SPR_ATLP:
1097                         TryPickupArtifact(player, arti_teleport, special);
1098                         return;
1099                 case SPR_TELO:
1100                         TryPickupArtifact(player, arti_teleportother, special);
1101                         return;
1102                 case SPR_PSBG:
1103                         TryPickupArtifact(player, arti_poisonbag, special);
1104                         return;
1105                 case SPR_SPED:
1106                         TryPickupArtifact(player, arti_speed, special);
1107                         return;
1108                 case SPR_BMAN:
1109                         TryPickupArtifact(player, arti_boostmana, special);
1110                         return;
1111                 case SPR_BRAC:
1112                         TryPickupArtifact(player, arti_boostarmor, special);
1113                         return;
1114                 case SPR_BLST:
1115                         TryPickupArtifact(player, arti_blastradius, special);
1116                         return;
1117
1118                 // Puzzle artifacts
1119                 case SPR_ASKU:
1120                         TryPickupArtifact(player, arti_puzzskull, special);
1121                         return;
1122                 case SPR_ABGM:
1123                         TryPickupArtifact(player, arti_puzzgembig, special);
1124                         return;
1125                 case SPR_AGMR:
1126                         TryPickupArtifact(player, arti_puzzgemred, special);
1127                         return;
1128                 case SPR_AGMG:
1129                         TryPickupArtifact(player, arti_puzzgemgreen1, special);
1130                         return;
1131                 case SPR_AGG2:
1132                         TryPickupArtifact(player, arti_puzzgemgreen2, special);
1133                         return;
1134                 case SPR_AGMB:
1135                         TryPickupArtifact(player, arti_puzzgemblue1, special);
1136                         return;
1137                 case SPR_AGB2:
1138                         TryPickupArtifact(player, arti_puzzgemblue2, special);
1139                         return;
1140                 case SPR_ABK1:
1141                         TryPickupArtifact(player, arti_puzzbook1, special);
1142                         return;
1143                 case SPR_ABK2:
1144                         TryPickupArtifact(player, arti_puzzbook2, special);
1145                         return;
1146                 case SPR_ASK2:
1147                         TryPickupArtifact(player, arti_puzzskull2, special);
1148                         return;
1149                 case SPR_AFWP:
1150                         TryPickupArtifact(player, arti_puzzfweapon, special);
1151                         return;
1152                 case SPR_ACWP:
1153                         TryPickupArtifact(player, arti_puzzcweapon, special);
1154                         return;
1155                 case SPR_AMWP:
1156                         TryPickupArtifact(player, arti_puzzmweapon, special);
1157                         return;
1158                 case SPR_AGER:
1159                         TryPickupArtifact(player, arti_puzzgear1, special);
1160                         return;
1161                 case SPR_AGR2:
1162                         TryPickupArtifact(player, arti_puzzgear2, special);
1163                         return;
1164                 case SPR_AGR3:
1165                         TryPickupArtifact(player, arti_puzzgear3, special);
1166                         return;
1167                 case SPR_AGR4:
1168                         TryPickupArtifact(player, arti_puzzgear4, special);
1169                         return;
1170
1171                 // Mana
1172                 case SPR_MAN1:
1173                         if(!P_GiveMana(player, MANA_1, 15))
1174                         {
1175                                 return;
1176                         }
1177                         P_SetMessage(player, TXT_MANA_1, false);
1178                         break;
1179                 case SPR_MAN2: 
1180                         if(!P_GiveMana(player, MANA_2, 15))
1181                         {
1182                                 return;
1183                         }
1184                         P_SetMessage(player, TXT_MANA_2, false);
1185                         break;
1186                 case SPR_MAN3: // Double Mana Dodecahedron
1187                         if(!P_GiveMana(player, MANA_1, 20))
1188                         {
1189                                 if(!P_GiveMana(player, MANA_2, 20))
1190                                 {
1191                                         return;
1192                                 }
1193                         }
1194                         else
1195                         {
1196                                 P_GiveMana(player, MANA_2, 20);
1197                         }
1198                         P_SetMessage(player, TXT_MANA_BOTH, false);
1199                         break;
1200
1201                 // 2nd and 3rd Mage Weapons
1202                 case SPR_WMCS: // Frost Shards
1203                         TryPickupWeapon(player, PCLASS_MAGE, WP_SECOND,
1204                                 special, TXT_WEAPON_M2);
1205                         return;
1206                 case SPR_WMLG: // Arc of Death
1207                         TryPickupWeapon(player, PCLASS_MAGE, WP_THIRD,
1208                                 special, TXT_WEAPON_M3);
1209                         return;
1210
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);
1215                         return;
1216                 case SPR_WFHM: // Hammer of Retribution
1217                         TryPickupWeapon(player, PCLASS_FIGHTER, WP_THIRD,
1218                                 special, TXT_WEAPON_F3);
1219                         return;
1220
1221                 // 2nd and 3rd Cleric Weapons
1222                 case SPR_WCSS: // Serpent Staff
1223                         TryPickupWeapon(player, PCLASS_CLERIC, WP_SECOND,
1224                                 special, TXT_WEAPON_C2);
1225                         return;
1226                 case SPR_WCFM: // Firestorm
1227                         TryPickupWeapon(player, PCLASS_CLERIC, WP_THIRD,
1228                                 special, TXT_WEAPON_C3);
1229                         return;
1230
1231                 // Fourth Weapon Pieces
1232                 case SPR_WFR1:
1233                         TryPickupWeaponPiece(player, PCLASS_FIGHTER, WPIECE1,
1234                                 special);
1235                         return;
1236                 case SPR_WFR2:
1237                         TryPickupWeaponPiece(player, PCLASS_FIGHTER, WPIECE2,
1238                                 special);
1239                         return;
1240                 case SPR_WFR3:
1241                         TryPickupWeaponPiece(player, PCLASS_FIGHTER, WPIECE3,
1242                                 special);
1243                         return;
1244                 case SPR_WCH1:
1245                         TryPickupWeaponPiece(player, PCLASS_CLERIC, WPIECE1,
1246                                 special);
1247                         return;
1248                 case SPR_WCH2:
1249                         TryPickupWeaponPiece(player, PCLASS_CLERIC, WPIECE2,
1250                                 special);
1251                         return;
1252                 case SPR_WCH3:
1253                         TryPickupWeaponPiece(player, PCLASS_CLERIC, WPIECE3,
1254                                 special);
1255                         return;
1256                 case SPR_WMS1:
1257                         TryPickupWeaponPiece(player, PCLASS_MAGE, WPIECE1,
1258                                 special);
1259                         return;
1260                 case SPR_WMS2:
1261                         TryPickupWeaponPiece(player, PCLASS_MAGE, WPIECE2,
1262                                 special);
1263                         return;
1264                 case SPR_WMS3:
1265                         TryPickupWeaponPiece(player, PCLASS_MAGE, WPIECE3,
1266                                 special);
1267                         return;
1268 #ifdef ASSASSIN
1269 // Don't forget to fix this
1270 /*              case SPR_WAS1:
1271                         TryPickupWeaponPiece(player, PCLASS_ASS, WPIECE1,
1272                                  special);
1273                         return;
1274                 case SPR_WAS2:
1275                         TryPickupWeaponPiece(player, PCLASS_ASS, WPIECE2,
1276                                  special);
1277                         return;
1278                 case SPR_WAS3:
1279                         TryPickupWeaponPiece(player,PCLASS_ASS, WPIECE3,
1280                                  special);
1281                         return;
1282 */
1283 #endif
1284                 default:
1285                         I_Error("P_SpecialThing: Unknown gettable thing");
1286         }
1287         if(special->special)
1288         {
1289                 P_ExecuteLineSpecial(special->special, special->args, NULL,
1290                         0, toucher);
1291                 special->special = 0;
1292         }
1293         if(deathmatch && respawn && !(special->flags2&MF2_DROPPED))
1294         {
1295                 P_HideSpecialThing(special);
1296         }
1297         else
1298         {
1299                 P_RemoveMobj(special);
1300         }
1301         player->bonuscount += BONUSADD;
1302         if(player == &players[consoleplayer])
1303         {
1304                 S_StartSound(NULL, sound);
1305                 SB_PaletteFlash(false);
1306         }
1307 }
1308
1309 // Search thinker list for minotaur
1310 mobj_t *ActiveMinotaur(player_t *master)
1311 {
1312         mobj_t *mo;
1313         player_t *plr;
1314         thinker_t *think;
1315         unsigned int *starttime;
1316
1317         for(think = thinkercap.next; think != &thinkercap; think = think->next)
1318         {
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);
1329         }
1330         return(NULL);
1331 }
1332
1333
1334 //---------------------------------------------------------------------------
1335 //
1336 // PROC P_KillMobj
1337 //
1338 //---------------------------------------------------------------------------
1339
1340 void P_KillMobj(mobj_t *source, mobj_t *target)
1341 {
1342         int dummy;
1343         mobj_t *master;
1344
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) 
1350                  && target->special)
1351         { // Initiate monster death actions
1352                 if(target->type == MT_SORCBOSS)
1353                 {
1354                         dummy = 0;
1355                         P_StartACS(target->special, 0, (byte *)&dummy, target,
1356                                 NULL, 0);
1357                 }
1358                 else
1359                 {
1360                         P_ExecuteLineSpecial(target->special, target->args,
1361                                 NULL, 0, target);
1362                 }
1363         }
1364         if(source && source->player)
1365         { // Check for frag changes
1366                 if(target->player)
1367                 {
1368                         if(target == source)
1369                         { // Self-frag
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);
1375                                 }
1376                         }
1377                         else
1378                         {
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);
1384                                 }
1385                         }
1386                 }
1387         }
1388         if(target->player)
1389         { // Player death
1390                 if(!source)
1391                 { // Self-frag
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);
1397                         }
1398                 }
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)
1407                         {
1408                                 case PCLASS_FIGHTER:
1409                                         S_StartSound(target, SFX_PLAYER_FIGHTER_BURN_DEATH);
1410                                         P_SetMobjState(target, S_PLAY_F_FDTH1);
1411                                         return;
1412                                 case PCLASS_CLERIC:
1413                                         S_StartSound(target, SFX_PLAYER_CLERIC_BURN_DEATH);
1414                                         P_SetMobjState(target, S_PLAY_C_FDTH1);
1415                                         return;
1416                                 case PCLASS_MAGE:
1417                                         S_StartSound(target, SFX_PLAYER_MAGE_BURN_DEATH);
1418                                         P_SetMobjState(target, S_PLAY_M_FDTH1);
1419                                         return;
1420                                 default:
1421                                         break;
1422                         }
1423                 }
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)
1429                         {
1430                                 case PCLASS_FIGHTER:
1431                                         P_SetMobjState(target, S_FPLAY_ICE);
1432                                         return;
1433                                 case PCLASS_CLERIC:
1434                                         P_SetMobjState(target, S_CPLAY_ICE);
1435                                         return;
1436                                 case PCLASS_MAGE:
1437                                         P_SetMobjState(target, S_MPLAY_ICE);
1438                                         return;
1439                                 case PCLASS_PIG:
1440                                         P_SetMobjState(target, S_PIG_ICE);
1441                                         return;
1442                                 default:
1443                                         break;
1444                         }
1445                 }
1446         }
1447         if(target->flags2&MF2_FIREDAMAGE)
1448         {
1449                 if(target->type == MT_FIGHTER_BOSS 
1450                         || target->type == MT_CLERIC_BOSS
1451                         || target->type == MT_MAGE_BOSS)
1452                 {
1453                         switch(target->type)
1454                         {
1455                                 case MT_FIGHTER_BOSS:
1456                                         S_StartSound(target, SFX_PLAYER_FIGHTER_BURN_DEATH);
1457                                         P_SetMobjState(target, S_PLAY_F_FDTH1);
1458                                         return;
1459                                 case MT_CLERIC_BOSS:
1460                                         S_StartSound(target, SFX_PLAYER_CLERIC_BURN_DEATH);
1461                                         P_SetMobjState(target, S_PLAY_C_FDTH1);
1462                                         return;
1463                                 case MT_MAGE_BOSS:
1464                                         S_StartSound(target, SFX_PLAYER_MAGE_BURN_DEATH);
1465                                         P_SetMobjState(target, S_PLAY_M_FDTH1);
1466                                         return;
1467                                 default:
1468                                         break;
1469                         }
1470                 }
1471                 else if(target->type == MT_TREEDESTRUCTIBLE)
1472                 {
1473                         P_SetMobjState(target, S_ZTREEDES_X1);
1474                         target->height = 24*FRACUNIT;
1475                         S_StartSound(target, SFX_TREE_EXPLODE);
1476                         return;
1477                 }
1478         }
1479         if(target->flags2&MF2_ICEDAMAGE)
1480         {
1481                 target->flags |= MF_ICECORPSE;
1482                 switch(target->type)
1483                 {
1484                         case MT_BISHOP:
1485                                 P_SetMobjState(target, S_BISHOP_ICE);
1486                                 return;         
1487                         case MT_CENTAUR:
1488                         case MT_CENTAURLEADER:
1489                                 P_SetMobjState(target, S_CENTAUR_ICE);
1490                                 return;         
1491                         case MT_DEMON:
1492                         case MT_DEMON2:
1493                                 P_SetMobjState(target, S_DEMON_ICE);
1494                                 return;         
1495                         case MT_SERPENT:
1496                         case MT_SERPENTLEADER:
1497                                 P_SetMobjState(target, S_SERPENT_ICE);
1498                                 return;         
1499                         case MT_WRAITH:
1500                         case MT_WRAITHB:
1501                                 P_SetMobjState(target, S_WRAITH_ICE);
1502                                 return;
1503                         case MT_ETTIN:
1504                                 P_SetMobjState(target, S_ETTIN_ICE1);
1505                                 return;
1506                         case MT_FIREDEMON:
1507                                 P_SetMobjState(target, S_FIRED_ICE1);
1508                                 return;
1509                         case MT_FIGHTER_BOSS:
1510                                 P_SetMobjState(target, S_FIGHTER_ICE);
1511                                 return;
1512                         case MT_CLERIC_BOSS:
1513                                 P_SetMobjState(target, S_CLERIC_ICE);
1514                                 return;
1515                         case MT_MAGE_BOSS:
1516                                 P_SetMobjState(target, S_MAGE_ICE);
1517                                 return;
1518                         case MT_PIG:
1519                                 P_SetMobjState(target, S_PIG_ICE);
1520                                 return;
1521                         default:
1522                                 target->flags &= ~MF_ICECORPSE;
1523                                 break;
1524                 }
1525         }
1526
1527         if(target->type == MT_MINOTAUR)
1528         {
1529                 master = (mobj_t *)target->special1;
1530                 if(master->health > 0)
1531                 {
1532                         if (!ActiveMinotaur(master->player))
1533                         {
1534                                 master->player->powers[pw_minotaur] = 0;
1535                         }
1536                 }               
1537         }
1538         else if(target->type == MT_TREEDESTRUCTIBLE)
1539         {
1540                 target->height = 24*FRACUNIT;
1541         }
1542         if(target->health < -(target->info->spawnhealth>>1)
1543                 && target->info->xdeathstate)
1544         { // Extreme death
1545                 P_SetMobjState(target, target->info->xdeathstate);
1546         }
1547         else
1548         { // Normal death
1549                 if ((target->type==MT_FIREDEMON) &&
1550                         (target->z <= target->floorz + 2*FRACUNIT) &&
1551                         (target->info->xdeathstate))
1552                 {
1553                         // This is to fix the imps' staying in fall state
1554                         P_SetMobjState(target, target->info->xdeathstate);
1555                 }
1556                 else
1557                 {
1558                         P_SetMobjState(target, target->info->deathstate);
1559                 }
1560         }
1561         target->tics -= P_Random()&3;
1562 //      I_StartSound(&actor->r, actor->info->deathsound);
1563 }
1564
1565 //---------------------------------------------------------------------------
1566 //
1567 // FUNC P_MinotaurSlam
1568 //
1569 //---------------------------------------------------------------------------
1570
1571 void P_MinotaurSlam(mobj_t *source, mobj_t *target)
1572 {
1573         angle_t angle;
1574         fixed_t thrust;
1575
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));
1582         if(target->player)
1583         {
1584                 target->reactiontime = 14+(P_Random()&7);
1585         }
1586         source->args[0] = 0;                    // Stop charging
1587 }
1588
1589
1590 //---------------------------------------------------------------------------
1591 //
1592 // FUNC P_MorphPlayer
1593 //
1594 // Returns true if the player gets turned into a pig
1595 //
1596 //---------------------------------------------------------------------------
1597
1598 boolean P_MorphPlayer(player_t *player)
1599 {
1600         mobj_t *pmo;
1601         mobj_t *fog;
1602         mobj_t *beastMo;
1603         fixed_t x;
1604         fixed_t y;
1605         fixed_t z;
1606         angle_t angle;
1607         int oldFlags2;
1608
1609         if(player->powers[pw_invulnerability])
1610         { // Immune when invulnerable
1611                 return(false);
1612         }
1613         if(player->morphTics)
1614         { // Player is already a beast
1615                 return false;
1616         }
1617         pmo = player->mo;
1618         x = pmo->x;
1619         y = pmo->y;
1620         z = pmo->z;
1621         angle = pmo->angle;
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)
1635         {
1636                 beastMo->flags2 |= MF2_FLY;
1637         }
1638         player->morphTics = MORPHTICS;
1639         P_ActivateMorphWeapon(player);
1640         return(true);
1641 }
1642
1643 //---------------------------------------------------------------------------
1644 //
1645 // FUNC P_MorphMonster
1646 //
1647 //---------------------------------------------------------------------------
1648
1649 boolean P_MorphMonster(mobj_t *actor)
1650 {
1651         mobj_t *master, *monster, *fog;
1652         mobjtype_t moType;
1653         fixed_t x;
1654         fixed_t y;
1655         fixed_t z;
1656         mobj_t oldMonster;
1657
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;
1662         switch(moType)
1663         {
1664                 case MT_PIG:
1665                         return(false);
1666                 case MT_FIGHTER_BOSS:
1667                 case MT_CLERIC_BOSS:
1668                 case MT_MAGE_BOSS:
1669                         return(false);
1670                 default:
1671                         break;
1672         }
1673
1674         oldMonster = *actor;
1675         x = oldMonster.x;
1676         y = oldMonster.y;
1677         z = oldMonster.z;
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);
1692
1693         // check for turning off minotaur power for active icon
1694         if (moType==MT_MINOTAUR)
1695         {
1696                 master = (mobj_t *)oldMonster.special1;
1697                 if(master->health > 0)
1698                 {
1699                         if (!ActiveMinotaur(master->player))
1700                         {
1701                                 master->player->powers[pw_minotaur] = 0;
1702                         }
1703                 }               
1704         }
1705         return(true);
1706 }
1707
1708 //---------------------------------------------------------------------------
1709 //
1710 // PROC P_AutoUseHealth
1711 //
1712 //---------------------------------------------------------------------------
1713
1714 void P_AutoUseHealth(player_t *player, int saveHealth)
1715 {
1716         int i;
1717         int count;
1718         int normalCount;
1719         int normalSlot=0;
1720         int superCount;
1721         int superSlot=0;
1722
1723         normalCount = superCount = 0;
1724         for(i = 0; i < player->inventorySlotNum; i++)
1725         {
1726                 if(player->inventory[i].type == arti_health)
1727                 {
1728                         normalSlot = i;
1729                         normalCount = player->inventory[i].count;
1730                 }
1731                 else if(player->inventory[i].type == arti_superhealth)
1732                 {
1733                         superSlot = i;
1734                         superCount = player->inventory[i].count;
1735                 }
1736         }
1737         if((gameskill == sk_baby) && (normalCount*25 >= saveHealth))
1738         { // Use quartz flasks
1739                 count = (saveHealth+24)/25;
1740                 for(i = 0; i < count; i++)
1741                 {
1742                         player->health += 25;
1743                         P_PlayerRemoveArtifact(player, normalSlot);
1744                 }
1745         }
1746         else if(superCount*100 >= saveHealth)
1747         { // Use mystic urns
1748                 count = (saveHealth+99)/100;
1749                 for(i = 0; i < count; i++)
1750                 {
1751                         player->health += 100;
1752                         P_PlayerRemoveArtifact(player, superSlot);
1753                 }
1754         }
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++)
1761                 {
1762                         player->health += 25;
1763                         P_PlayerRemoveArtifact(player, normalSlot);
1764                 }
1765                 count = (saveHealth+99)/100;
1766                 for(i = 0; i < count; i++)
1767                 {
1768                         player->health += 100;
1769                         P_PlayerRemoveArtifact(player, normalSlot);
1770                 }
1771         }
1772         player->mo->health = player->health;
1773 }
1774
1775 /*
1776 =================
1777 =
1778 = P_DamageMobj
1779 =
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
1784 =               creature or NULL
1785 = Source and inflictor are the same for melee attacks
1786 = source can be null for barrel explosions and other environmental stuff
1787 ==================
1788 */
1789
1790 void P_DamageMobj
1791 (
1792         mobj_t *target,
1793         mobj_t *inflictor,
1794         mobj_t *source,
1795         int     damage
1796 )
1797 {
1798         unsigned ang;
1799         int saved;
1800         fixed_t savedPercent;
1801         player_t *player;
1802         mobj_t *master;
1803         fixed_t thrust;
1804         int temp;
1805         int i;
1806
1807         if(!(target->flags&MF_SHOOTABLE))
1808         {
1809                 // Shouldn't happen
1810                 return;
1811         }
1812         if(target->health <= 0)
1813         {
1814                 if (inflictor && inflictor->flags2&MF2_ICEDAMAGE)
1815                 {
1816                         return;
1817                 }
1818                 else if (target->flags&MF_ICECORPSE) // frozen
1819                 {
1820                         target->tics = 1;
1821                         target->momx = target->momy = 0;
1822                 }
1823                 return;
1824         }
1825         if ((target->flags2&MF2_INVULNERABLE) && damage < 10000)
1826         { // mobj is invulnerable
1827                 if(target->player) return;      // for player, no exceptions
1828                 if(inflictor)
1829                 {
1830                         switch(inflictor->type)
1831                         {
1832                                 // These inflictors aren't foiled by invulnerability
1833                                 case MT_HOLY_FX:
1834                                 case MT_POISONCLOUD:
1835                                 case MT_FIREBOMB:
1836                                         break;
1837                                 default:
1838                                         return;
1839                         }
1840                 }
1841                 else
1842                 {
1843                         return;
1844                 }
1845         }
1846         if(target->player)
1847         {
1848                 if(damage < 1000 && ((target->player->cheats&CF_GODMODE)
1849                         || target->player->powers[pw_invulnerability]))
1850                 {
1851                         return;
1852                 }
1853         }
1854         if(target->flags&MF_SKULLFLY)
1855         {
1856                 target->momx = target->momy = target->momz = 0;
1857         }
1858         if(target->flags2&MF2_DORMANT)
1859         {
1860                 // Invulnerable, and won't wake up
1861                 return;
1862         }
1863         player = target->player;
1864         if(player && gameskill == sk_baby)
1865         {
1866                 // Take half damage in trainer mode
1867                 damage >>= 1;
1868         }
1869         // Special damage types
1870         if(inflictor)
1871         {
1872                 switch(inflictor->type)
1873                 {
1874                         case MT_EGGFX:
1875                                 if(player)
1876                                 {
1877                                         P_MorphPlayer(player);
1878                                 }
1879                                 else
1880                                 {
1881                                         P_MorphMonster(target);
1882                                 }
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)))
1893                                 {
1894                                         P_TeleportOther(target);
1895                                 }
1896                                 return;
1897                         case MT_MINOTAUR:
1898                                 if(inflictor->flags&MF_SKULLFLY)
1899                                 { // Slam only when in charge mode
1900                                         P_MinotaurSlam(inflictor, target);
1901                                         return;
1902                                 }
1903                                 break;
1904                         case MT_BISH_FX:
1905                                 // Bishops are just too nasty
1906                                 damage >>= 1;
1907                                 break;
1908                         case MT_SHARDFX1:
1909                                 switch(inflictor->special2)
1910                                 {
1911                                         case 3:
1912                                                 damage <<= 3;
1913                                                 break;
1914                                         case 2:
1915                                                 damage <<= 2;
1916                                                 break;
1917                                         case 1:
1918                                                 damage <<= 1;
1919                                                 break;
1920                                         default:
1921                                                 break;
1922                                 }
1923                                 break;
1924                         case MT_CSTAFF_MISSILE:
1925                                 // Cleric Serpent Staff does poison damage
1926                                 if(target->player)
1927                                 {
1928                                         P_PoisonPlayer(target->player, source, 20);
1929                                         damage >>= 1;
1930                                 }
1931                                 break;
1932                         case MT_ICEGUY_FX2:
1933                                 damage >>= 1;
1934                                 break;
1935                         case MT_POISONDART:
1936                                 if(target->player)
1937                                 {
1938                                         P_PoisonPlayer(target->player, source, 20);
1939                                         damage >>= 1;
1940                                 }
1941                                 break;
1942                         case MT_POISONCLOUD:
1943                                 if(target->player)
1944                                 {
1945                                         if(target->player->poisoncount < 4)
1946                                         {
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);
1951                                         }       
1952                                         return;
1953                                 }
1954                                 else if(!(target->flags&MF_COUNTKILL))
1955                                 { // only damage monsters/players with the poison cloud
1956                                         return;
1957                                 }
1958                                 break;
1959                         case MT_FSWORD_MISSILE:
1960                                 if(target->player)
1961                                 {
1962                                         damage -= damage>>2;
1963                                 }
1964                                 break;
1965                         default:
1966                                 break;
1967                 }
1968         }
1969         // Push the target unless source is using the gauntlets
1970         if(inflictor && (!source || !source->player)
1971                 && !(inflictor->flags2&MF2_NODMGTHRUST))
1972         {
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))
1980                 {
1981                         ang += ANG180;
1982                         thrust *= 4;
1983                 }
1984                 ang >>= ANGLETOFINESHIFT;
1985                 target->momx += FixedMul(thrust, finecosine[ang]);
1986                 target->momy += FixedMul(thrust, finesine[ang]);
1987         }
1988
1989         //
1990         // player specific
1991         //
1992         if(player)
1993         {
1994                 savedPercent = AutoArmorSave[player->class]
1995                         +player->armorpoints[ARMOR_ARMOR]+player->armorpoints[ARMOR_SHIELD]
1996                         +player->armorpoints[ARMOR_HELMET]
1997                         +player->armorpoints[ARMOR_AMULET];
1998                 if(savedPercent)
1999                 { // armor absorbed some damage
2000                         if(savedPercent > 100*FRACUNIT)
2001                         {
2002                                 savedPercent = 100*FRACUNIT;
2003                         }
2004                         for(i = 0; i < NUMARMOR; i++)
2005                         {
2006                                 if(player->armorpoints[i])
2007                                 {
2008                                         player->armorpoints[i] -= 
2009                                                 FixedDiv(FixedMul(damage<<FRACBITS,
2010                                                 ArmorIncrement[player->class][i]), 300*FRACUNIT);
2011                                         if(player->armorpoints[i] < 2*FRACUNIT)
2012                                         {
2013                                                 player->armorpoints[i] = 0;
2014                                         }
2015                                 }
2016                         }
2017                         saved = FixedDiv(FixedMul(damage<<FRACBITS, savedPercent),
2018                                 100*FRACUNIT);
2019                         if(saved > savedPercent*2)
2020                         {       
2021                                 saved = savedPercent*2;
2022                         }
2023                         damage -= saved>>FRACBITS;
2024                 }
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);
2030                 }
2031                 player->health -= damage; // mirror mobj health here for Dave
2032                 if(player->health < 0)
2033                 {
2034                         player->health = 0;
2035                 }
2036                 player->attacker = source;
2037                 player->damagecount += damage; // add damage after armor / invuln
2038                 if(player->damagecount > 100)
2039                 {
2040                         player->damagecount = 100; // teleport stomp does 10k points...
2041                 }
2042                 temp = damage < 100 ? damage : 100;
2043                 if(player == &players[consoleplayer])
2044                 {
2045                         //I_Tactile(40, 10, 40+temp*2);
2046                         SB_PaletteFlash(false);
2047                 }
2048         }
2049
2050         //
2051         // do the damage
2052         //
2053         target->health -= damage;
2054         if(target->health <= 0)
2055         { // Death
2056                 if(inflictor)
2057                 { // check for special fire damage or ice damage deaths
2058                         if(inflictor->flags2&MF2_FIREDAMAGE)
2059                         {
2060                                 if(player && !player->morphTics)
2061                                 { // Check for flame death
2062                                         if(target->health > -50 && damage > 25)
2063                                         {
2064                                                 target->flags2 |= MF2_FIREDAMAGE;
2065                                         }
2066                                 }
2067                                 else
2068                                 {
2069                                         target->flags2 |= MF2_FIREDAMAGE;
2070                                 }
2071                         }
2072                         else if(inflictor->flags2&MF2_ICEDAMAGE)
2073                         {
2074                                 target->flags2 |= MF2_ICEDAMAGE;
2075                         }
2076                 }
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))
2082                         {
2083                                 source = master;
2084                         }
2085                 }
2086                 if(source && (source->player) &&
2087                         (source->player->readyweapon == WP_FOURTH))
2088                 {
2089                         // Always extreme death from fourth weapon
2090                         target->health = -5000;
2091                 }
2092                 P_KillMobj(source, target);
2093                 return;
2094         }
2095         if((P_Random() < target->info->painchance)
2096                 && !(target->flags&MF_SKULLFLY))
2097         {
2098                 if(inflictor && (inflictor->type >= MT_LIGHTNING_FLOOR
2099                         && inflictor->type <= MT_LIGHTNING_ZAP))
2100                 {
2101                         if(P_Random() < 96)
2102                         {
2103                                 target->flags |= MF_JUSTHIT; // fight back!
2104                                 P_SetMobjState(target, target->info->painstate);
2105                         }
2106                         else
2107                         { // "electrocute" the target
2108                                 target->frame |= FF_FULLBRIGHT;
2109                                 if(target->flags&MF_COUNTKILL && P_Random() < 128
2110                                 && !S_GetSoundPlayingInfo(target, SFX_PUPPYBEAT))
2111                                 {
2112                                         if ((target->type == MT_CENTAUR) ||
2113                                                 (target->type == MT_CENTAURLEADER) ||
2114                                                 (target->type == MT_ETTIN))
2115                                         {
2116                                                 S_StartSound(target, SFX_PUPPYBEAT);
2117                                         }
2118                                 }
2119                         }
2120                 }
2121                 else
2122                 {
2123                         target->flags |= MF_JUSTHIT; // fight back!
2124                         P_SetMobjState(target, target->info->painstate);        
2125                         if(inflictor && inflictor->type == MT_POISONCLOUD)
2126                         {
2127                                 if(target->flags&MF_COUNTKILL && P_Random() < 128
2128                                 && !S_GetSoundPlayingInfo(target, SFX_PUPPYBEAT))
2129                                 {
2130                                         if ((target->type == MT_CENTAUR) ||
2131                                                 (target->type == MT_CENTAURLEADER) ||
2132                                                 (target->type == MT_ETTIN))
2133                                         {
2134                                                 S_StartSound(target, SFX_PUPPYBEAT);
2135                                         }
2136                                 }
2137                         }
2138                 }
2139         }
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))
2143         {
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))
2149                 {
2150                         return;
2151                 }
2152                 target->target = source;
2153                 target->threshold = BASETHRESHOLD;
2154                 if(target->state == &states[target->info->spawnstate]
2155                         && target->info->seestate != S_NULL)
2156                 {
2157                         P_SetMobjState(target, target->info->seestate);
2158                 }
2159         }
2160 }
2161
2162 //==========================================================================
2163 //
2164 // P_FallingDamage
2165 //
2166 //==========================================================================
2167
2168 void P_FallingDamage(player_t *player)
2169 {
2170         int damage;
2171         int mom;
2172         int dist;
2173
2174         mom = abs(player->mo->momz);    
2175         dist = FixedMul(mom, 16*FRACUNIT/23);
2176
2177         if(mom >= 63*FRACUNIT)
2178         { // automatic death
2179                 P_DamageMobj(player->mo, NULL, NULL, 10000);
2180                 return;
2181         }
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;
2187         }
2188         S_StartSound(player->mo, SFX_PLAYER_LAND);
2189         P_DamageMobj(player->mo, NULL, NULL, damage);
2190 }
2191
2192 //==========================================================================
2193 //
2194 // P_PoisonPlayer - Sets up all data concerning poisoning
2195 //
2196 //==========================================================================
2197
2198 void P_PoisonPlayer(player_t *player, mobj_t *poisoner, int poison)
2199 {
2200         if((player->cheats&CF_GODMODE) || player->powers[pw_invulnerability])
2201         {
2202                 return;
2203         }
2204         player->poisoncount += poison;
2205         player->poisoner = poisoner;
2206         if(player->poisoncount > 100)
2207         {
2208                 player->poisoncount = 100;
2209         }
2210 }
2211
2212 //==========================================================================
2213 //
2214 // P_PoisonDamage - Similar to P_DamageMobj
2215 //
2216 //==========================================================================
2217
2218 void P_PoisonDamage(player_t *player, mobj_t *source, int damage,
2219         boolean playPainSound)
2220 {
2221         mobj_t *target;
2222         mobj_t *inflictor;
2223
2224         target = player->mo;
2225         inflictor = source;
2226         if(target->health <= 0)
2227         {
2228                 return;
2229         }
2230         if(target->flags2&MF2_INVULNERABLE && damage < 10000)
2231         { // mobj is invulnerable
2232                 return;
2233         }
2234         if(player && gameskill == sk_baby)
2235         {
2236                 // Take half damage in trainer mode
2237                 damage >>= 1;
2238         }
2239         if(damage < 1000 && ((player->cheats&CF_GODMODE)
2240                 || player->powers[pw_invulnerability]))
2241         {
2242                 return;
2243         }
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);
2249         }
2250         player->health -= damage; // mirror mobj health here for Dave
2251         if(player->health < 0)
2252         {
2253                 player->health = 0;
2254         }
2255         player->attacker = source;
2256
2257         //
2258         // do the damage
2259         //
2260         target->health -= damage;
2261         if(target->health <= 0)
2262         { // Death
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))
2268                         {
2269                                 target->flags2 |= MF2_FIREDAMAGE;
2270                         }
2271                         if(inflictor->flags2&MF2_ICEDAMAGE)
2272                         {
2273                                 target->flags2 |= MF2_ICEDAMAGE;
2274                         }
2275                 }
2276                 P_KillMobj(source, target);
2277                 return;
2278         }
2279         if(!(leveltime&63) && playPainSound)
2280         {
2281                 P_SetMobjState(target, target->info->painstate);
2282         }
2283 /*
2284         if((P_Random() < target->info->painchance)
2285                 && !(target->flags&MF_SKULLFLY))
2286         {
2287                 target->flags |= MF_JUSTHIT; // fight back!
2288                 P_SetMobjState(target, target->info->painstate);
2289         }
2290 */
2291 }
2292