mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-16 15:41:16 +00:00
523 lines
11 KiB
C++
523 lines
11 KiB
C++
/*
|
|
===========================================================================
|
|
|
|
Doom 3 BFG Edition GPL Source Code
|
|
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
|
|
|
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
|
|
|
Doom 3 BFG Edition Source Code 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 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
|
|
|
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
|
|
|
===========================================================================
|
|
*/
|
|
|
|
#include "Precompiled.h"
|
|
#include "globaldata.h"
|
|
|
|
|
|
#include "doomdef.h"
|
|
#include "d_event.h"
|
|
|
|
#include "p_local.h"
|
|
|
|
#include "doomstat.h"
|
|
|
|
|
|
|
|
// Index of the special effects (INVUL inverse) map.
|
|
|
|
|
|
//
|
|
// Movement.
|
|
//
|
|
|
|
// 16 pixels of bob
|
|
|
|
|
|
|
|
//
|
|
// 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;
|
|
|
|
// DHM - NERVE :: player bob reduced by 25%, MAXBOB reduced by 25% as well
|
|
player->bob = ( fixed_t )( ( float )( player->bob ) * 0.75f );
|
|
if( player->bob > MAXBOB )
|
|
{
|
|
player->bob = MAXBOB;
|
|
}
|
|
|
|
if( ( player->cheats & CF_NOMOMENTUM ) || !::g->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 *::g->leveltime )&FINEMASK;
|
|
bob = FixedMul( player->bob / 2, finesine[angle] );
|
|
|
|
|
|
// move ::g->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 ::g->onground.
|
|
::g->onground = ( player->mo->z <= player->mo->floorz );
|
|
|
|
if( cmd->forwardmove && ::g->onground )
|
|
{
|
|
P_Thrust( player, player->mo->angle, cmd->forwardmove * 2048 );
|
|
}
|
|
|
|
if( cmd->sidemove && ::g->onground )
|
|
{
|
|
P_Thrust( player, player->mo->angle - ANG90, cmd->sidemove * 2048 );
|
|
}
|
|
|
|
if( ( cmd->forwardmove || cmd->sidemove )
|
|
&& player->mo->state == &::g->states[S_PLAY] )
|
|
{
|
|
P_SetMobjState( player->mo, S_PLAY_RUN1 );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// P_DeathThink
|
|
// Fall on your face when dying.
|
|
// Decrease POV height to floor height.
|
|
//
|
|
extern byte demoversion;
|
|
|
|
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;
|
|
::g->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 > UINT_MAX - ANG5 + 1 ) // SRS - make uint math explicit
|
|
{
|
|
// 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 = wp_fist;
|
|
|
|
// 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( ::g->demoplayback && demoversion < VERSION )
|
|
{
|
|
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 = ( weapontype_t )( ( 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( ( ::g->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 )
|
|
|| ( ::g->gamemode != shareware ) )
|
|
{
|
|
player->pendingweapon = newweapon;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if( cmd->buttons & BT_CHANGE )
|
|
{
|
|
int k, which;
|
|
// The actual changing of the weapon is done
|
|
// when the weapon psprite can do it
|
|
// (read: not in the middle of an attack).
|
|
which = ( ( cmd->buttons & BT_WEAPONMASK ) >> BT_WEAPONSHIFT );
|
|
|
|
if( cmd->nextPrevWeapon > 0 )
|
|
{
|
|
newweapon = player->readyweapon;
|
|
|
|
for( k = 0; k < NUMWEAPONS; ++k )
|
|
{
|
|
newweapon = ( weapontype_t )( ( cmd->nextPrevWeapon - 1 ) ? ( newweapon + 1 ) : ( newweapon - 1 ) );
|
|
|
|
if( newweapon == wp_nochange )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
weapontype_t maxweapon = ( ::g->gamemode == retail ) ? wp_chainsaw : wp_supershotgun;
|
|
|
|
if( newweapon < 0 )
|
|
{
|
|
newweapon = maxweapon;
|
|
}
|
|
|
|
if( newweapon > maxweapon )
|
|
{
|
|
newweapon = wp_fist;
|
|
}
|
|
|
|
|
|
if( player->weaponowned[newweapon] && newweapon != player->readyweapon )
|
|
{
|
|
player->pendingweapon = newweapon;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
newweapon = ( weapontype_t )( ( 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( ( ::g->gamemode == commercial )
|
|
&& newweapon == wp_shotgun
|
|
&& player->weaponowned[wp_supershotgun]
|
|
&& player->readyweapon != wp_supershotgun )
|
|
{
|
|
newweapon = wp_supershotgun;
|
|
}
|
|
|
|
if( player->weaponowned[ newweapon ] && newweapon != player->readyweapon )
|
|
{
|
|
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 ::g->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;
|
|
}
|
|
}
|
|
|
|
|
|
|