8 void P_PlayerNextArtifact(player_t *player);
12 #define MAXBOB 0x100000 // 16 pixels of bob
17 int newtorch; // used in the torch flicker effect.
20 boolean WeaponInShareware[] =
38 = moves the given origin along a given angle
43 void P_Thrust(player_t *player, angle_t angle, fixed_t move)
45 angle >>= ANGLETOFINESHIFT;
46 if(player->powers[pw_flight] && !(player->mo->z <= player->mo->floorz))
48 player->mo->momx += FixedMul(move, finecosine[angle]);
49 player->mo->momy += FixedMul(move, finesine[angle]);
51 else if(player->mo->subsector->sector->special == 15) // Friction_Low
53 player->mo->momx += FixedMul(move>>2, finecosine[angle]);
54 player->mo->momy += FixedMul(move>>2, finesine[angle]);
58 player->mo->momx += FixedMul(move, finecosine[angle]);
59 player->mo->momy += FixedMul(move, finesine[angle]);
69 =Calculate the walking / running height adjustment
74 void P_CalcHeight (player_t *player)
80 // regular movement bobbing (needs to be calculated for gun swing even
82 // OPTIMIZE: tablify angle
84 player->bob = FixedMul (player->mo->momx, player->mo->momx)+
85 FixedMul (player->mo->momy,player->mo->momy);
87 if (player->bob>MAXBOB)
89 if(player->mo->flags2&MF2_FLY && !onground)
91 player->bob = FRACUNIT/2;
94 if ((player->cheats & CF_NOMOMENTUM))
96 player->viewz = player->mo->z + VIEWHEIGHT;
97 if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
98 player->viewz = player->mo->ceilingz-4*FRACUNIT;
99 player->viewz = player->mo->z + player->viewheight;
103 angle = (FINEANGLES/20*leveltime)&FINEMASK;
104 bob = FixedMul ( player->bob/2, finesine[angle]);
109 if (player->playerstate == PST_LIVE)
111 player->viewheight += player->deltaviewheight;
112 if (player->viewheight > VIEWHEIGHT)
114 player->viewheight = VIEWHEIGHT;
115 player->deltaviewheight = 0;
117 if (player->viewheight < VIEWHEIGHT/2)
119 player->viewheight = VIEWHEIGHT/2;
120 if (player->deltaviewheight <= 0)
121 player->deltaviewheight = 1;
124 if (player->deltaviewheight)
126 player->deltaviewheight += FRACUNIT/4;
127 if (!player->deltaviewheight)
128 player->deltaviewheight = 1;
132 if(player->chickenTics)
134 player->viewz = player->mo->z+player->viewheight-(20*FRACUNIT);
138 player->viewz = player->mo->z+player->viewheight+bob;
140 if(player->mo->flags2&MF2_FEETARECLIPPED
141 && player->playerstate != PST_DEAD
142 && player->mo->z <= player->mo->floorz)
144 player->viewz -= FOOTCLIPSIZE;
146 if(player->viewz > player->mo->ceilingz-4*FRACUNIT)
148 player->viewz = player->mo->ceilingz-4*FRACUNIT;
150 if(player->viewz < player->mo->floorz+4*FRACUNIT)
152 player->viewz = player->mo->floorz+4*FRACUNIT;
164 void P_MovePlayer(player_t *player)
171 player->mo->angle += (cmd->angleturn<<16);
173 onground = (player->mo->z <= player->mo->floorz
174 || (player->mo->flags2&MF2_ONMOBJ));
176 if(player->chickenTics)
178 if(cmd->forwardmove && (onground||player->mo->flags2&MF2_FLY))
179 P_Thrust(player, player->mo->angle, cmd->forwardmove*2500);
180 if(cmd->sidemove && (onground||player->mo->flags2&MF2_FLY))
181 P_Thrust(player, player->mo->angle-ANG90, cmd->sidemove*2500);
185 if(cmd->forwardmove && (onground||player->mo->flags2&MF2_FLY))
186 P_Thrust(player, player->mo->angle, cmd->forwardmove*2048);
187 if(cmd->sidemove && (onground||player->mo->flags2&MF2_FLY))
188 P_Thrust(player, player->mo->angle-ANG90, cmd->sidemove*2048);
191 if(cmd->forwardmove || cmd->sidemove)
193 if(player->chickenTics)
195 if(player->mo->state == &states[S_CHICPLAY])
197 P_SetMobjState(player->mo, S_CHICPLAY_RUN1);
202 if(player->mo->state == &states[S_PLAY])
204 P_SetMobjState(player->mo, S_PLAY_RUN1);
209 look = cmd->lookfly&15;
218 player->centering = true;
222 player->lookdir += 5*look;
223 if(player->lookdir > 90 || player->lookdir < -110)
225 player->lookdir -= 5*look;
229 if(player->centering)
231 if(player->lookdir > 0)
233 player->lookdir -= 8;
235 else if(player->lookdir < 0)
237 player->lookdir += 8;
239 if(abs(player->lookdir) < 8)
242 player->centering = false;
245 fly = cmd->lookfly>>4;
250 if(fly && player->powers[pw_flight])
254 player->flyheight = fly*2;
255 if(!(player->mo->flags2&MF2_FLY))
257 player->mo->flags2 |= MF2_FLY;
258 player->mo->flags |= MF_NOGRAVITY;
263 player->mo->flags2 &= ~MF2_FLY;
264 player->mo->flags &= ~MF_NOGRAVITY;
269 P_PlayerUseArtifact(player, arti_fly);
271 if(player->mo->flags2&MF2_FLY)
273 player->mo->momz = player->flyheight*FRACUNIT;
274 if(player->flyheight)
276 player->flyheight /= 2;
289 #define ANG5 (ANG90/18)
291 void P_DeathThink(player_t *player)
293 angle_t angle, delta;
298 P_MovePsprites(player);
300 onground = (player->mo->z <= player->mo->floorz);
301 if(player->mo->type == MT_BLOODYSKULL)
302 { // Flying bloody skull
303 player->viewheight = 6*FRACUNIT;
304 player->deltaviewheight = 0;
305 //player->damagecount = 20;
308 if(player->lookdir < 60)
310 lookDelta = (60-player->lookdir)/8;
311 if(lookDelta < 1 && (leveltime&1))
315 else if(lookDelta > 6)
319 player->lookdir += lookDelta;
325 player->deltaviewheight = 0;
326 if(player->viewheight > 6*FRACUNIT)
327 player->viewheight -= FRACUNIT;
328 if(player->viewheight < 6*FRACUNIT)
329 player->viewheight = 6*FRACUNIT;
330 if(player->lookdir > 0)
332 player->lookdir -= 6;
334 else if(player->lookdir < 0)
336 player->lookdir += 6;
338 if(abs(player->lookdir) < 6)
343 P_CalcHeight(player);
345 if(player->attacker && player->attacker != player->mo)
347 angle = R_PointToAngle2(player->mo->x, player->mo->y,
348 player->attacker->x, player->attacker->y);
349 delta = angle-player->mo->angle;
350 if(delta < ANG5 || delta > (unsigned)-ANG5)
351 { // Looking at killer, so fade damage flash down
352 player->mo->angle = angle;
353 if(player->damagecount)
355 player->damagecount--;
358 else if(delta < ANG180)
359 player->mo->angle += ANG5;
361 player->mo->angle -= ANG5;
363 else if(player->damagecount)
365 player->damagecount--;
368 if(player->cmd.buttons&BT_USE)
370 if(player == &players[consoleplayer])
372 I_SetPalette((byte *)W_CacheLumpName("PLAYPAL", PU_CACHE));
378 player->playerstate = PST_REBORN;
379 // Let the mobj know the player has entered the reborn state. Some
380 // mobjs need to know when it's ok to remove themselves.
381 player->mo->special2 = 666;
385 //----------------------------------------------------------------------------
387 // PROC P_ChickenPlayerThink
389 //----------------------------------------------------------------------------
391 void P_ChickenPlayerThink(player_t *player)
395 if(player->health > 0)
396 { // Handle beak movement
397 P_UpdateBeak(player, &player->psprites[ps_weapon]);
399 if(player->chickenTics&15)
404 if(!(pmo->momx+pmo->momy) && P_Random() < 160)
405 { // Twitch view angle
406 pmo->angle += (P_Random()-P_Random())<<19;
408 if((pmo->z <= pmo->floorz) && (P_Random() < 32))
410 pmo->momz += FRACUNIT;
411 P_SetMobjState(pmo, S_CHICPLAY_PAIN);
416 S_StartSound(pmo, sfx_chicact);
420 //----------------------------------------------------------------------------
422 // FUNC P_GetPlayerNum
424 //----------------------------------------------------------------------------
426 int P_GetPlayerNum(player_t *player)
430 for(i = 0; i < MAXPLAYERS; i++)
432 if(player == &players[i])
440 //----------------------------------------------------------------------------
442 // FUNC P_UndoPlayerChicken
444 //----------------------------------------------------------------------------
446 boolean P_UndoPlayerChicken(player_t *player)
465 weapon = pmo->special1;
466 oldFlags = pmo->flags;
467 oldFlags2 = pmo->flags2;
468 P_SetMobjState(pmo, S_FREETARGMOBJ);
469 mo = P_SpawnMobj(x, y, z, MT_PLAYER);
470 if(P_TestMobjLocation(mo) == false)
473 mo = P_SpawnMobj(x, y, z, MT_CHICPLAYER);
475 mo->health = player->health;
476 mo->special1 = weapon;
478 mo->flags = oldFlags;
479 mo->flags2 = oldFlags2;
481 player->chickenTics = 2*35;
484 playerNum = P_GetPlayerNum(player);
486 { // Set color translation
487 mo->flags |= playerNum<<MF_TRANSSHIFT;
491 mo->reactiontime = 18;
492 if(oldFlags2&MF2_FLY)
494 mo->flags2 |= MF2_FLY;
495 mo->flags |= MF_NOGRAVITY;
497 player->chickenTics = 0;
498 player->powers[pw_weaponlevel2] = 0;
499 player->health = mo->health = MAXHEALTH;
501 angle >>= ANGLETOFINESHIFT;
502 fog = P_SpawnMobj(x+20*finecosine[angle],
503 y+20*finesine[angle], z+TELEFOGHEIGHT, MT_TFOG);
504 S_StartSound(fog, sfx_telept);
505 P_PostChickenWeapon(player, weapon);
509 //----------------------------------------------------------------------------
511 // PROC P_PlayerThink
513 //----------------------------------------------------------------------------
515 void P_PlayerThink(player_t *player)
518 weapontype_t newweapon;
520 extern boolean ultimatemsg;
523 if(player->cheats&CF_NOCLIP)
525 player->mo->flags |= MF_NOCLIP;
529 player->mo->flags &= ~MF_NOCLIP;
532 if(player->mo->flags&MF_JUSTATTACKED)
533 { // Gauntlets attack auto forward motion
535 cmd->forwardmove = 0xc800/512;
537 player->mo->flags &= ~MF_JUSTATTACKED;
539 // messageTics is above the rest of the counters so that messages will
540 // go away, even in death.
541 player->messageTics--; // Can go negative
542 if(!player->messageTics)
543 { // Refresh the screen when a message goes away
544 ultimatemsg = false; // clear out any chat messages.
545 BorderTopRefresh = true;
547 if(player->playerstate == PST_DEAD)
549 P_DeathThink(player);
552 if(player->chickenTics)
554 P_ChickenPlayerThink(player);
557 if(player->mo->reactiontime)
558 { // Player is frozen
559 player->mo->reactiontime--;
563 P_MovePlayer(player);
565 P_CalcHeight(player);
566 if(player->mo->subsector->sector->special)
568 P_PlayerInSpecialSector(player);
572 if(cmd->arti == 0xff)
574 P_PlayerNextArtifact(player);
578 P_PlayerUseArtifact(player, cmd->arti);
581 // Check for weapon change
582 if(cmd->buttons&BT_SPECIAL)
583 { // A special event has no other buttons
586 if(cmd->buttons&BT_CHANGE)
588 // The actual changing of the weapon is done when the weapon
589 // psprite can do it (A_WeaponReady), so it doesn't happen in
590 // the middle of an attack.
591 newweapon = (cmd->buttons&BT_WEAPONMASK)>>BT_WEAPONSHIFT;
592 if(newweapon == wp_staff && player->weaponowned[wp_gauntlets]
593 && !(player->readyweapon == wp_gauntlets))
595 newweapon = wp_gauntlets;
597 if(player->weaponowned[newweapon]
598 && newweapon != player->readyweapon)
600 if(WeaponInShareware[newweapon] || !shareware)
602 player->pendingweapon = newweapon;
607 if(cmd->buttons&BT_USE)
612 player->usedown = true;
617 player->usedown = false;
620 if(player->chickenTics)
622 if(player->chickenPeck)
623 { // Chicken attack counter
624 player->chickenPeck -= 3;
626 if(!--player->chickenTics)
627 { // Attempt to undo the chicken
628 P_UndoPlayerChicken(player);
632 P_MovePsprites(player);
634 if(player->powers[pw_invulnerability])
636 player->powers[pw_invulnerability]--;
638 if(player->powers[pw_invisibility])
640 if(!--player->powers[pw_invisibility])
642 player->mo->flags &= ~MF_SHADOW;
645 if(player->powers[pw_infrared])
647 player->powers[pw_infrared]--;
649 if(player->powers[pw_flight])
651 if(!--player->powers[pw_flight])
654 if(player->mo->z != player->mo->floorz && !useexterndriver)
656 player->centering = true;
659 if(player->mo->z != player->mo->floorz)
661 player->centering = true;
665 player->mo->flags2 &= ~MF2_FLY;
666 player->mo->flags &= ~MF_NOGRAVITY;
667 BorderTopRefresh = true; //make sure the sprite's cleared out
670 if(player->powers[pw_weaponlevel2])
672 if(!--player->powers[pw_weaponlevel2])
674 if((player->readyweapon == wp_phoenixrod)
675 && (player->psprites[ps_weapon].state
676 != &states[S_PHOENIXREADY])
677 && (player->psprites[ps_weapon].state
678 != &states[S_PHOENIXUP]))
680 P_SetPsprite(player, ps_weapon, S_PHOENIXREADY);
681 player->ammo[am_phoenixrod] -= USE_PHRD_AMMO_2;
684 else if((player->readyweapon == wp_gauntlets)
685 || (player->readyweapon == wp_staff))
687 player->pendingweapon = player->readyweapon;
689 BorderTopRefresh = true;
692 if(player->damagecount)
694 player->damagecount--;
696 if(player->bonuscount)
698 player->bonuscount--;
701 if(player->powers[pw_invulnerability])
703 if(player->powers[pw_invulnerability] > BLINKTHRESHOLD
704 || (player->powers[pw_invulnerability]&8))
706 player->fixedcolormap = INVERSECOLORMAP;
710 player->fixedcolormap = 0;
713 else if(player->powers[pw_infrared])
715 if (player->powers[pw_infrared] <= BLINKTHRESHOLD)
717 if(player->powers[pw_infrared]&8)
719 player->fixedcolormap = 0;
723 player->fixedcolormap = 1;
726 else if(!(leveltime&16) && player == &players[consoleplayer])
730 if(player->fixedcolormap+newtorchdelta > 7
731 || player->fixedcolormap+newtorchdelta < 1
732 || newtorch == player->fixedcolormap)
738 player->fixedcolormap += newtorchdelta;
743 newtorch = (M_Random()&7)+1;
744 newtorchdelta = (newtorch == player->fixedcolormap) ?
745 0 : ((newtorch > player->fixedcolormap) ? 1 : -1);
751 player->fixedcolormap = 0;
755 //----------------------------------------------------------------------------
759 //----------------------------------------------------------------------------
761 void P_ArtiTele(player_t *player)
771 selections = deathmatch_p-deathmatchstarts;
772 i = P_Random()%selections;
773 destX = deathmatchstarts[i].x<<FRACBITS;
774 destY = deathmatchstarts[i].y<<FRACBITS;
775 destAngle = ANG45*(deathmatchstarts[i].angle/45);
779 destX = playerstarts[0].x<<FRACBITS;
780 destY = playerstarts[0].y<<FRACBITS;
781 destAngle = ANG45*(playerstarts[0].angle/45);
783 P_Teleport(player->mo, destX, destY, destAngle);
784 S_StartSound(NULL, sfx_wpnup); // Full volume laugh
787 //----------------------------------------------------------------------------
789 // PROC P_PlayerNextArtifact
791 //----------------------------------------------------------------------------
793 void P_PlayerNextArtifact(player_t *player)
798 if(player == &players[consoleplayer])
811 inv_ptr = player->inventorySlotNum-1;
821 player->readyArtifact =
822 player->inventory[inv_ptr].type;
826 //----------------------------------------------------------------------------
828 // PROC P_PlayerRemoveArtifact
830 //----------------------------------------------------------------------------
832 void P_PlayerRemoveArtifact(player_t *player, int slot)
838 player->artifactCount--;
839 if(!(--player->inventory[slot].count))
840 { // Used last of a type - compact the artifact list
841 player->readyArtifact = arti_none;
842 player->inventory[slot].type = arti_none;
843 for(i = slot+1; i < player->inventorySlotNum; i++)
845 player->inventory[i-1] = player->inventory[i];
847 player->inventorySlotNum--;
848 if(player == &players[consoleplayer])
849 { // Set position markers and get next readyArtifact
859 if(inv_ptr >= player->inventorySlotNum)
861 inv_ptr = player->inventorySlotNum-1;
867 player->readyArtifact =
868 player->inventory[inv_ptr].type;
873 //----------------------------------------------------------------------------
875 // PROC P_PlayerUseArtifact
877 //----------------------------------------------------------------------------
879 void P_PlayerUseArtifact(player_t *player, artitype_t arti)
883 for(i = 0; i < player->inventorySlotNum; i++)
885 if(player->inventory[i].type == arti)
886 { // Found match - try to use
887 if(P_UseArtifact(player, arti))
888 { // Artifact was used - remove it from inventory
889 P_PlayerRemoveArtifact(player, i);
890 if(player == &players[consoleplayer])
892 S_StartSound(NULL, sfx_artiuse);
897 { // Unable to use artifact, advance pointer
898 P_PlayerNextArtifact(player);
905 //----------------------------------------------------------------------------
907 // FUNC P_UseArtifact
909 // Returns true if artifact was used.
911 //----------------------------------------------------------------------------
913 boolean P_UseArtifact(player_t *player, artitype_t arti)
920 case arti_invulnerability:
921 if(!P_GivePower(player, pw_invulnerability))
926 case arti_invisibility:
927 if(!P_GivePower(player, pw_invisibility))
933 if(!P_GiveBody(player, 25))
938 case arti_superhealth:
939 if(!P_GiveBody(player, 100))
944 case arti_tomeofpower:
945 if(player->chickenTics)
946 { // Attempt to undo chicken
947 if(P_UndoPlayerChicken(player) == false)
949 P_DamageMobj(player->mo, NULL, NULL, 10000);
953 player->chickenTics = 0;
954 S_StartSound(player->mo, sfx_wpnup);
959 if(!P_GivePower(player, pw_weaponlevel2))
963 if(player->readyweapon == wp_staff)
965 P_SetPsprite(player, ps_weapon, S_STAFFREADY2_1);
967 else if(player->readyweapon == wp_gauntlets)
969 P_SetPsprite(player, ps_weapon, S_GAUNTLETREADY2_1);
974 if(!P_GivePower(player, pw_infrared))
980 angle = player->mo->angle>>ANGLETOFINESHIFT;
981 mo = P_SpawnMobj(player->mo->x+24*finecosine[angle],
982 player->mo->y+24*finesine[angle], player->mo->z - 15*FRACUNIT*
983 ((player->mo->flags2&MF2_FEETARECLIPPED) != 0), MT_FIREBOMB);
984 mo->target = player->mo;
988 P_SpawnPlayerMissile(mo, MT_EGGFX);
989 P_SPMAngle(mo, MT_EGGFX, mo->angle-(ANG45/6));
990 P_SPMAngle(mo, MT_EGGFX, mo->angle+(ANG45/6));
991 P_SPMAngle(mo, MT_EGGFX, mo->angle-(ANG45/3));
992 P_SPMAngle(mo, MT_EGGFX, mo->angle+(ANG45/3));
995 if(!P_GivePower(player, pw_flight))