summaryrefslogtreecommitdiff
path: root/src/doom/p_user.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/doom/p_user.c')
-rw-r--r--src/doom/p_user.c387
1 files changed, 387 insertions, 0 deletions
diff --git a/src/doom/p_user.c b/src/doom/p_user.c
new file mode 100644
index 00000000..2ff7f818
--- /dev/null
+++ b/src/doom/p_user.c
@@ -0,0 +1,387 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Player related stuff.
+// Bobbing POV/weapon, movement.
+// Pending weapon.
+//
+//-----------------------------------------------------------------------------
+
+
+
+
+#include "doomdef.h"
+#include "d_event.h"
+
+#include "p_local.h"
+
+#include "doomstat.h"
+
+
+
+// Index of the special effects (INVUL inverse) map.
+#define INVERSECOLORMAP 32
+
+
+//
+// Movement.
+//
+
+// 16 pixels of bob
+#define MAXBOB 0x100000
+
+boolean onground;
+
+
+//
+// P_Thrust
+// Moves the given origin along a given angle.
+//
+void
+P_Thrust
+( player_t* player,
+ angle_t angle,
+ fixed_t move )
+{
+ angle >>= ANGLETOFINESHIFT;
+
+ player->mo->momx += FixedMul(move,finecosine[angle]);
+ player->mo->momy += FixedMul(move,finesine[angle]);
+}
+
+
+
+
+//
+// P_CalcHeight
+// Calculate the walking / running height adjustment
+//
+void P_CalcHeight (player_t* player)
+{
+ int angle;
+ fixed_t bob;
+
+ // Regular movement bobbing
+ // (needs to be calculated for gun swing
+ // even if not on ground)
+ // OPTIMIZE: tablify angle
+ // Note: a LUT allows for effects
+ // like a ramp with low health.
+ player->bob =
+ FixedMul (player->mo->momx, player->mo->momx)
+ + FixedMul (player->mo->momy,player->mo->momy);
+
+ player->bob >>= 2;
+
+ if (player->bob>MAXBOB)
+ player->bob = MAXBOB;
+
+ if ((player->cheats & CF_NOMOMENTUM) || !onground)
+ {
+ player->viewz = player->mo->z + VIEWHEIGHT;
+
+ if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
+ player->viewz = player->mo->ceilingz-4*FRACUNIT;
+
+ player->viewz = player->mo->z + player->viewheight;
+ return;
+ }
+
+ angle = (FINEANGLES/20*leveltime)&FINEMASK;
+ bob = FixedMul ( player->bob/2, finesine[angle]);
+
+
+ // move viewheight
+ if (player->playerstate == PST_LIVE)
+ {
+ player->viewheight += player->deltaviewheight;
+
+ if (player->viewheight > VIEWHEIGHT)
+ {
+ player->viewheight = VIEWHEIGHT;
+ player->deltaviewheight = 0;
+ }
+
+ if (player->viewheight < VIEWHEIGHT/2)
+ {
+ player->viewheight = VIEWHEIGHT/2;
+ if (player->deltaviewheight <= 0)
+ player->deltaviewheight = 1;
+ }
+
+ if (player->deltaviewheight)
+ {
+ player->deltaviewheight += FRACUNIT/4;
+ if (!player->deltaviewheight)
+ player->deltaviewheight = 1;
+ }
+ }
+ player->viewz = player->mo->z + player->viewheight + bob;
+
+ if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
+ player->viewz = player->mo->ceilingz-4*FRACUNIT;
+}
+
+
+
+//
+// P_MovePlayer
+//
+void P_MovePlayer (player_t* player)
+{
+ ticcmd_t* cmd;
+
+ cmd = &player->cmd;
+
+ player->mo->angle += (cmd->angleturn<<16);
+
+ // Do not let the player control movement
+ // if not onground.
+ onground = (player->mo->z <= player->mo->floorz);
+
+ if (cmd->forwardmove && onground)
+ P_Thrust (player, player->mo->angle, cmd->forwardmove*2048);
+
+ if (cmd->sidemove && onground)
+ P_Thrust (player, player->mo->angle-ANG90, cmd->sidemove*2048);
+
+ if ( (cmd->forwardmove || cmd->sidemove)
+ && player->mo->state == &states[S_PLAY] )
+ {
+ P_SetMobjState (player->mo, S_PLAY_RUN1);
+ }
+}
+
+
+
+//
+// P_DeathThink
+// Fall on your face when dying.
+// Decrease POV height to floor height.
+//
+#define ANG5 (ANG90/18)
+
+void P_DeathThink (player_t* player)
+{
+ angle_t angle;
+ angle_t delta;
+
+ P_MovePsprites (player);
+
+ // fall to the ground
+ if (player->viewheight > 6*FRACUNIT)
+ player->viewheight -= FRACUNIT;
+
+ if (player->viewheight < 6*FRACUNIT)
+ player->viewheight = 6*FRACUNIT;
+
+ player->deltaviewheight = 0;
+ onground = (player->mo->z <= player->mo->floorz);
+ P_CalcHeight (player);
+
+ if (player->attacker && player->attacker != player->mo)
+ {
+ angle = R_PointToAngle2 (player->mo->x,
+ player->mo->y,
+ player->attacker->x,
+ player->attacker->y);
+
+ delta = angle - player->mo->angle;
+
+ if (delta < ANG5 || delta > (unsigned)-ANG5)
+ {
+ // Looking at killer,
+ // so fade damage flash down.
+ player->mo->angle = angle;
+
+ if (player->damagecount)
+ player->damagecount--;
+ }
+ else if (delta < ANG180)
+ player->mo->angle += ANG5;
+ else
+ player->mo->angle -= ANG5;
+ }
+ else if (player->damagecount)
+ player->damagecount--;
+
+
+ if (player->cmd.buttons & BT_USE)
+ player->playerstate = PST_REBORN;
+}
+
+
+
+//
+// P_PlayerThink
+//
+void P_PlayerThink (player_t* player)
+{
+ ticcmd_t* cmd;
+ weapontype_t newweapon;
+
+ // fixme: do this in the cheat code
+ if (player->cheats & CF_NOCLIP)
+ player->mo->flags |= MF_NOCLIP;
+ else
+ player->mo->flags &= ~MF_NOCLIP;
+
+ // chain saw run forward
+ cmd = &player->cmd;
+ if (player->mo->flags & MF_JUSTATTACKED)
+ {
+ cmd->angleturn = 0;
+ cmd->forwardmove = 0xc800/512;
+ cmd->sidemove = 0;
+ player->mo->flags &= ~MF_JUSTATTACKED;
+ }
+
+
+ if (player->playerstate == PST_DEAD)
+ {
+ P_DeathThink (player);
+ return;
+ }
+
+ // Move around.
+ // Reactiontime is used to prevent movement
+ // for a bit after a teleport.
+ if (player->mo->reactiontime)
+ player->mo->reactiontime--;
+ else
+ P_MovePlayer (player);
+
+ P_CalcHeight (player);
+
+ if (player->mo->subsector->sector->special)
+ P_PlayerInSpecialSector (player);
+
+ // Check for weapon change.
+
+ // A special event has no other buttons.
+ if (cmd->buttons & BT_SPECIAL)
+ cmd->buttons = 0;
+
+ if (cmd->buttons & BT_CHANGE)
+ {
+ // The actual changing of the weapon is done
+ // when the weapon psprite can do it
+ // (read: not in the middle of an attack).
+ newweapon = (cmd->buttons&BT_WEAPONMASK)>>BT_WEAPONSHIFT;
+
+ if (newweapon == wp_fist
+ && player->weaponowned[wp_chainsaw]
+ && !(player->readyweapon == wp_chainsaw
+ && player->powers[pw_strength]))
+ {
+ newweapon = wp_chainsaw;
+ }
+
+ if ( (gamemode == commercial)
+ && newweapon == wp_shotgun
+ && player->weaponowned[wp_supershotgun]
+ && player->readyweapon != wp_supershotgun)
+ {
+ newweapon = wp_supershotgun;
+ }
+
+
+ if (player->weaponowned[newweapon]
+ && newweapon != player->readyweapon)
+ {
+ // Do not go to plasma or BFG in shareware,
+ // even if cheated.
+ if ((newweapon != wp_plasma
+ && newweapon != wp_bfg)
+ || (gamemode != shareware) )
+ {
+ player->pendingweapon = newweapon;
+ }
+ }
+ }
+
+ // check for use
+ if (cmd->buttons & BT_USE)
+ {
+ if (!player->usedown)
+ {
+ P_UseLines (player);
+ player->usedown = true;
+ }
+ }
+ else
+ player->usedown = false;
+
+ // cycle psprites
+ P_MovePsprites (player);
+
+ // Counters, time dependend power ups.
+
+ // Strength counts up to diminish fade.
+ if (player->powers[pw_strength])
+ player->powers[pw_strength]++;
+
+ if (player->powers[pw_invulnerability])
+ player->powers[pw_invulnerability]--;
+
+ if (player->powers[pw_invisibility])
+ if (! --player->powers[pw_invisibility] )
+ player->mo->flags &= ~MF_SHADOW;
+
+ if (player->powers[pw_infrared])
+ player->powers[pw_infrared]--;
+
+ if (player->powers[pw_ironfeet])
+ player->powers[pw_ironfeet]--;
+
+ if (player->damagecount)
+ player->damagecount--;
+
+ if (player->bonuscount)
+ player->bonuscount--;
+
+
+ // Handling colormaps.
+ if (player->powers[pw_invulnerability])
+ {
+ if (player->powers[pw_invulnerability] > 4*32
+ || (player->powers[pw_invulnerability]&8) )
+ player->fixedcolormap = INVERSECOLORMAP;
+ else
+ player->fixedcolormap = 0;
+ }
+ else if (player->powers[pw_infrared])
+ {
+ if (player->powers[pw_infrared] > 4*32
+ || (player->powers[pw_infrared]&8) )
+ {
+ // almost full bright
+ player->fixedcolormap = 1;
+ }
+ else
+ player->fixedcolormap = 0;
+ }
+ else
+ player->fixedcolormap = 0;
+}
+
+