1
2 //**************************************************************************
3 //**
4 //** p_user.c : Heretic 2 : Raven Software, Corp.
5 //**
6 //** $RCSfile: p_user.c,v $
7 //** $Revision: 1.123 $
8 //** $Date: 96/01/05 14:21:01 $
9 //** $Author: bgokey $
10 //**
11 //**************************************************************************
12
13 #include "h2def.h"
14 #include "p_local.h"
15 #include "soundst.h"
16
17 void P_PlayerNextArtifact(player_t *player);
18
19 // Macros
20
21 #define MAXBOB 0x100000 // 16 pixels of bob
22
23 // Data
24
25 boolean onground;
26 int newtorch; // used in the torch flicker effect.
27 int newtorchdelta;
28
29 int PStateNormal[NUMCLASSES] =
30 {
31 S_FPLAY,
32 S_CPLAY,
33 S_MPLAY,
34 S_PIGPLAY
35 };
36
37 int PStateRun[NUMCLASSES] =
38 {
39 S_FPLAY_RUN1,
40 S_CPLAY_RUN1,
41 S_MPLAY_RUN1,
42 S_PIGPLAY_RUN1
43 };
44
45 int PStateAttack[NUMCLASSES] =
46 {
47 S_FPLAY_ATK1,
48 S_CPLAY_ATK1,
49 S_MPLAY_ATK1,
50 S_PIGPLAY_ATK1
51 };
52
53 int PStateAttackEnd[NUMCLASSES] =
54 {
55 S_FPLAY_ATK2,
56 S_CPLAY_ATK3,
57 S_MPLAY_ATK2,
58 S_PIGPLAY_ATK1
59 };
60
61 int ArmorMax[NUMCLASSES] = { 20, 18, 16, 1 };
62 /*
63 ==================
64 =
65 = P_Thrust
66 =
67 = moves the given origin along a given angle
68 =
69 ==================
70 */
71
P_Thrust(player_t * player,angle_t angle,fixed_t move)72 void P_Thrust(player_t *player, angle_t angle, fixed_t move)
73 {
74 angle >>= ANGLETOFINESHIFT;
75 if(player->powers[pw_flight] && !(player->mo->z <= player->mo->floorz))
76 {
77 player->mo->momx += FixedMul(move, finecosine[angle]);
78 player->mo->momy += FixedMul(move, finesine[angle]);
79 }
80 else if(P_GetThingFloorType(player->mo) == FLOOR_ICE) // Friction_Low
81 {
82 player->mo->momx += FixedMul(move>>1, finecosine[angle]);
83 player->mo->momy += FixedMul(move>>1, finesine[angle]);
84 }
85 else
86 {
87 player->mo->momx += FixedMul(move, finecosine[angle]);
88 player->mo->momy += FixedMul(move, finesine[angle]);
89 }
90 }
91
92
93 /*
94 ==================
95 =
96 = P_CalcHeight
97 =
98 =Calculate the walking / running height adjustment
99 =
100 ==================
101 */
102
P_CalcHeight(player_t * player)103 void P_CalcHeight (player_t *player)
104 {
105 int angle;
106 fixed_t bob;
107
108 //
109 // regular movement bobbing (needs to be calculated for gun swing even
110 // if not on ground)
111 // OPTIMIZE: tablify angle
112
113 player->bob = FixedMul (player->mo->momx, player->mo->momx)+
114 FixedMul (player->mo->momy,player->mo->momy);
115 player->bob >>= 2;
116 if (player->bob>MAXBOB)
117 player->bob = MAXBOB;
118 if(player->mo->flags2&MF2_FLY && !onground)
119 {
120 player->bob = FRACUNIT/2;
121 }
122
123 if ((player->cheats & CF_NOMOMENTUM))
124 {
125 player->viewz = player->mo->z + VIEWHEIGHT;
126 if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
127 player->viewz = player->mo->ceilingz-4*FRACUNIT;
128 player->viewz = player->mo->z + player->viewheight;
129 return;
130 }
131
132 angle = (FINEANGLES/20*leveltime)&FINEMASK;
133 bob = FixedMul ( player->bob/2, finesine[angle]);
134
135 //
136 // move viewheight
137 //
138 if (player->playerstate == PST_LIVE)
139 {
140 player->viewheight += player->deltaviewheight;
141 if (player->viewheight > VIEWHEIGHT)
142 {
143 player->viewheight = VIEWHEIGHT;
144 player->deltaviewheight = 0;
145 }
146 if (player->viewheight < VIEWHEIGHT/2)
147 {
148 player->viewheight = VIEWHEIGHT/2;
149 if (player->deltaviewheight <= 0)
150 player->deltaviewheight = 1;
151 }
152
153 if (player->deltaviewheight)
154 {
155 player->deltaviewheight += FRACUNIT/4;
156 if (!player->deltaviewheight)
157 player->deltaviewheight = 1;
158 }
159 }
160
161 if(player->morphTics)
162 {
163 player->viewz = player->mo->z+player->viewheight-(20*FRACUNIT);
164 }
165 else
166 {
167 player->viewz = player->mo->z+player->viewheight+bob;
168 }
169 if(player->mo->floorclip && player->playerstate != PST_DEAD
170 && player->mo->z <= player->mo->floorz)
171 {
172 player->viewz -= player->mo->floorclip;
173 }
174 if(player->viewz > player->mo->ceilingz-4*FRACUNIT)
175 {
176 player->viewz = player->mo->ceilingz-4*FRACUNIT;
177 }
178 if(player->viewz < player->mo->floorz+4*FRACUNIT)
179 {
180 player->viewz = player->mo->floorz+4*FRACUNIT;
181 }
182 }
183
184 /*
185 =================
186 =
187 = P_MovePlayer
188 =
189 =================
190 */
191
P_MovePlayer(player_t * player)192 void P_MovePlayer(player_t *player)
193 {
194 int look;
195 int fly;
196 ticcmd_t *cmd;
197
198 cmd = &player->cmd;
199 player->mo->angle += (cmd->angleturn<<16);
200
201 onground = (player->mo->z <= player->mo->floorz
202 || (player->mo->flags2&MF2_ONMOBJ));
203
204 if(cmd->forwardmove)
205 {
206 if(onground || player->mo->flags2&MF2_FLY)
207 {
208 P_Thrust(player, player->mo->angle, cmd->forwardmove*2048);
209 }
210 else
211 {
212 P_Thrust(player, player->mo->angle, FRACUNIT>>8);
213 }
214 }
215 if(cmd->sidemove)
216 {
217 if(onground || player->mo->flags2&MF2_FLY)
218 {
219 P_Thrust(player, player->mo->angle-ANG90, cmd->sidemove*2048);
220 }
221 else
222 {
223 P_Thrust(player, player->mo->angle, FRACUNIT>>8);
224 }
225 }
226 if(cmd->forwardmove || cmd->sidemove)
227 {
228 if(player->mo->state == &states[PStateNormal[player->class]])
229 {
230 P_SetMobjState(player->mo, PStateRun[player->class]);
231 }
232 }
233
234 look = cmd->lookfly&15;
235 if(look > 7)
236 {
237 look -= 16;
238 }
239 if(look)
240 {
241 if(look == TOCENTER)
242 {
243 player->centering = true;
244 }
245 else
246 {
247 player->lookdir += 5*look;
248 if(player->lookdir > 90 || player->lookdir < -110)
249 {
250 player->lookdir -= 5*look;
251 }
252 }
253 }
254 if(player->centering)
255 {
256 if(player->lookdir > 0)
257 {
258 player->lookdir -= 8;
259 }
260 else if(player->lookdir < 0)
261 {
262 player->lookdir += 8;
263 }
264 if(abs(player->lookdir) < 8)
265 {
266 player->lookdir = 0;
267 player->centering = false;
268 }
269 }
270 fly = cmd->lookfly>>4;
271 if(fly > 7)
272 {
273 fly -= 16;
274 }
275 if(fly && player->powers[pw_flight])
276 {
277 if(fly != TOCENTER)
278 {
279 player->flyheight = fly*2;
280 if(!(player->mo->flags2&MF2_FLY))
281 {
282 player->mo->flags2 |= MF2_FLY;
283 player->mo->flags |= MF_NOGRAVITY;
284 if(player->mo->momz <= -39*FRACUNIT)
285 { // stop falling scream
286 S_StopSound(player->mo);
287 }
288 }
289 }
290 else
291 {
292 player->mo->flags2 &= ~MF2_FLY;
293 player->mo->flags &= ~MF_NOGRAVITY;
294 }
295 }
296 else if(fly > 0)
297 {
298 P_PlayerUseArtifact(player, arti_fly);
299 }
300 if(player->mo->flags2&MF2_FLY)
301 {
302 player->mo->momz = player->flyheight*FRACUNIT;
303 if(player->flyheight)
304 {
305 player->flyheight /= 2;
306 }
307 }
308 }
309
310 //==========================================================================
311 //
312 // P_DeathThink
313 //
314 //==========================================================================
315
P_DeathThink(player_t * player)316 void P_DeathThink(player_t *player)
317 {
318 int dir;
319 angle_t delta;
320 int lookDelta;
321 extern int inv_ptr;
322 extern int curpos;
323
324 P_MovePsprites(player);
325
326 onground = (player->mo->z <= player->mo->floorz);
327 if(player->mo->type == MT_BLOODYSKULL || player->mo->type == MT_ICECHUNK)
328 { // Flying bloody skull or flying ice chunk
329 player->viewheight = 6*FRACUNIT;
330 player->deltaviewheight = 0;
331 //player->damagecount = 20;
332 if(onground)
333 {
334 if(player->lookdir < 60)
335 {
336 lookDelta = (60-player->lookdir)/8;
337 if(lookDelta < 1 && (leveltime&1))
338 {
339 lookDelta = 1;
340 }
341 else if(lookDelta > 6)
342 {
343 lookDelta = 6;
344 }
345 player->lookdir += lookDelta;
346 }
347 }
348 }
349 else if(!(player->mo->flags2&MF2_ICEDAMAGE))
350 { // Fall to ground (if not frozen)
351 player->deltaviewheight = 0;
352 if(player->viewheight > 6*FRACUNIT)
353 {
354 player->viewheight -= FRACUNIT;
355 }
356 if(player->viewheight < 6*FRACUNIT)
357 {
358 player->viewheight = 6*FRACUNIT;
359 }
360 if(player->lookdir > 0)
361 {
362 player->lookdir -= 6;
363 }
364 else if(player->lookdir < 0)
365 {
366 player->lookdir += 6;
367 }
368 if(abs(player->lookdir) < 6)
369 {
370 player->lookdir = 0;
371 }
372 }
373 P_CalcHeight(player);
374
375 if(player->attacker && player->attacker != player->mo)
376 { // Watch killer
377 dir = P_FaceMobj(player->mo, player->attacker, &delta);
378 if(delta < ANGLE_1*10)
379 { // Looking at killer, so fade damage and poison counters
380 if(player->damagecount)
381 {
382 player->damagecount--;
383 }
384 if(player->poisoncount)
385 {
386 player->poisoncount--;
387 }
388 }
389 delta = delta/8;
390 if(delta > ANGLE_1*5)
391 {
392 delta = ANGLE_1*5;
393 }
394 if(dir)
395 { // Turn clockwise
396 player->mo->angle += delta;
397 }
398 else
399 { // Turn counter clockwise
400 player->mo->angle -= delta;
401 }
402 }
403 else if(player->damagecount || player->poisoncount)
404 {
405 if(player->damagecount)
406 {
407 player->damagecount--;
408 }
409 else
410 {
411 player->poisoncount--;
412 }
413 }
414
415 if(player->cmd.buttons&BT_USE)
416 {
417 if(player == &players[consoleplayer])
418 {
419 I_SetPalette((byte *)W_CacheLumpName("PLAYPAL", PU_CACHE));
420 inv_ptr = 0;
421 curpos = 0;
422 newtorch = 0;
423 newtorchdelta = 0;
424 }
425 player->playerstate = PST_REBORN;
426 player->mo->special1 = player->class;
427 if(player->mo->special1 > 2)
428 {
429 player->mo->special1 = 0;
430 }
431 // Let the mobj know the player has entered the reborn state. Some
432 // mobjs need to know when it's ok to remove themselves.
433 player->mo->special2 = 666;
434 }
435 }
436
437 //----------------------------------------------------------------------------
438 //
439 // PROC P_MorphPlayerThink
440 //
441 //----------------------------------------------------------------------------
442
P_MorphPlayerThink(player_t * player)443 void P_MorphPlayerThink(player_t *player)
444 {
445 mobj_t *pmo;
446
447 if(player->morphTics&15)
448 {
449 return;
450 }
451 pmo = player->mo;
452 if(!(pmo->momx+pmo->momy) && P_Random() < 64)
453 { // Snout sniff
454 P_SetPspriteNF(player, ps_weapon, S_SNOUTATK2);
455 S_StartSound(pmo, SFX_PIG_ACTIVE1); // snort
456 return;
457 }
458 if(P_Random() < 48)
459 {
460 if(P_Random() < 128)
461 {
462 S_StartSound(pmo, SFX_PIG_ACTIVE1);
463 }
464 else
465 {
466 S_StartSound(pmo, SFX_PIG_ACTIVE2);
467 }
468 }
469 }
470
471 //----------------------------------------------------------------------------
472 //
473 // FUNC P_GetPlayerNum
474 //
475 //----------------------------------------------------------------------------
476
P_GetPlayerNum(player_t * player)477 int P_GetPlayerNum(player_t *player)
478 {
479 int i;
480
481 for(i = 0; i < MAXPLAYERS; i++)
482 {
483 if(player == &players[i])
484 {
485 return(i);
486 }
487 }
488 return(0);
489 }
490
491 //----------------------------------------------------------------------------
492 //
493 // FUNC P_UndoPlayerMorph
494 //
495 //----------------------------------------------------------------------------
496
P_UndoPlayerMorph(player_t * player)497 boolean P_UndoPlayerMorph(player_t *player)
498 {
499 mobj_t *fog;
500 mobj_t *mo;
501 mobj_t *pmo;
502 fixed_t x;
503 fixed_t y;
504 fixed_t z;
505 angle_t angle;
506 int playerNum;
507 weapontype_t weapon;
508 int oldFlags;
509 int oldFlags2;
510 int oldBeast;
511
512
513 if (player->cheats & CF_FUNNYPIGGY) {
514 player->morphTics = 10000;
515 return(false);
516 }
517 pmo = player->mo;
518 x = pmo->x;
519 y = pmo->y;
520 z = pmo->z;
521 angle = pmo->angle;
522 weapon = pmo->special1;
523 oldFlags = pmo->flags;
524 oldFlags2 = pmo->flags2;
525 oldBeast = pmo->type;
526 P_SetMobjState(pmo, S_FREETARGMOBJ);
527 playerNum = P_GetPlayerNum(player);
528 switch(PlayerClass[playerNum])
529 {
530 case PCLASS_FIGHTER:
531 mo = P_SpawnMobj(x, y, z, MT_PLAYER_FIGHTER);
532 break;
533 case PCLASS_CLERIC:
534 mo = P_SpawnMobj(x, y, z, MT_PLAYER_CLERIC);
535 break;
536 case PCLASS_MAGE:
537 mo = P_SpawnMobj(x, y, z, MT_PLAYER_MAGE);
538 break;
539 default:
540 I_Error("P_UndoPlayerMorph: Unknown player class %d\n",
541 player->class);
542 }
543 if(P_TestMobjLocation(mo) == false)
544 { // Didn't fit
545 P_RemoveMobj(mo);
546 mo = P_SpawnMobj(x, y, z, oldBeast);
547 mo->angle = angle;
548 mo->health = player->health;
549 mo->special1 = weapon;
550 mo->player = player;
551 mo->flags = oldFlags;
552 mo->flags2 = oldFlags2;
553 player->mo = mo;
554 player->morphTics = 2*35;
555 return(false);
556 }
557 if(player->class == PCLASS_FIGHTER)
558 {
559 // The first type should be blue, and the third should be the
560 // Fighter's original gold color
561 if(playerNum == 0)
562 {
563 mo->flags |= 2<<MF_TRANSSHIFT;
564 }
565 else if(playerNum != 2)
566 {
567 mo->flags |= playerNum<<MF_TRANSSHIFT;
568 }
569 }
570 else if(playerNum)
571 { // Set color translation bits for player sprites
572 mo->flags |= playerNum<<MF_TRANSSHIFT;
573 }
574 mo->angle = angle;
575 mo->player = player;
576 mo->reactiontime = 18;
577 if(oldFlags2&MF2_FLY)
578 {
579 mo->flags2 |= MF2_FLY;
580 mo->flags |= MF_NOGRAVITY;
581 }
582 player->morphTics = 0;
583 player->health = mo->health = MAXHEALTH;
584 player->mo = mo;
585 player->class = PlayerClass[playerNum];
586 angle >>= ANGLETOFINESHIFT;
587 fog = P_SpawnMobj(x+20*finecosine[angle],
588 y+20*finesine[angle], z+TELEFOGHEIGHT, MT_TFOG);
589 S_StartSound(fog, SFX_TELEPORT);
590 P_PostMorphWeapon(player, weapon);
591 return(true);
592 }
593
594
595 //----------------------------------------------------------------------------
596 //
597 // PROC P_PlayerThink
598 //
599 //----------------------------------------------------------------------------
600
P_PlayerThink(player_t * player)601 void P_PlayerThink(player_t *player)
602 {
603 ticcmd_t *cmd;
604 weapontype_t newweapon;
605 int floorType;
606 mobj_t *pmo;
607
608 if (!player)
609 I_Error("P_PlayerThink: no player!");
610 if (!player->mo)
611 I_Error("P_PlayerThink: no player->mo!");
612
613 // No-clip cheat
614 if(player->cheats&CF_NOCLIP)
615 {
616 player->mo->flags |= MF_NOCLIP;
617 }
618 else
619 {
620 player->mo->flags &= ~MF_NOCLIP;
621 }
622 cmd = &player->cmd;
623 if(player->mo->flags&MF_JUSTATTACKED)
624 { // Gauntlets attack auto forward motion
625 cmd->angleturn = 0;
626 cmd->forwardmove = 0xc800/512;
627 cmd->sidemove = 0;
628 player->mo->flags &= ~MF_JUSTATTACKED;
629 }
630 // messageTics is above the rest of the counters so that messages will
631 // go away, even in death.
632 player->messageTics--; // Can go negative
633 if(!player->messageTics || player->messageTics == -1)
634 { // Refresh the screen when a message goes away
635 player->ultimateMessage = false; // clear out any chat messages.
636 player->yellowMessage = false;
637 if(player == &players[consoleplayer])
638 {
639 BorderTopRefresh = true;
640 }
641 }
642 player->worldTimer++;
643 if(player->playerstate == PST_DEAD)
644 {
645 P_DeathThink(player);
646 return;
647 }
648 if(player->jumpTics)
649 {
650 player->jumpTics--;
651 }
652 if(player->morphTics)
653 {
654 P_MorphPlayerThink(player);
655 }
656 // Handle movement
657 if(player->mo->reactiontime)
658 { // Player is frozen
659 player->mo->reactiontime--;
660 }
661 else
662 {
663 P_MovePlayer(player);
664 pmo = player->mo;
665 if(player->powers[pw_speed] && !(leveltime&1)
666 && P_AproxDistance(pmo->momx, pmo->momy) > 12*FRACUNIT)
667 {
668 mobj_t *speedMo;
669 int playerNum;
670
671 speedMo = P_SpawnMobj(pmo->x, pmo->y, pmo->z, MT_PLAYER_SPEED);
672 if(speedMo)
673 {
674 speedMo->angle = pmo->angle;
675 playerNum = P_GetPlayerNum(player);
676 if(player->class == PCLASS_FIGHTER)
677 {
678 // The first type should be blue, and the
679 // third should be the Fighter's original gold color
680 if(playerNum == 0)
681 {
682 speedMo->flags |= 2<<MF_TRANSSHIFT;
683 }
684 else if(playerNum != 2)
685 {
686 speedMo->flags |= playerNum<<MF_TRANSSHIFT;
687 }
688 }
689 else if(playerNum)
690 { // Set color translation bits for player sprites
691 speedMo->flags |= playerNum<<MF_TRANSSHIFT;
692 }
693 speedMo->target = pmo;
694 speedMo->special1 = player->class;
695 if(speedMo->special1 > 2)
696 {
697 speedMo->special1 = 0;
698 }
699 speedMo->sprite = pmo->sprite;
700 speedMo->floorclip = pmo->floorclip;
701 if(player == &players[consoleplayer])
702 {
703 speedMo->flags2 |= MF2_DONTDRAW;
704 }
705 }
706 }
707 }
708 P_CalcHeight(player);
709 if(player->mo->subsector->sector->special)
710 {
711 P_PlayerInSpecialSector(player);
712 }
713 if((floorType = P_GetThingFloorType(player->mo)) != FLOOR_SOLID)
714 {
715 P_PlayerOnSpecialFlat(player, floorType);
716 }
717 switch(player->class)
718 {
719 case PCLASS_FIGHTER:
720 if(player->mo->momz <= -35*FRACUNIT
721 && player->mo->momz >= -40*FRACUNIT && !player->morphTics
722 && !S_GetSoundPlayingInfo(player->mo,
723 SFX_PLAYER_FIGHTER_FALLING_SCREAM))
724 {
725 S_StartSound(player->mo,
726 SFX_PLAYER_FIGHTER_FALLING_SCREAM);
727 }
728 break;
729 case PCLASS_CLERIC:
730 if(player->mo->momz <= -35*FRACUNIT
731 && player->mo->momz >= -40*FRACUNIT && !player->morphTics
732 && !S_GetSoundPlayingInfo(player->mo,
733 SFX_PLAYER_CLERIC_FALLING_SCREAM))
734 {
735 S_StartSound(player->mo,
736 SFX_PLAYER_CLERIC_FALLING_SCREAM);
737 }
738 break;
739 case PCLASS_MAGE:
740 if(player->mo->momz <= -35*FRACUNIT
741 && player->mo->momz >= -40*FRACUNIT && !player->morphTics
742 && !S_GetSoundPlayingInfo(player->mo,
743 SFX_PLAYER_MAGE_FALLING_SCREAM))
744 {
745 S_StartSound(player->mo,
746 SFX_PLAYER_MAGE_FALLING_SCREAM);
747 }
748 break;
749 default:
750 break;
751 }
752 if(cmd->arti)
753 { // Use an artifact
754 if((cmd->arti&AFLAG_JUMP) && onground && !player->jumpTics)
755 {
756 if(player->morphTics)
757 {
758 player->mo->momz = 6*FRACUNIT;
759 }
760 else
761 {
762 player->mo->momz = 9*FRACUNIT;
763 }
764 player->mo->flags2 &= ~MF2_ONMOBJ;
765 player->jumpTics = 18;
766 }
767 else if(cmd->arti&AFLAG_SUICIDE)
768 {
769 P_DamageMobj(player->mo, NULL, NULL, 10000);
770 }
771 if(cmd->arti == NUMARTIFACTS)
772 { // use one of each artifact (except puzzle artifacts)
773 int i;
774
775 for(i = 1; i < arti_firstpuzzitem; i++)
776 {
777 P_PlayerUseArtifact(player, i);
778 }
779 }
780 else
781 {
782 P_PlayerUseArtifact(player, cmd->arti&AFLAG_MASK);
783 }
784 }
785 // Check for weapon change
786 if(cmd->buttons&BT_SPECIAL)
787 { // A special event has no other buttons
788 cmd->buttons = 0;
789 }
790 if(cmd->buttons&BT_CHANGE && !player->morphTics)
791 {
792 // The actual changing of the weapon is done when the weapon
793 // psprite can do it (A_WeaponReady), so it doesn't happen in
794 // the middle of an attack.
795 newweapon = (cmd->buttons&BT_WEAPONMASK)>>BT_WEAPONSHIFT;
796 if(player->weaponowned[newweapon]
797 && newweapon != player->readyweapon)
798 {
799 player->pendingweapon = newweapon;
800 }
801 }
802 // Check for use
803 if(cmd->buttons&BT_USE)
804 {
805 if(!player->usedown)
806 {
807 P_UseLines(player);
808 player->usedown = true;
809 }
810 }
811 else
812 {
813 player->usedown = false;
814 }
815 // Morph counter
816 if(player->morphTics)
817 {
818 if(!--player->morphTics)
819 { // Attempt to undo the pig
820 P_UndoPlayerMorph(player);
821 }
822 }
823 // Cycle psprites
824 P_MovePsprites(player);
825 // Other Counters
826 if(player->powers[pw_invulnerability])
827 {
828 if(player->class == PCLASS_CLERIC)
829 {
830 if(!(leveltime&7) && player->mo->flags&MF_SHADOW
831 && !(player->mo->flags2&MF2_DONTDRAW))
832 {
833 player->mo->flags &= ~MF_SHADOW;
834 if(!(player->mo->flags&MF_ALTSHADOW))
835 {
836 player->mo->flags2 |= MF2_DONTDRAW|MF2_NONSHOOTABLE;
837 }
838 }
839 if(!(leveltime&31))
840 {
841 if(player->mo->flags2&MF2_DONTDRAW)
842 {
843 if(!(player->mo->flags&MF_SHADOW))
844 {
845 player->mo->flags |= MF_SHADOW|MF_ALTSHADOW;
846 }
847 else
848 {
849 player->mo->flags2 &= ~(MF2_DONTDRAW|MF2_NONSHOOTABLE);
850 }
851 }
852 else
853 {
854 player->mo->flags |= MF_SHADOW;
855 player->mo->flags &= ~MF_ALTSHADOW;
856 }
857 }
858 }
859 if(!(--player->powers[pw_invulnerability]))
860 {
861 player->mo->flags2 &= ~(MF2_INVULNERABLE|MF2_REFLECTIVE);
862 if(player->class == PCLASS_CLERIC)
863 {
864 player->mo->flags2 &= ~(MF2_DONTDRAW|MF2_NONSHOOTABLE);
865 player->mo->flags &= ~(MF_SHADOW|MF_ALTSHADOW);
866 }
867 }
868 }
869 if(player->powers[pw_minotaur])
870 {
871 player->powers[pw_minotaur]--;
872 }
873 if(player->powers[pw_infrared])
874 {
875 player->powers[pw_infrared]--;
876 }
877 if(player->powers[pw_flight] && netgame)
878 {
879 if(!--player->powers[pw_flight])
880 {
881 if(player->mo->z != player->mo->floorz)
882 {
883 #ifdef __WATCOMC__
884 if(!useexterndriver)
885 {
886 player->centering = true;
887 }
888 #else
889 player->centering = true;
890 #endif
891 }
892 player->mo->flags2 &= ~MF2_FLY;
893 player->mo->flags &= ~MF_NOGRAVITY;
894 BorderTopRefresh = true; //make sure the sprite's cleared out
895 }
896 }
897 if(player->powers[pw_speed])
898 {
899 player->powers[pw_speed]--;
900 }
901 if(player->damagecount)
902 {
903 player->damagecount--;
904 }
905 if(player->bonuscount)
906 {
907 player->bonuscount--;
908 }
909 if(player->poisoncount && !(leveltime&15))
910 {
911 player->poisoncount -= 5;
912 if(player->poisoncount < 0)
913 {
914 player->poisoncount = 0;
915 }
916 P_PoisonDamage(player, player->poisoner, 1, true);
917 }
918 // Colormaps
919 // if(player->powers[pw_invulnerability])
920 // {
921 // if(player->powers[pw_invulnerability] > BLINKTHRESHOLD
922 // || (player->powers[pw_invulnerability]&8))
923 // {
924 // player->fixedcolormap = INVERSECOLORMAP;
925 // }
926 // else
927 // {
928 // player->fixedcolormap = 0;
929 // }
930 // }
931 // else
932 if(player->powers[pw_infrared])
933 {
934 if (player->powers[pw_infrared] <= BLINKTHRESHOLD)
935 {
936 if(player->powers[pw_infrared]&8)
937 {
938 player->fixedcolormap = 0;
939 }
940 else
941 {
942 player->fixedcolormap = 1;
943 }
944 }
945 else if(!(leveltime&16) && player == &players[consoleplayer])
946 {
947 if(newtorch)
948 {
949 if(player->fixedcolormap+newtorchdelta > 7
950 || player->fixedcolormap+newtorchdelta < 1
951 || newtorch == player->fixedcolormap)
952 {
953 newtorch = 0;
954 }
955 else
956 {
957 player->fixedcolormap += newtorchdelta;
958 }
959 }
960 else
961 {
962 newtorch = (M_Random()&7)+1;
963 newtorchdelta = (newtorch == player->fixedcolormap) ?
964 0 : ((newtorch > player->fixedcolormap) ? 1 : -1);
965 }
966 }
967 }
968 else
969 {
970 player->fixedcolormap = 0;
971 }
972 }
973
974 //----------------------------------------------------------------------------
975 //
976 // PROC P_ArtiTele
977 //
978 //----------------------------------------------------------------------------
979
P_ArtiTele(player_t * player)980 void P_ArtiTele(player_t *player)
981 {
982 int i;
983 int selections;
984 fixed_t destX;
985 fixed_t destY;
986 angle_t destAngle;
987
988 if(deathmatch)
989 {
990 selections = deathmatch_p-deathmatchstarts;
991 i = P_Random()%selections;
992 destX = deathmatchstarts[i].x<<FRACBITS;
993 destY = deathmatchstarts[i].y<<FRACBITS;
994 destAngle = ANG45*(deathmatchstarts[i].angle/45);
995 }
996 else
997 {
998 destX = playerstarts[0][0].x<<FRACBITS;
999 destY = playerstarts[0][0].y<<FRACBITS;
1000 destAngle = ANG45*(playerstarts[0][0].angle/45);
1001 }
1002 P_Teleport(player->mo, destX, destY, destAngle, true);
1003 if(player->morphTics)
1004 { // Teleporting away will undo any morph effects (pig)
1005 P_UndoPlayerMorph(player);
1006 }
1007 //S_StartSound(NULL, sfx_wpnup); // Full volume laugh
1008 }
1009
1010
1011 //----------------------------------------------------------------------------
1012 //
1013 // PROC P_ArtiTeleportOther
1014 //
1015 //----------------------------------------------------------------------------
1016
P_ArtiTeleportOther(player_t * player)1017 void P_ArtiTeleportOther(player_t *player)
1018 {
1019 mobj_t *mo;
1020
1021 mo=P_SpawnPlayerMissile(player->mo, MT_TELOTHER_FX1);
1022 if (mo)
1023 {
1024 mo->target = player->mo;
1025 }
1026 }
1027
1028
P_TeleportToPlayerStarts(mobj_t * victim)1029 void P_TeleportToPlayerStarts(mobj_t *victim)
1030 {
1031 int i,selections=0;
1032 fixed_t destX,destY;
1033 angle_t destAngle;
1034
1035 for (i=0;i<MAXPLAYERS;i++)
1036 {
1037 if (!playeringame[i]) continue;
1038 selections++;
1039 }
1040 i = P_Random()%selections;
1041 destX = playerstarts[0][i].x<<FRACBITS;
1042 destY = playerstarts[0][i].y<<FRACBITS;
1043 destAngle = ANG45*(playerstarts[0][i].angle/45);
1044 P_Teleport(victim, destX, destY, destAngle, true);
1045 //S_StartSound(NULL, sfx_wpnup); // Full volume laugh
1046 }
1047
P_TeleportToDeathmatchStarts(mobj_t * victim)1048 void P_TeleportToDeathmatchStarts(mobj_t *victim)
1049 {
1050 int i,selections;
1051 fixed_t destX,destY;
1052 angle_t destAngle;
1053
1054 selections = deathmatch_p-deathmatchstarts;
1055 if (selections)
1056 {
1057 i = P_Random()%selections;
1058 destX = deathmatchstarts[i].x<<FRACBITS;
1059 destY = deathmatchstarts[i].y<<FRACBITS;
1060 destAngle = ANG45*(deathmatchstarts[i].angle/45);
1061 P_Teleport(victim, destX, destY, destAngle, true);
1062 //S_StartSound(NULL, sfx_wpnup); // Full volume laugh
1063 }
1064 else
1065 {
1066 P_TeleportToPlayerStarts(victim);
1067 }
1068 }
1069
1070
1071
1072 //----------------------------------------------------------------------------
1073 //
1074 // PROC P_TeleportOther
1075 //
1076 //----------------------------------------------------------------------------
P_TeleportOther(mobj_t * victim)1077 void P_TeleportOther(mobj_t *victim)
1078 {
1079 if (victim->player)
1080 {
1081 if (deathmatch)
1082 P_TeleportToDeathmatchStarts(victim);
1083 else
1084 P_TeleportToPlayerStarts(victim);
1085 }
1086 else
1087 {
1088 // If death action, run it upon teleport
1089 if (victim->flags&MF_COUNTKILL && victim->special)
1090 {
1091 P_RemoveMobjFromTIDList(victim);
1092 P_ExecuteLineSpecial(victim->special, victim->args,
1093 NULL, 0, victim);
1094 victim->special = 0;
1095 }
1096
1097 // Send all monsters to deathmatch spots
1098 P_TeleportToDeathmatchStarts(victim);
1099 }
1100 }
1101
1102
1103
1104 #define BLAST_RADIUS_DIST 255*FRACUNIT
1105 #define BLAST_SPEED 20*FRACUNIT
1106 #define BLAST_FULLSTRENGTH 255
1107
ResetBlasted(mobj_t * mo)1108 void ResetBlasted(mobj_t *mo)
1109 {
1110 mo->flags2 &= ~MF2_BLASTED;
1111 if (!(mo->flags&MF_ICECORPSE))
1112 {
1113 mo->flags2 &= ~MF2_SLIDE;
1114 }
1115 }
1116
P_BlastMobj(mobj_t * source,mobj_t * victim,fixed_t strength)1117 void P_BlastMobj(mobj_t *source, mobj_t *victim, fixed_t strength)
1118 {
1119 angle_t angle,ang;
1120 mobj_t *mo;
1121 fixed_t x,y,z;
1122
1123 angle = R_PointToAngle2(source->x, source->y, victim->x, victim->y);
1124 angle >>= ANGLETOFINESHIFT;
1125 if (strength < BLAST_FULLSTRENGTH)
1126 {
1127 victim->momx = FixedMul(strength, finecosine[angle]);
1128 victim->momy = FixedMul(strength, finesine[angle]);
1129 if (victim->player)
1130 {
1131 // Players handled automatically
1132 }
1133 else
1134 {
1135 victim->flags2 |= MF2_SLIDE;
1136 victim->flags2 |= MF2_BLASTED;
1137 }
1138 }
1139 else // full strength blast from artifact
1140 {
1141 if (victim->flags&MF_MISSILE)
1142 {
1143 switch(victim->type)
1144 {
1145 case MT_SORCBALL1: // don't blast sorcerer balls
1146 case MT_SORCBALL2:
1147 case MT_SORCBALL3:
1148 return;
1149 break;
1150 case MT_MSTAFF_FX2: // Reflect to originator
1151 victim->special1 = (int)victim->target;
1152 victim->target = source;
1153 break;
1154 default:
1155 break;
1156 }
1157 }
1158 if (victim->type == MT_HOLY_FX)
1159 {
1160 if ((mobj_t *)(victim->special1) == source)
1161 {
1162 victim->special1 = (int)victim->target;
1163 victim->target = source;
1164 }
1165 }
1166 victim->momx = FixedMul(BLAST_SPEED, finecosine[angle]);
1167 victim->momy = FixedMul(BLAST_SPEED, finesine[angle]);
1168
1169 // Spawn blast puff
1170 ang = R_PointToAngle2(victim->x, victim->y, source->x, source->y);
1171 ang >>= ANGLETOFINESHIFT;
1172 x = victim->x + FixedMul(victim->radius+FRACUNIT, finecosine[ang]);
1173 y = victim->y + FixedMul(victim->radius+FRACUNIT, finesine[ang]);
1174 z = victim->z - victim->floorclip + (victim->height>>1);
1175 mo=P_SpawnMobj(x, y, z, MT_BLASTEFFECT);
1176 if (mo)
1177 {
1178 mo->momx = victim->momx;
1179 mo->momy = victim->momy;
1180 }
1181
1182 if (victim->flags&MF_MISSILE)
1183 {
1184 victim->momz = 8*FRACUNIT;
1185 mo->momz = victim->momz;
1186 }
1187 else
1188 {
1189 victim->momz = (1000/victim->info->mass)<<FRACBITS;
1190 }
1191 if (victim->player)
1192 {
1193 // Players handled automatically
1194 }
1195 else
1196 {
1197 victim->flags2 |= MF2_SLIDE;
1198 victim->flags2 |= MF2_BLASTED;
1199 }
1200 }
1201 }
1202
1203
1204 // Blast all mobj things away
P_BlastRadius(player_t * player)1205 void P_BlastRadius(player_t *player)
1206 {
1207 mobj_t *mo;
1208 mobj_t *pmo=player->mo;
1209 thinker_t *think;
1210 fixed_t dist;
1211
1212 S_StartSound(pmo, SFX_ARTIFACT_BLAST);
1213 P_NoiseAlert(player->mo, player->mo);
1214
1215 for(think = thinkercap.next; think != &thinkercap; think = think->next)
1216 {
1217 if(think->function != P_MobjThinker)
1218 { // Not a mobj thinker
1219 continue;
1220 }
1221 mo = (mobj_t *)think;
1222 if((mo == pmo) || (mo->flags2&MF2_BOSS))
1223 { // Not a valid monster
1224 continue;
1225 }
1226 if ((mo->type == MT_POISONCLOUD) || // poison cloud
1227 (mo->type == MT_HOLY_FX) || // holy fx
1228 (mo->flags&MF_ICECORPSE)) // frozen corpse
1229 {
1230 // Let these special cases go
1231 }
1232 else if ((mo->flags&MF_COUNTKILL) &&
1233 (mo->health <= 0))
1234 {
1235 continue;
1236 }
1237 else if (!(mo->flags&MF_COUNTKILL) &&
1238 !(mo->player) &&
1239 !(mo->flags&MF_MISSILE))
1240 { // Must be monster, player, or missile
1241 continue;
1242 }
1243 if (mo->flags2&MF2_DORMANT)
1244 {
1245 continue; // no dormant creatures
1246 }
1247 if ((mo->type == MT_WRAITHB) && (mo->flags2&MF2_DONTDRAW))
1248 {
1249 continue; // no underground wraiths
1250 }
1251 if ((mo->type == MT_SPLASHBASE) ||
1252 (mo->type == MT_SPLASH))
1253 {
1254 continue;
1255 }
1256 if(mo->type == MT_SERPENT || mo->type == MT_SERPENTLEADER)
1257 {
1258 continue;
1259 }
1260 dist = P_AproxDistance(pmo->x - mo->x, pmo->y - mo->y);
1261 if(dist > BLAST_RADIUS_DIST)
1262 { // Out of range
1263 continue;
1264 }
1265 P_BlastMobj(pmo, mo, BLAST_FULLSTRENGTH);
1266 }
1267 }
1268
1269
1270 #define HEAL_RADIUS_DIST 255*FRACUNIT
1271
1272 // Do class specific effect for everyone in radius
P_HealRadius(player_t * player)1273 boolean P_HealRadius(player_t *player)
1274 {
1275 mobj_t *mo;
1276 mobj_t *pmo=player->mo;
1277 thinker_t *think;
1278 fixed_t dist;
1279 int effective=false;
1280 int amount;
1281
1282 for(think = thinkercap.next; think != &thinkercap; think = think->next)
1283 {
1284 if(think->function != P_MobjThinker)
1285 { // Not a mobj thinker
1286 continue;
1287 }
1288 mo = (mobj_t *)think;
1289
1290 if (!mo->player) continue;
1291 if (mo->health <= 0) continue;
1292 dist = P_AproxDistance(pmo->x - mo->x, pmo->y - mo->y);
1293 if(dist > HEAL_RADIUS_DIST)
1294 { // Out of range
1295 continue;
1296 }
1297
1298 switch(player->class)
1299 {
1300 case PCLASS_FIGHTER: // Radius armor boost
1301 if ((P_GiveArmor(mo->player, ARMOR_ARMOR, 1)) ||
1302 (P_GiveArmor(mo->player, ARMOR_SHIELD, 1)) ||
1303 (P_GiveArmor(mo->player, ARMOR_HELMET, 1)) ||
1304 (P_GiveArmor(mo->player, ARMOR_AMULET, 1)))
1305 {
1306 effective=true;
1307 S_StartSound(mo, SFX_MYSTICINCANT);
1308 }
1309 break;
1310 case PCLASS_CLERIC: // Radius heal
1311 amount = 50 + (P_Random()%50);
1312 if (P_GiveBody(mo->player, amount))
1313 {
1314 effective=true;
1315 S_StartSound(mo, SFX_MYSTICINCANT);
1316 }
1317 break;
1318 case PCLASS_MAGE: // Radius mana boost
1319 amount = 50 + (P_Random()%50);
1320 if ((P_GiveMana(mo->player, MANA_1, amount)) ||
1321 (P_GiveMana(mo->player, MANA_2, amount)))
1322 {
1323 effective=true;
1324 S_StartSound(mo, SFX_MYSTICINCANT);
1325 }
1326 break;
1327 case PCLASS_PIG:
1328 default:
1329 break;
1330 }
1331 }
1332 return(effective);
1333 }
1334
1335
1336 //----------------------------------------------------------------------------
1337 //
1338 // PROC P_PlayerNextArtifact
1339 //
1340 //----------------------------------------------------------------------------
1341
P_PlayerNextArtifact(player_t * player)1342 void P_PlayerNextArtifact(player_t *player)
1343 {
1344 extern int inv_ptr;
1345 extern int curpos;
1346
1347 if(player == &players[consoleplayer])
1348 {
1349 inv_ptr--;
1350 if(inv_ptr < 6)
1351 {
1352 curpos--;
1353 if(curpos < 0)
1354 {
1355 curpos = 0;
1356 }
1357 }
1358 if(inv_ptr < 0)
1359 {
1360 inv_ptr = player->inventorySlotNum-1;
1361 if(inv_ptr < 6)
1362 {
1363 curpos = inv_ptr;
1364 }
1365 else
1366 {
1367 curpos = 6;
1368 }
1369 }
1370 player->readyArtifact =
1371 player->inventory[inv_ptr].type;
1372 }
1373 }
1374
1375 //----------------------------------------------------------------------------
1376 //
1377 // PROC P_PlayerRemoveArtifact
1378 //
1379 //----------------------------------------------------------------------------
1380
P_PlayerRemoveArtifact(player_t * player,int slot)1381 void P_PlayerRemoveArtifact(player_t *player, int slot)
1382 {
1383 int i;
1384 extern int inv_ptr;
1385 extern int curpos;
1386
1387 player->artifactCount--;
1388 if(!(--player->inventory[slot].count))
1389 { // Used last of a type - compact the artifact list
1390 player->readyArtifact = arti_none;
1391 player->inventory[slot].type = arti_none;
1392 for(i = slot+1; i < player->inventorySlotNum; i++)
1393 {
1394 player->inventory[i-1] = player->inventory[i];
1395 }
1396 player->inventorySlotNum--;
1397 if(player == &players[consoleplayer])
1398 { // Set position markers and get next readyArtifact
1399 inv_ptr--;
1400 if(inv_ptr < 6)
1401 {
1402 curpos--;
1403 if(curpos < 0)
1404 {
1405 curpos = 0;
1406 }
1407 }
1408 if(inv_ptr >= player->inventorySlotNum)
1409 {
1410 inv_ptr = player->inventorySlotNum-1;
1411 }
1412 if(inv_ptr < 0)
1413 {
1414 inv_ptr = 0;
1415 }
1416 player->readyArtifact =
1417 player->inventory[inv_ptr].type;
1418 }
1419 }
1420 }
1421
1422 //----------------------------------------------------------------------------
1423 //
1424 // PROC P_PlayerUseArtifact
1425 //
1426 //----------------------------------------------------------------------------
1427
P_PlayerUseArtifact(player_t * player,artitype_t arti)1428 void P_PlayerUseArtifact(player_t *player, artitype_t arti)
1429 {
1430 int i;
1431
1432 for(i = 0; i < player->inventorySlotNum; i++)
1433 {
1434 if(player->inventory[i].type == arti)
1435 { // Found match - try to use
1436 if(P_UseArtifact(player, arti))
1437 { // Artifact was used - remove it from inventory
1438 P_PlayerRemoveArtifact(player, i);
1439 if(player == &players[consoleplayer])
1440 {
1441 if(arti < arti_firstpuzzitem)
1442 {
1443 S_StartSound(NULL, SFX_ARTIFACT_USE);
1444 }
1445 else
1446 {
1447 S_StartSound(NULL, SFX_PUZZLE_SUCCESS);
1448 }
1449 ArtifactFlash = 4;
1450 }
1451 }
1452 else if(arti < arti_firstpuzzitem)
1453 { // Unable to use artifact, advance pointer
1454 P_PlayerNextArtifact(player);
1455 }
1456 break;
1457 }
1458 }
1459 }
1460
1461 //==========================================================================
1462 //
1463 // P_UseArtifact
1464 //
1465 // Returns true if the artifact was used.
1466 //
1467 //==========================================================================
1468
P_UseArtifact(player_t * player,artitype_t arti)1469 boolean P_UseArtifact(player_t *player, artitype_t arti)
1470 {
1471 mobj_t *mo;
1472 angle_t angle;
1473 int i;
1474 int count;
1475
1476 switch(arti)
1477 {
1478 case arti_invulnerability:
1479 if(!P_GivePower(player, pw_invulnerability))
1480 {
1481 return(false);
1482 }
1483 break;
1484 case arti_health:
1485 if(!P_GiveBody(player, 25))
1486 {
1487 return(false);
1488 }
1489 break;
1490 case arti_superhealth:
1491 if(!P_GiveBody(player, 100))
1492 {
1493 return(false);
1494 }
1495 break;
1496 case arti_healingradius:
1497 if (!P_HealRadius(player))
1498 {
1499 return(false);
1500 }
1501 break;
1502 case arti_torch:
1503 if(!P_GivePower(player, pw_infrared))
1504 {
1505 return(false);
1506 }
1507 break;
1508 case arti_egg:
1509 mo = player->mo;
1510 P_SpawnPlayerMissile(mo, MT_EGGFX);
1511 P_SPMAngle(mo, MT_EGGFX, mo->angle-(ANG45/6));
1512 P_SPMAngle(mo, MT_EGGFX, mo->angle+(ANG45/6));
1513 P_SPMAngle(mo, MT_EGGFX, mo->angle-(ANG45/3));
1514 P_SPMAngle(mo, MT_EGGFX, mo->angle+(ANG45/3));
1515 break;
1516 case arti_fly:
1517 if(!P_GivePower(player, pw_flight))
1518 {
1519 return(false);
1520 }
1521 if(player->mo->momz <= -35*FRACUNIT)
1522 { // stop falling scream
1523 S_StopSound(player->mo);
1524 }
1525 break;
1526 case arti_summon:
1527 mo = P_SpawnPlayerMissile(player->mo, MT_SUMMON_FX);
1528 if (mo)
1529 {
1530 mo->target = player->mo;
1531 mo->special1 = (int)(player->mo);
1532 mo->momz = 5*FRACUNIT;
1533 }
1534 break;
1535 case arti_teleport:
1536 P_ArtiTele(player);
1537 break;
1538 case arti_teleportother:
1539 P_ArtiTeleportOther(player);
1540 break;
1541 case arti_poisonbag:
1542 angle = player->mo->angle>>ANGLETOFINESHIFT;
1543 if(player->class == PCLASS_CLERIC)
1544 {
1545 mo = P_SpawnMobj(player->mo->x+16*finecosine[angle],
1546 player->mo->y+24*finesine[angle], player->mo->z-
1547 player->mo->floorclip+8*FRACUNIT, MT_POISONBAG);
1548 if(mo)
1549 {
1550 mo->target = player->mo;
1551 }
1552 }
1553 else if(player->class == PCLASS_MAGE)
1554 {
1555 mo = P_SpawnMobj(player->mo->x+16*finecosine[angle],
1556 player->mo->y+24*finesine[angle], player->mo->z-
1557 player->mo->floorclip+8*FRACUNIT, MT_FIREBOMB);
1558 if(mo)
1559 {
1560 mo->target = player->mo;
1561 }
1562 }
1563 else // PCLASS_FIGHTER, obviously (also pig, not so obviously)
1564 {
1565 mo = P_SpawnMobj(player->mo->x, player->mo->y,
1566 player->mo->z-player->mo->floorclip+35*FRACUNIT,
1567 MT_THROWINGBOMB);
1568 if(mo)
1569 {
1570 mo->angle = player->mo->angle+(((P_Random()&7)-4)<<24);
1571 mo->momz = 4*FRACUNIT+((player->lookdir)<<(FRACBITS-4));
1572 mo->z += player->lookdir<<(FRACBITS-4);
1573 P_ThrustMobj(mo, mo->angle, mo->info->speed);
1574 mo->momx += player->mo->momx>>1;
1575 mo->momy += player->mo->momy>>1;
1576 mo->target = player->mo;
1577 mo->tics -= P_Random()&3;
1578 P_CheckMissileSpawn(mo);
1579 }
1580 }
1581 break;
1582 case arti_speed:
1583 if(!P_GivePower(player, pw_speed))
1584 {
1585 return(false);
1586 }
1587 break;
1588 case arti_boostmana:
1589 if(!P_GiveMana(player, MANA_1, MAX_MANA))
1590 {
1591 if(!P_GiveMana(player, MANA_2, MAX_MANA))
1592 {
1593 return false;
1594 }
1595
1596 }
1597 else
1598 {
1599 P_GiveMana(player, MANA_2, MAX_MANA);
1600 }
1601 break;
1602 case arti_boostarmor:
1603 count = 0;
1604
1605 for(i = 0; i < NUMARMOR; i++)
1606 {
1607 count += P_GiveArmor(player, i, 1); // 1 point per armor type
1608 }
1609 if(!count)
1610 {
1611 return false;
1612 }
1613 break;
1614 case arti_blastradius:
1615 P_BlastRadius(player);
1616 break;
1617
1618 case arti_puzzskull:
1619 case arti_puzzgembig:
1620 case arti_puzzgemred:
1621 case arti_puzzgemgreen1:
1622 case arti_puzzgemgreen2:
1623 case arti_puzzgemblue1:
1624 case arti_puzzgemblue2:
1625 case arti_puzzbook1:
1626 case arti_puzzbook2:
1627 case arti_puzzskull2:
1628 case arti_puzzfweapon:
1629 case arti_puzzcweapon:
1630 case arti_puzzmweapon:
1631 case arti_puzzgear1:
1632 case arti_puzzgear2:
1633 case arti_puzzgear3:
1634 case arti_puzzgear4:
1635 if(P_UsePuzzleItem(player, arti-arti_firstpuzzitem))
1636 {
1637 return true;
1638 }
1639 else
1640 {
1641 P_SetYellowMessage(player, TXT_USEPUZZLEFAILED, false);
1642 return false;
1643 }
1644 break;
1645 default:
1646 return false;
1647 }
1648 return true;
1649 }
1650
1651 //============================================================================
1652 //
1653 // A_SpeedFade
1654 //
1655 //============================================================================
1656
A_SpeedFade(mobj_t * actor)1657 void A_SpeedFade(mobj_t *actor)
1658 {
1659 actor->flags |= MF_SHADOW;
1660 actor->flags &= ~MF_ALTSHADOW;
1661 actor->sprite = actor->target->sprite;
1662 }
1663