9 void P_PlayerNextArtifact(player_t *player);
13 #define MAXBOB 0x100000 // 16 pixels of bob
18 int newtorch; // used in the torch flicker effect.
21 boolean WeaponInShareware[] =
39 = moves the given origin along a given angle
44 void P_Thrust(player_t *player, angle_t angle, fixed_t move)
46 angle >>= ANGLETOFINESHIFT;
47 if(player->powers[pw_flight] && !(player->mo->z <= player->mo->floorz))
49 player->mo->momx += FixedMul(move, finecosine[angle]);
50 player->mo->momy += FixedMul(move, finesine[angle]);
52 else if(player->mo->subsector->sector->special == 15) // Friction_Low
54 player->mo->momx += FixedMul(move>>2, finecosine[angle]);
55 player->mo->momy += FixedMul(move>>2, finesine[angle]);
59 player->mo->momx += FixedMul(move, finecosine[angle]);
60 player->mo->momy += FixedMul(move, finesine[angle]);
70 =Calculate the walking / running height adjustment
75 void P_CalcHeight (player_t *player)
81 // regular movement bobbing (needs to be calculated for gun swing even
83 // OPTIMIZE: tablify angle
85 player->bob = FixedMul (player->mo->momx, player->mo->momx)+
86 FixedMul (player->mo->momy,player->mo->momy);
88 if (player->bob>MAXBOB)
90 if(player->mo->flags2&MF2_FLY && !onground)
92 player->bob = FRACUNIT/2;
95 if ((player->cheats & CF_NOMOMENTUM))
97 player->viewz = player->mo->z + VIEWHEIGHT;
98 if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
99 player->viewz = player->mo->ceilingz-4*FRACUNIT;
100 player->viewz = player->mo->z + player->viewheight;
104 angle = (FINEANGLES/20*leveltime)&FINEMASK;
105 bob = FixedMul ( player->bob/2, finesine[angle]);
110 if (player->playerstate == PST_LIVE)
112 player->viewheight += player->deltaviewheight;
113 if (player->viewheight > VIEWHEIGHT)
115 player->viewheight = VIEWHEIGHT;
116 player->deltaviewheight = 0;
118 if (player->viewheight < VIEWHEIGHT/2)
120 player->viewheight = VIEWHEIGHT/2;
121 if (player->deltaviewheight <= 0)
122 player->deltaviewheight = 1;
125 if (player->deltaviewheight)
127 player->deltaviewheight += FRACUNIT/4;
128 if (!player->deltaviewheight)
129 player->deltaviewheight = 1;
133 if(player->chickenTics)
135 player->viewz = player->mo->z+player->viewheight-(20*FRACUNIT);
139 player->viewz = player->mo->z+player->viewheight+bob;
141 if(player->mo->flags2&MF2_FEETARECLIPPED
142 && player->playerstate != PST_DEAD
143 && player->mo->z <= player->mo->floorz)
145 player->viewz -= FOOTCLIPSIZE;
147 if(player->viewz > player->mo->ceilingz-4*FRACUNIT)
149 player->viewz = player->mo->ceilingz-4*FRACUNIT;
151 if(player->viewz < player->mo->floorz+4*FRACUNIT)
153 player->viewz = player->mo->floorz+4*FRACUNIT;
165 void P_MovePlayer(player_t *player)
172 player->mo->angle += (cmd->angleturn<<16);
174 onground = (player->mo->z <= player->mo->floorz
175 || (player->mo->flags2&MF2_ONMOBJ));
177 if(player->chickenTics)
179 if(cmd->forwardmove && (onground||player->mo->flags2&MF2_FLY))
180 P_Thrust(player, player->mo->angle, cmd->forwardmove*2500);
181 if(cmd->sidemove && (onground||player->mo->flags2&MF2_FLY))
182 P_Thrust(player, player->mo->angle-ANG90, cmd->sidemove*2500);
186 if(cmd->forwardmove && (onground||player->mo->flags2&MF2_FLY))
187 P_Thrust(player, player->mo->angle, cmd->forwardmove*2048);
188 if(cmd->sidemove && (onground||player->mo->flags2&MF2_FLY))
189 P_Thrust(player, player->mo->angle-ANG90, cmd->sidemove*2048);
192 if(cmd->forwardmove || cmd->sidemove)
194 if(player->chickenTics)
196 if(player->mo->state == &states[S_CHICPLAY])
198 P_SetMobjState(player->mo, S_CHICPLAY_RUN1);
203 if(player->mo->state == &states[S_PLAY])
205 P_SetMobjState(player->mo, S_PLAY_RUN1);
210 look = cmd->lookfly&15;
219 player->centering = true;
223 player->lookdir += 5*look;
224 if(player->lookdir > 90 || player->lookdir < -110)
226 player->lookdir -= 5*look;
230 if(player->centering)
232 if(player->lookdir > 0)
234 player->lookdir -= 8;
236 else if(player->lookdir < 0)
238 player->lookdir += 8;
240 if(abs(player->lookdir) < 8)
243 player->centering = false;
246 fly = cmd->lookfly>>4;
251 if(fly && player->powers[pw_flight])
255 player->flyheight = fly*2;
256 if(!(player->mo->flags2&MF2_FLY))
258 player->mo->flags2 |= MF2_FLY;
259 player->mo->flags |= MF_NOGRAVITY;
264 player->mo->flags2 &= ~MF2_FLY;
265 player->mo->flags &= ~MF_NOGRAVITY;
270 P_PlayerUseArtifact(player, arti_fly);
272 if(player->mo->flags2&MF2_FLY)
274 player->mo->momz = player->flyheight*FRACUNIT;
275 if(player->flyheight)
277 player->flyheight /= 2;
290 #define ANG5 (ANG90/18)
292 void P_DeathThink(player_t *player)
294 angle_t angle, delta;
299 P_MovePsprites(player);
301 onground = (player->mo->z <= player->mo->floorz);
302 if(player->mo->type == MT_BLOODYSKULL)
303 { // Flying bloody skull
304 player->viewheight = 6*FRACUNIT;
305 player->deltaviewheight = 0;
306 //player->damagecount = 20;
309 if(player->lookdir < 60)
311 lookDelta = (60-player->lookdir)/8;
312 if(lookDelta < 1 && (leveltime&1))
316 else if(lookDelta > 6)
320 player->lookdir += lookDelta;
326 player->deltaviewheight = 0;
327 if(player->viewheight > 6*FRACUNIT)
328 player->viewheight -= FRACUNIT;
329 if(player->viewheight < 6*FRACUNIT)
330 player->viewheight = 6*FRACUNIT;
331 if(player->lookdir > 0)
333 player->lookdir -= 6;
335 else if(player->lookdir < 0)
337 player->lookdir += 6;
339 if(abs(player->lookdir) < 6)
344 P_CalcHeight(player);
346 if(player->attacker && player->attacker != player->mo)
348 angle = R_PointToAngle2(player->mo->x, player->mo->y,
349 player->attacker->x, player->attacker->y);
350 delta = angle-player->mo->angle;
351 if(delta < ANG5 || delta > (unsigned)-ANG5)
352 { // Looking at killer, so fade damage flash down
353 player->mo->angle = angle;
354 if(player->damagecount)
356 player->damagecount--;
359 else if(delta < ANG180)
360 player->mo->angle += ANG5;
362 player->mo->angle -= ANG5;
364 else if(player->damagecount)
366 player->damagecount--;
369 if(player->cmd.buttons&BT_USE)
371 if(player == &players[consoleplayer])
373 I_SetPalette((byte *)W_CacheLumpName("PLAYPAL", PU_CACHE));
379 player->playerstate = PST_REBORN;
380 // Let the mobj know the player has entered the reborn state. Some
381 // mobjs need to know when it's ok to remove themselves.
382 player->mo->special2 = 666;
386 //----------------------------------------------------------------------------
388 // PROC P_ChickenPlayerThink
390 //----------------------------------------------------------------------------
392 void P_ChickenPlayerThink(player_t *player)
396 if(player->health > 0)
397 { // Handle beak movement
398 P_UpdateBeak(player, &player->psprites[ps_weapon]);
400 if(player->chickenTics&15)
405 if(!(pmo->momx+pmo->momy) && P_Random() < 160)
406 { // Twitch view angle
407 pmo->angle += (P_Random()-P_Random())<<19;
409 if((pmo->z <= pmo->floorz) && (P_Random() < 32))
411 pmo->momz += FRACUNIT;
412 P_SetMobjState(pmo, S_CHICPLAY_PAIN);
417 S_StartSound(pmo, sfx_chicact);
421 //----------------------------------------------------------------------------
423 // FUNC P_GetPlayerNum
425 //----------------------------------------------------------------------------
427 int P_GetPlayerNum(player_t *player)
431 for(i = 0; i < MAXPLAYERS; i++)
433 if(player == &players[i])
441 //----------------------------------------------------------------------------
443 // FUNC P_UndoPlayerChicken
445 //----------------------------------------------------------------------------
447 boolean P_UndoPlayerChicken(player_t *player)
466 weapon = pmo->special1;
467 oldFlags = pmo->flags;
468 oldFlags2 = pmo->flags2;
469 P_SetMobjState(pmo, S_FREETARGMOBJ);
470 mo = P_SpawnMobj(x, y, z, MT_PLAYER);
471 if(P_TestMobjLocation(mo) == false)
474 mo = P_SpawnMobj(x, y, z, MT_CHICPLAYER);
476 mo->health = player->health;
477 mo->special1 = weapon;
479 mo->flags = oldFlags;
480 mo->flags2 = oldFlags2;
482 player->chickenTics = 2*35;
485 playerNum = P_GetPlayerNum(player);
487 { // Set color translation
488 mo->flags |= playerNum<<MF_TRANSSHIFT;
492 mo->reactiontime = 18;
493 if(oldFlags2&MF2_FLY)
495 mo->flags2 |= MF2_FLY;
496 mo->flags |= MF_NOGRAVITY;
498 player->chickenTics = 0;
499 player->powers[pw_weaponlevel2] = 0;
500 player->health = mo->health = MAXHEALTH;
502 angle >>= ANGLETOFINESHIFT;
503 fog = P_SpawnMobj(x+20*finecosine[angle],
504 y+20*finesine[angle], z+TELEFOGHEIGHT, MT_TFOG);
505 S_StartSound(fog, sfx_telept);
506 P_PostChickenWeapon(player, weapon);
510 //----------------------------------------------------------------------------
512 // PROC P_PlayerThink
514 //----------------------------------------------------------------------------
516 void P_PlayerThink(player_t *player)
519 weapontype_t newweapon;
521 extern boolean ultimatemsg;
524 if(player->cheats&CF_NOCLIP)
526 player->mo->flags |= MF_NOCLIP;
530 player->mo->flags &= ~MF_NOCLIP;
533 if(player->mo->flags&MF_JUSTATTACKED)
534 { // Gauntlets attack auto forward motion
536 cmd->forwardmove = 0xc800/512;
538 player->mo->flags &= ~MF_JUSTATTACKED;
540 // messageTics is above the rest of the counters so that messages will
541 // go away, even in death.
542 player->messageTics--; // Can go negative
543 if(!player->messageTics)
544 { // Refresh the screen when a message goes away
545 ultimatemsg = false; // clear out any chat messages.
546 BorderTopRefresh = true;
548 if(player->playerstate == PST_DEAD)
550 P_DeathThink(player);
553 if(player->chickenTics)
555 P_ChickenPlayerThink(player);
558 if(player->mo->reactiontime)
559 { // Player is frozen
560 player->mo->reactiontime--;
564 P_MovePlayer(player);
566 P_CalcHeight(player);
567 if(player->mo->subsector->sector->special)
569 P_PlayerInSpecialSector(player);
573 if(cmd->arti == 0xff)
575 P_PlayerNextArtifact(player);
579 P_PlayerUseArtifact(player, cmd->arti);
582 // Check for weapon change
583 if(cmd->buttons&BT_SPECIAL)
584 { // A special event has no other buttons
587 if(cmd->buttons&BT_CHANGE)
589 // The actual changing of the weapon is done when the weapon
590 // psprite can do it (A_WeaponReady), so it doesn't happen in
591 // the middle of an attack.
592 newweapon = (cmd->buttons&BT_WEAPONMASK)>>BT_WEAPONSHIFT;
593 if(newweapon == wp_staff && player->weaponowned[wp_gauntlets]
594 && !(player->readyweapon == wp_gauntlets))
596 newweapon = wp_gauntlets;
598 if(player->weaponowned[newweapon]
599 && newweapon != player->readyweapon)
601 if(WeaponInShareware[newweapon] || !shareware)
603 player->pendingweapon = newweapon;
608 if(cmd->buttons&BT_USE)
613 player->usedown = true;
618 player->usedown = false;
621 if(player->chickenTics)
623 if(player->chickenPeck)
624 { // Chicken attack counter
625 player->chickenPeck -= 3;
627 if(!--player->chickenTics)
628 { // Attempt to undo the chicken
629 P_UndoPlayerChicken(player);
633 P_MovePsprites(player);
635 if(player->powers[pw_invulnerability])
637 player->powers[pw_invulnerability]--;
639 if(player->powers[pw_invisibility])
641 if(!--player->powers[pw_invisibility])
643 player->mo->flags &= ~MF_SHADOW;
646 if(player->powers[pw_infrared])
648 player->powers[pw_infrared]--;
650 if(player->powers[pw_flight])
652 if(!--player->powers[pw_flight])
655 if(player->mo->z != player->mo->floorz && !useexterndriver)
657 player->centering = true;
660 if(player->mo->z != player->mo->floorz)
662 player->centering = true;
666 player->mo->flags2 &= ~MF2_FLY;
667 player->mo->flags &= ~MF_NOGRAVITY;
668 BorderTopRefresh = true; //make sure the sprite's cleared out
671 if(player->powers[pw_weaponlevel2])
673 if(!--player->powers[pw_weaponlevel2])
675 if((player->readyweapon == wp_phoenixrod)
676 && (player->psprites[ps_weapon].state
677 != &states[S_PHOENIXREADY])
678 && (player->psprites[ps_weapon].state
679 != &states[S_PHOENIXUP]))
681 P_SetPsprite(player, ps_weapon, S_PHOENIXREADY);
682 player->ammo[am_phoenixrod] -= USE_PHRD_AMMO_2;
685 else if((player->readyweapon == wp_gauntlets)
686 || (player->readyweapon == wp_staff))
688 player->pendingweapon = player->readyweapon;
690 BorderTopRefresh = true;
693 if(player->damagecount)
695 player->damagecount--;
697 if(player->bonuscount)
699 player->bonuscount--;
702 if(player->powers[pw_invulnerability])
704 if(player->powers[pw_invulnerability] > BLINKTHRESHOLD
705 || (player->powers[pw_invulnerability]&8))
707 player->fixedcolormap = INVERSECOLORMAP;
711 player->fixedcolormap = 0;
714 else if(player->powers[pw_infrared])
716 if (player->powers[pw_infrared] <= BLINKTHRESHOLD)
718 if(player->powers[pw_infrared]&8)
720 player->fixedcolormap = 0;
724 player->fixedcolormap = 1;
727 else if(!(leveltime&16) && player == &players[consoleplayer])
731 if(player->fixedcolormap+newtorchdelta > 7
732 || player->fixedcolormap+newtorchdelta < 1
733 || newtorch == player->fixedcolormap)
739 player->fixedcolormap += newtorchdelta;
744 newtorch = (M_Random()&7)+1;
745 newtorchdelta = (newtorch == player->fixedcolormap) ?
746 0 : ((newtorch > player->fixedcolormap) ? 1 : -1);
752 player->fixedcolormap = 0;
756 //----------------------------------------------------------------------------
760 //----------------------------------------------------------------------------
762 void P_ArtiTele(player_t *player)
772 selections = deathmatch_p-deathmatchstarts;
773 i = P_Random()%selections;
774 destX = deathmatchstarts[i].x<<FRACBITS;
775 destY = deathmatchstarts[i].y<<FRACBITS;
776 destAngle = ANG45*(deathmatchstarts[i].angle/45);
780 destX = playerstarts[0].x<<FRACBITS;
781 destY = playerstarts[0].y<<FRACBITS;
782 destAngle = ANG45*(playerstarts[0].angle/45);
784 P_Teleport(player->mo, destX, destY, destAngle);
785 S_StartSound(NULL, sfx_wpnup); // Full volume laugh
788 //----------------------------------------------------------------------------
790 // PROC P_PlayerNextArtifact
792 //----------------------------------------------------------------------------
794 void P_PlayerNextArtifact(player_t *player)
799 if(player == &players[consoleplayer])
812 inv_ptr = player->inventorySlotNum-1;
822 player->readyArtifact =
823 player->inventory[inv_ptr].type;
827 //----------------------------------------------------------------------------
829 // PROC P_PlayerRemoveArtifact
831 //----------------------------------------------------------------------------
833 void P_PlayerRemoveArtifact(player_t *player, int slot)
839 player->artifactCount--;
840 if(!(--player->inventory[slot].count))
841 { // Used last of a type - compact the artifact list
842 player->readyArtifact = arti_none;
843 player->inventory[slot].type = arti_none;
844 for(i = slot+1; i < player->inventorySlotNum; i++)
846 player->inventory[i-1] = player->inventory[i];
848 player->inventorySlotNum--;
849 if(player == &players[consoleplayer])
850 { // Set position markers and get next readyArtifact
860 if(inv_ptr >= player->inventorySlotNum)
862 inv_ptr = player->inventorySlotNum-1;
868 player->readyArtifact =
869 player->inventory[inv_ptr].type;
874 //----------------------------------------------------------------------------
876 // PROC P_PlayerUseArtifact
878 //----------------------------------------------------------------------------
880 void P_PlayerUseArtifact(player_t *player, artitype_t arti)
884 for(i = 0; i < player->inventorySlotNum; i++)
886 if(player->inventory[i].type == arti)
887 { // Found match - try to use
888 if(P_UseArtifact(player, arti))
889 { // Artifact was used - remove it from inventory
890 P_PlayerRemoveArtifact(player, i);
891 if(player == &players[consoleplayer])
893 S_StartSound(NULL, sfx_artiuse);
898 { // Unable to use artifact, advance pointer
899 P_PlayerNextArtifact(player);
906 //----------------------------------------------------------------------------
908 // FUNC P_UseArtifact
910 // Returns true if artifact was used.
912 //----------------------------------------------------------------------------
914 boolean P_UseArtifact(player_t *player, artitype_t arti)
921 case arti_invulnerability:
922 if(!P_GivePower(player, pw_invulnerability))
927 case arti_invisibility:
928 if(!P_GivePower(player, pw_invisibility))
934 if(!P_GiveBody(player, 25))
939 case arti_superhealth:
940 if(!P_GiveBody(player, 100))
945 case arti_tomeofpower:
946 if(player->chickenTics)
947 { // Attempt to undo chicken
948 if(P_UndoPlayerChicken(player) == false)
950 P_DamageMobj(player->mo, NULL, NULL, 10000);
954 player->chickenTics = 0;
955 S_StartSound(player->mo, sfx_wpnup);
960 if(!P_GivePower(player, pw_weaponlevel2))
964 if(player->readyweapon == wp_staff)
966 P_SetPsprite(player, ps_weapon, S_STAFFREADY2_1);
968 else if(player->readyweapon == wp_gauntlets)
970 P_SetPsprite(player, ps_weapon, S_GAUNTLETREADY2_1);
975 if(!P_GivePower(player, pw_infrared))
981 angle = player->mo->angle>>ANGLETOFINESHIFT;
982 mo = P_SpawnMobj(player->mo->x+24*finecosine[angle],
983 player->mo->y+24*finesine[angle], player->mo->z - 15*FRACUNIT*
984 ((player->mo->flags2&MF2_FEETARECLIPPED) != 0), MT_FIREBOMB);
985 mo->target = player->mo;
989 P_SpawnPlayerMissile(mo, MT_EGGFX);
990 P_SPMAngle(mo, MT_EGGFX, mo->angle-(ANG45/6));
991 P_SPMAngle(mo, MT_EGGFX, mo->angle+(ANG45/6));
992 P_SPMAngle(mo, MT_EGGFX, mo->angle-(ANG45/3));
993 P_SPMAngle(mo, MT_EGGFX, mo->angle+(ANG45/3));
996 if(!P_GivePower(player, pw_flight))