- the last scriptified bits of P_PlayerThink.

This commit is contained in:
Christoph Oelckers 2017-05-01 00:25:21 +02:00
parent 6044c876ab
commit abee2805cb
7 changed files with 591 additions and 668 deletions

View file

@ -97,8 +97,6 @@ public:
bool ResetAirSupply (bool playgasp = true);
int GetMaxHealth(bool withupgrades = false) const;
void TweakSpeeds (double &forwardmove, double &sidemove);
void MorphPlayerThink ();
void ActivateMorphWeapon ();
AWeapon *PickNewWeapon (PClassActor *ammotype);
AWeapon *BestWeapon (PClassActor *ammotype);
@ -111,7 +109,6 @@ public:
// These are virtual on the script side only.
void PlayIdle();
void PlayRunning();
void PlayAttacking ();
void PlayAttacking2 ();

View file

@ -1450,6 +1450,13 @@ bool FLevelLocals::IsJumpingAllowed() const
return !(flags & LEVEL_JUMP_NO);
}
DEFINE_ACTION_FUNCTION(FLevelLocals, IsJumpingAllowed)
{
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
ACTION_RETURN_BOOL(self->IsJumpingAllowed());
}
//==========================================================================
//
//
@ -1484,6 +1491,13 @@ bool FLevelLocals::IsFreelookAllowed() const
return !(flags & LEVEL_FREELOOK_NO);
}
DEFINE_ACTION_FUNCTION(FLevelLocals, IsFreelookAllowed)
{
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
ACTION_RETURN_BOOL(self->IsFreelookAllowed());
}
//==========================================================================
//
//
@ -1938,6 +1952,7 @@ DEFINE_FIELD_BIT(FLevelLocals, flags2, missilesactivateimpact, LEVEL2_MISSILESAC
DEFINE_FIELD_BIT(FLevelLocals, flags2, monsterfallingdamage, LEVEL2_MONSTERFALLINGDAMAGE)
DEFINE_FIELD_BIT(FLevelLocals, flags2, checkswitchrange, LEVEL2_CHECKSWITCHRANGE)
DEFINE_FIELD_BIT(FLevelLocals, flags2, polygrind, LEVEL2_POLYGRIND)
DEFINE_FIELD_BIT(FLevelLocals, flags2, allowrespawn, LEVEL2_ALLOWRESPAWN)
DEFINE_FIELD_BIT(FLevelLocals, flags2, nomonsters, LEVEL2_NOMONSTERS)
DEFINE_FIELD_BIT(FLevelLocals, flags2, frozen, LEVEL2_FROZEN)
DEFINE_FIELD_BIT(FLevelLocals, flags2, infinite_flight, LEVEL2_INFINITE_FLIGHT)

View file

@ -102,9 +102,6 @@
static FRandom pr_skullpop ("SkullPop");
// [RH] # of ticks to complete a turn180
#define TURN180_TICKS ((TICRATE / 4) + 1)
// [SP] Allows respawn in single player
CVAR(Bool, sv_singleplayerrespawn, false, CVAR_SERVERINFO | CVAR_LATCH)
@ -1544,15 +1541,6 @@ void APlayerPawn::PlayIdle ()
}
}
void APlayerPawn::PlayRunning ()
{
IFVIRTUAL(APlayerPawn, PlayRunning)
{
VMValue params[1] = { (DObject*)this };
VMCall(func, params, 1, nullptr, 0);
}
}
void APlayerPawn::PlayAttacking ()
{
IFVIRTUAL(APlayerPawn, PlayAttacking)
@ -1660,15 +1648,6 @@ void APlayerPawn::GiveDefaultInventory ()
}
}
void APlayerPawn::MorphPlayerThink ()
{
IFVIRTUAL(APlayerPawn, MorphPlayerThink)
{
VMValue params[1] = { (DObject*)this };
VMCall(func, params, 1, nullptr, 0);
}
}
void APlayerPawn::ActivateMorphWeapon ()
{
PClassActor *morphweapon = PClass::FindActor (MorphWeapon);
@ -1790,48 +1769,6 @@ void APlayerPawn::Die (AActor *source, AActor *inflictor, int dmgflags)
}
}
//===========================================================================
//
// APlayerPawn :: TweakSpeeds
//
//===========================================================================
void APlayerPawn::TweakSpeeds (double &forward, double &side)
{
// Strife's player can't run when its health is below 10
if (health <= RunHealth)
{
forward = clamp<double>(forward, -0x1900, 0x1900);
side = clamp<double>(side, -0x1800, 0x1800);
}
// [GRB]
if (fabs(forward) < 0x3200)
{
forward *= ForwardMove1;
}
else
{
forward *= ForwardMove2;
}
if (fabs(side) < 0x2800)
{
side *= SideMove1;
}
else
{
side *= SideMove2;
}
if (!player->morphTics && Inventory != NULL)
{
double factor = Inventory->GetSpeedFactor ();
forward *= factor;
side *= factor;
}
}
//===========================================================================
//
// A_PlayerScream
@ -2029,57 +1966,6 @@ void P_CheckPlayerSprite(AActor *actor, int &spritenum, DVector2 &scale)
}
}
/*
==================
=
= P_Thrust
=
= moves the given origin along a given angle
=
==================
*/
void P_SideThrust (player_t *player, DAngle angle, double move)
{
player->mo->Thrust(angle-90, move);
}
void P_ForwardThrust (player_t *player, DAngle angle, double move)
{
if ((player->mo->waterlevel || (player->mo->flags & MF_NOGRAVITY))
&& player->mo->Angles.Pitch != 0)
{
double zpush = move * player->mo->Angles.Pitch.Sin();
if (player->mo->waterlevel && player->mo->waterlevel < 2 && zpush < 0)
zpush = 0;
player->mo->Vel.Z -= zpush;
move *= player->mo->Angles.Pitch.Cos();
}
player->mo->Thrust(angle, move);
}
//
// P_Bob
// Same as P_Thrust, but only affects bobbing.
//
// killough 10/98: We apply thrust separately between the real physical player
// and the part which affects bobbing. This way, bobbing only comes from player
// motion, nothing external, avoiding many problems, e.g. bobbing should not
// occur on conveyors, unless the player walks on one, and bobbing should be
// reduced at a regular rate, even on ice (where the player coasts).
//
void P_Bob (player_t *player, DAngle angle, double move, bool forward)
{
if (forward
&& (player->mo->waterlevel || (player->mo->flags & MF_NOGRAVITY))
&& player->mo->Angles.Pitch != 0)
{
move *= player->mo->Angles.Pitch.Cos();
}
player->Vel += angle.ToVector(move);
}
/*
==================
=
@ -2205,115 +2091,19 @@ void P_CalcHeight (player_t *player)
}
}
/*
=================
=
= P_MovePlayer
=
=================
*/
DEFINE_ACTION_FUNCTION(APlayerPawn, CalcHeight)
{
PARAM_SELF_PROLOGUE(APlayerPawn);
P_CalcHeight(self->player);
return 0;
}
CUSTOM_CVAR (Float, sv_aircontrol, 0.00390625f, CVAR_SERVERINFO|CVAR_NOSAVE)
{
level.aircontrol = self;
G_AirControlChanged ();
}
void P_MovePlayer (player_t *player)
{
ticcmd_t *cmd = &player->cmd;
APlayerPawn *mo = player->mo;
// [RH] 180-degree turn overrides all other yaws
if (player->turnticks)
{
player->turnticks--;
mo->Angles.Yaw += (180. / TURN180_TICKS);
}
else
{
mo->Angles.Yaw += cmd->ucmd.yaw * (360./65536.);
}
player->onground = (mo->Z() <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ) || (mo->BounceFlags & BOUNCE_MBF) || (player->cheats & CF_NOCLIP2);
// killough 10/98:
//
// We must apply thrust to the player and bobbing separately, to avoid
// anomalies. The thrust applied to bobbing is always the same strength on
// ice, because the player still "works just as hard" to move, while the
// thrust applied to the movement varies with 'movefactor'.
if (cmd->ucmd.forwardmove | cmd->ucmd.sidemove)
{
double forwardmove, sidemove;
double bobfactor;
double friction, movefactor;
double fm, sm;
movefactor = P_GetMoveFactor (mo, &friction);
bobfactor = friction < ORIG_FRICTION ? movefactor : ORIG_FRICTION_FACTOR;
if (!player->onground && !(player->mo->flags & MF_NOGRAVITY) && !player->mo->waterlevel)
{
// [RH] allow very limited movement if not on ground.
movefactor *= level.aircontrol;
bobfactor*= level.aircontrol;
}
fm = cmd->ucmd.forwardmove;
sm = cmd->ucmd.sidemove;
mo->TweakSpeeds (fm, sm);
fm *= player->mo->Speed / 256;
sm *= player->mo->Speed / 256;
// When crouching, speed and bobbing have to be reduced
if (player->CanCrouch() && player->crouchfactor != 1)
{
fm *= player->crouchfactor;
sm *= player->crouchfactor;
bobfactor *= player->crouchfactor;
}
forwardmove = fm * movefactor * (35 / TICRATE);
sidemove = sm * movefactor * (35 / TICRATE);
if (forwardmove)
{
P_Bob(player, mo->Angles.Yaw, cmd->ucmd.forwardmove * bobfactor / 256., true);
P_ForwardThrust(player, mo->Angles.Yaw, forwardmove);
}
if (sidemove)
{
P_Bob(player, mo->Angles.Yaw - 90, cmd->ucmd.sidemove * bobfactor / 256., false);
P_SideThrust(player, mo->Angles.Yaw, sidemove);
}
if (debugfile)
{
fprintf (debugfile, "move player for pl %d%c: (%f,%f,%f) (%f,%f) %f %f w%d [", int(player-players),
player->cheats&CF_PREDICTING?'p':' ',
player->mo->X(), player->mo->Y(), player->mo->Z(),forwardmove, sidemove, movefactor, friction, player->mo->waterlevel);
msecnode_t *n = player->mo->touching_sectorlist;
while (n != NULL)
{
fprintf (debugfile, "%d ", n->m_sector->sectornum);
n = n->m_tnext;
}
fprintf (debugfile, "]\n");
}
if (!(player->cheats & CF_PREDICTING) && (forwardmove != 0 || sidemove != 0))
{
player->mo->PlayRunning ();
}
if (player->cheats & CF_REVERTPLEASE)
{
player->cheats &= ~CF_REVERTPLEASE;
player->camera = player->mo;
}
}
}
//==========================================================================
//
// P_FallingDamage
@ -2409,117 +2199,6 @@ void P_FallingDamage (AActor *actor)
P_DamageMobj (actor, NULL, NULL, damage, NAME_Falling);
}
//==========================================================================
//
// P_DeathThink
//
//==========================================================================
void P_DeathThink (player_t *player)
{
int dir;
DAngle delta;
player->Uncrouch();
player->TickPSprites();
player->onground = (player->mo->Z() <= player->mo->floorz);
if (player->mo->IsKindOf (PClass::FindActor("PlayerChunk")))
{ // Flying bloody skull or flying ice chunk
player->viewheight = 6;
player->deltaviewheight = 0;
if (player->onground)
{
if (player->mo->Angles.Pitch > -19.)
{
DAngle lookDelta = (-19. - player->mo->Angles.Pitch) / 8;
player->mo->Angles.Pitch += lookDelta;
}
}
}
else if (!(player->mo->flags & MF_ICECORPSE))
{ // Fall to ground (if not frozen)
player->deltaviewheight = 0;
if (player->viewheight > 6)
{
player->viewheight -= 1;
}
if (player->viewheight < 6)
{
player->viewheight = 6;
}
if (player->mo->Angles.Pitch < 0)
{
player->mo->Angles.Pitch += 3;
}
else if (player->mo->Angles.Pitch > 0)
{
player->mo->Angles.Pitch -= 3;
}
if (fabs(player->mo->Angles.Pitch) < 3)
{
player->mo->Angles.Pitch = 0.;
}
}
P_CalcHeight (player);
if (player->attacker && player->attacker != player->mo)
{ // Watch killer
dir = P_FaceMobj (player->mo, player->attacker, &delta);
if (delta < 10)
{ // Looking at killer, so fade damage and poison counters
if (player->damagecount)
{
player->damagecount--;
}
if (player->poisoncount)
{
player->poisoncount--;
}
}
delta /= 8;
if (delta > 5.)
{
delta = 5.;
}
if (dir)
{ // Turn clockwise
player->mo->Angles.Yaw += delta;
}
else
{ // Turn counter clockwise
player->mo->Angles.Yaw -= delta;
}
}
else
{
if (player->damagecount)
{
player->damagecount--;
}
if (player->poisoncount)
{
player->poisoncount--;
}
}
if ((player->cmd.ucmd.buttons & BT_USE ||
((multiplayer || alwaysapplydmflags) && (dmflags & DF_FORCE_RESPAWN))) && !(dmflags2 & DF2_NO_RESPAWN))
{
if (level.time >= player->respawn_time || ((player->cmd.ucmd.buttons & BT_USE) && player->Bot == NULL))
{
player->cls = NULL; // Force a new class if the player is using a random class
player->playerstate =
(multiplayer || (level.flags2 & LEVEL2_ALLOWRESPAWN) || sv_singleplayerrespawn)
? PST_REBORN : PST_ENTER;
if (player->mo->special1 > 2)
{
player->mo->special1 = 0;
}
}
}
}
//----------------------------------------------------------------------------
//
// PROC P_CheckMusicChange
@ -2554,154 +2233,13 @@ void P_CheckMusicChange(player_t *player)
}
}
//----------------------------------------------------------------------------
//
// PROC P_CheckPitch
//
//----------------------------------------------------------------------------
void P_CheckPitch(player_t *player)
DEFINE_ACTION_FUNCTION(APlayerPawn, CheckMusicChange)
{
// [RH] Look up/down stuff
if (!level.IsFreelookAllowed())
{
player->mo->Angles.Pitch = 0.;
}
else
{
// The player's view pitch is clamped between -32 and +56 degrees,
// which translates to about half a screen height up and (more than)
// one full screen height down from straight ahead when view panning
// is used.
int clook = player->cmd.ucmd.pitch;
if (clook != 0)
{
if (clook == -32768)
{ // center view
player->centering = true;
}
else if (!player->centering)
{
// no more overflows with floating point. Yay! :)
player->mo->Angles.Pitch = clamp(player->mo->Angles.Pitch - clook * (360. / 65536.), player->MinPitch, player->MaxPitch);
}
}
}
if (player->centering)
{
if (fabs(player->mo->Angles.Pitch) > 2.)
{
player->mo->Angles.Pitch *= (2. / 3.);
}
else
{
player->mo->Angles.Pitch = 0.;
player->centering = false;
if (player - players == consoleplayer)
{
LocalViewPitch = 0;
}
}
}
PARAM_SELF_PROLOGUE(APlayerPawn);
P_CheckMusicChange(self->player);
return 0;
}
//----------------------------------------------------------------------------
//
// PROC P_CheckJump
//
//----------------------------------------------------------------------------
void P_CheckJump(player_t *player)
{
// [RH] check for jump
if (player->cmd.ucmd.buttons & BT_JUMP)
{
if (player->crouchoffset != 0)
{
// Jumping while crouching will force an un-crouch but not jump
player->crouching = 1;
}
else if (player->mo->waterlevel >= 2)
{
player->mo->Vel.Z = 4 * player->mo->Speed;
}
else if (player->mo->flags & MF_NOGRAVITY)
{
player->mo->Vel.Z = 3.;
}
else if (level.IsJumpingAllowed() && player->onground && player->jumpTics == 0)
{
double jumpvelz = player->mo->JumpZ * 35 / TICRATE;
double jumpfac = 0;
// [BC] If the player has the high jump power, double his jump velocity.
// (actually, pick the best factors from all active items.)
for (auto p = player->mo->Inventory; p != nullptr; p = p->Inventory)
{
if (p->IsKindOf(NAME_PowerHighJump))
{
double f = p->FloatVar(NAME_Strength);
if (f > jumpfac) jumpfac = f;
}
}
if (jumpfac > 0) jumpvelz *= jumpfac;
player->mo->Vel.Z += jumpvelz;
player->mo->flags2 &= ~MF2_ONMOBJ;
player->jumpTics = -1;
if (!(player->cheats & CF_PREDICTING))
S_Sound(player->mo, CHAN_BODY, "*jump", 1, ATTN_NORM);
}
}
}
//----------------------------------------------------------------------------
//
// PROC P_CheckMoveUpDown
//
//----------------------------------------------------------------------------
void P_CheckMoveUpDown(player_t *player)
{
auto cmd = &player->cmd;
if (cmd->ucmd.upmove == -32768)
{ // Only land if in the air
if ((player->mo->flags & MF_NOGRAVITY) && player->mo->waterlevel < 2)
{
//player->mo->flags2 &= ~MF2_FLY;
player->mo->flags &= ~MF_NOGRAVITY;
}
}
else if (cmd->ucmd.upmove != 0)
{
// Clamp the speed to some reasonable maximum.
cmd->ucmd.upmove = clamp<short>(cmd->ucmd.upmove, -0x300, 0x300);
if (player->mo->waterlevel >= 2 || (player->mo->flags2 & MF2_FLY) || (player->cheats & CF_NOCLIP2))
{
player->mo->Vel.Z = player->mo->Speed * cmd->ucmd.upmove / 128.;
if (player->mo->waterlevel < 2 && !(player->mo->flags & MF_NOGRAVITY))
{
player->mo->flags2 |= MF2_FLY;
player->mo->flags |= MF_NOGRAVITY;
if ((player->mo->Vel.Z <= -39) && !(player->cheats & CF_PREDICTING))
{ // Stop falling scream
S_StopSound(player->mo, CHAN_VOICE);
}
}
}
else if (cmd->ucmd.upmove > 0 && !(player->cheats & CF_PREDICTING))
{
AInventory *fly = player->mo->FindInventory(NAME_ArtiFly);
if (fly != NULL)
{
player->mo->UseInventory(fly);
}
}
}
}
//----------------------------------------------------------------------------
//
// PROC P_CheckEnviroment
@ -2731,6 +2269,13 @@ void P_CheckEnvironment(player_t *player)
}
}
DEFINE_ACTION_FUNCTION(APlayerPawn, CheckEnvironment)
{
PARAM_SELF_PROLOGUE(APlayerPawn);
P_CheckEnvironment(self->player);
return 0;
}
//----------------------------------------------------------------------------
//
// PROC P_CheckUse
@ -2757,190 +2302,13 @@ void P_CheckUse(player_t *player)
}
}
//----------------------------------------------------------------------------
//
// PROC P_CheckUndoMorph
//
//----------------------------------------------------------------------------
void P_CheckUndoMorph(player_t *player)
{
// Morph counter
if (player->morphTics)
{
if (player->chickenPeck)
{ // Chicken attack counter
player->chickenPeck -= 3;
}
if (!--player->morphTics)
{ // Attempt to undo the chicken/pig
P_UndoPlayerMorph(player, player, MORPH_UNDOBYTIMEOUT);
}
}
}
//----------------------------------------------------------------------------
//
// PROC P_CheckPoison
//
//----------------------------------------------------------------------------
void P_CheckPoison(player_t *player)
{
if (player->poisoncount && !(level.time & 15))
{
player->poisoncount -= 5;
if (player->poisoncount < 0)
{
player->poisoncount = 0;
}
P_PoisonDamage(player, player->poisoner, 1, true);
}
}
//----------------------------------------------------------------------------
//
// PROC P_CheckDegeneration
//
//----------------------------------------------------------------------------
void P_CheckDegeneration(player_t *player)
{
// Apply degeneration.
if (dmflags2 & DF2_YES_DEGENERATION)
{
int maxhealth = player->mo->GetMaxHealth(true);
if ((level.time % TICRATE) == 0 && player->health > maxhealth)
{
if (player->health - 5 < maxhealth)
player->health = maxhealth;
else
player->health--;
player->mo->health = player->health;
}
}
}
//----------------------------------------------------------------------------
//
// PROC P_CheckAirSupply
//
//----------------------------------------------------------------------------
void P_CheckAirSupply(player_t *player)
{
// Handle air supply
//if (level.airsupply > 0)
{
if (player->mo->waterlevel < 3 ||
(player->mo->flags2 & MF2_INVULNERABLE) ||
(player->cheats & (CF_GODMODE | CF_NOCLIP2)) ||
(player->cheats & CF_GODMODE2))
{
player->mo->ResetAirSupply();
}
else if (player->air_finished <= level.time && !(level.time & 31))
{
P_DamageMobj(player->mo, NULL, NULL, 2 + ((level.time - player->air_finished) / TICRATE), NAME_Drowning);
}
}
}
//----------------------------------------------------------------------------
//
// PROC P_HandleMovement
//
//----------------------------------------------------------------------------
void P_HandleMovement(player_t *player)
{
// [RH] Check for fast turn around
if (player->cmd.ucmd.buttons & BT_TURN180 && !(player->oldbuttons & BT_TURN180))
{
player->turnticks = TURN180_TICKS;
}
// Handle movement
if (player->mo->reactiontime)
{ // Player is frozen
player->mo->reactiontime--;
}
else
{
P_MovePlayer(player);
P_CheckJump(player);
P_CheckMoveUpDown(player);
}
}
DEFINE_ACTION_FUNCTION(APlayerPawn, CheckMusicChange)
{
PARAM_SELF_PROLOGUE(APlayerPawn);
P_CheckMusicChange(self->player);
return 0;
}
DEFINE_ACTION_FUNCTION(APlayerPawn, DeathThink)
{
PARAM_SELF_PROLOGUE(APlayerPawn);
P_DeathThink(self->player);
return 0;
}
DEFINE_ACTION_FUNCTION(APlayerPawn, CheckPitch)
{
PARAM_SELF_PROLOGUE(APlayerPawn);
P_CheckPitch(self->player);
return 0;
}
DEFINE_ACTION_FUNCTION(APlayerPawn, HandleMovement)
{
PARAM_SELF_PROLOGUE(APlayerPawn);
P_HandleMovement(self->player);
return 0;
}
DEFINE_ACTION_FUNCTION(APlayerPawn, CalcHeight)
{
PARAM_SELF_PROLOGUE(APlayerPawn);
P_CalcHeight(self->player);
return 0;
}
DEFINE_ACTION_FUNCTION(APlayerPawn, CheckEnvironment)
{
PARAM_SELF_PROLOGUE(APlayerPawn);
P_CheckEnvironment(self->player);
return 0;
}
DEFINE_ACTION_FUNCTION(APlayerPawn, CheckUse)
{
PARAM_SELF_PROLOGUE(APlayerPawn);
P_CheckUse(self->player);
return 0;
}
DEFINE_ACTION_FUNCTION(APlayerPawn, CheckUndoMorph)
{
PARAM_SELF_PROLOGUE(APlayerPawn);
P_CheckUndoMorph(self->player);
return 0;
}
DEFINE_ACTION_FUNCTION(APlayerPawn, CheckPoison)
{
PARAM_SELF_PROLOGUE(APlayerPawn);
P_CheckPoison(self->player);
return 0;
}
DEFINE_ACTION_FUNCTION(APlayerPawn, CheckDegeneration)
{
PARAM_SELF_PROLOGUE(APlayerPawn);
P_CheckDegeneration(self->player);
return 0;
}
DEFINE_ACTION_FUNCTION(APlayerPawn, CheckAirSupply)
{
PARAM_SELF_PROLOGUE(APlayerPawn);
P_CheckAirSupply(self->player);
return 0;
}
//----------------------------------------------------------------------------
//

View file

@ -154,6 +154,7 @@ FCanvasTextureInfo *FCanvasTextureInfo::List;
DVector3a view;
DAngle viewpitch;
DEFINE_GLOBAL(LocalViewPitch);
// CODE --------------------------------------------------------------------
static void R_Shutdown ();

View file

@ -44,6 +44,8 @@ class Actor : Thinker native
const TELEFRAG_DAMAGE = 1000000;
const MinVel = 1./65536;
const LARGE_MASS = 10000000; // not INT_MAX on purpose
const ORIG_FRICTION = (0xE800/65536.); // original value
const ORIG_FRICTION_FACTOR = (2048/65536.); // original value
// flags are not defined here, the native fields for those get synthesized from the internal tables.

View file

@ -42,6 +42,7 @@ struct _ native // These are the global variables, the struct is only here to av
native readonly int Net_Arbitrator;
native ui BaseStatusBar StatusBar;
native readonly Weapon WP_NOCHANGE;
native int LocalViewPitch;
}
@ -513,6 +514,7 @@ struct LevelLocals native
native readonly bool checkswitchrange;
native readonly bool polygrind;
native readonly bool nomonsters;
native readonly bool allowrespawn;
native bool frozen;
native readonly bool infinite_flight;
native readonly bool no_dlg_freeze;
@ -530,7 +532,9 @@ struct LevelLocals native
native static void RemoveAllBots(bool fromlist);
native void SetInterMusic(String nextmap);
native String FormatMapName(int mapnamecolor);
native bool IsJumpingAllowed() const;
native bool IsCrouchingAllowed() const;
native bool IsFreelookAllowed() const;
String TimeFormatted(bool totals = false)
{

View file

@ -13,6 +13,8 @@ struct UserCmd native
class PlayerPawn : Actor native
{
const CROUCHSPEED = (1./12);
// [RH] # of ticks to complete a turn180
const TURN180_TICKS = ((TICRATE / 4) + 1);
native int crouchsprite;
native int MaxHealth;
@ -216,6 +218,107 @@ class PlayerPawn : Actor native
return -1, -1;
}
//==========================================================================
//
// P_DeathThink
//
//==========================================================================
virtual void DeathThink ()
{
let player = self.player;
int dir;
double delta;
player.Uncrouch();
player.TickPSprites();
player.onground = (pos.Z <= floorz);
if (self is "PlayerChunk")
{ // Flying bloody skull or flying ice chunk
player.viewheight = 6;
player.deltaviewheight = 0;
if (player.onground)
{
if (Pitch > -19.)
{
double lookDelta = (-19. - Pitch) / 8;
Pitch += lookDelta;
}
}
}
else if (!bIceCorpse)
{ // Fall to ground (if not frozen)
player.deltaviewheight = 0;
if (player.viewheight > 6)
{
player.viewheight -= 1;
}
if (player.viewheight < 6)
{
player.viewheight = 6;
}
if (Pitch < 0)
{
Pitch += 3;
}
else if (Pitch > 0)
{
Pitch -= 3;
}
if (abs(Pitch) < 3)
{
Pitch = 0.;
}
}
CalcHeight ();
if (player.attacker && player.attacker != self)
{ // Watch killer
double diff = deltaangle(angle, AngleTo(player.attacker));
double delta = abs(diff);
if (delta < 10)
{ // Looking at killer, so fade damage and poison counters
if (player.damagecount)
{
player.damagecount--;
}
if (player.poisoncount)
{
player.poisoncount--;
}
}
delta /= 8;
Angle += clamp(diff, -5., 5.);
}
else
{
if (player.damagecount)
{
player.damagecount--;
}
if (player.poisoncount)
{
player.poisoncount--;
}
}
if ((player.cmd.buttons & BT_USE ||
((multiplayer || alwaysapplydmflags) && sv_forcerespawn)) && !sv_norespawn)
{
if (level.time >= player.respawn_time || ((player.cmd.buttons & BT_USE) && player.Bot == NULL))
{
player.cls = NULL; // Force a new class if the player is using a random class
player.playerstate = (multiplayer || (level.AllowRespawn) || sv_singleplayerrespawn)? PST_REBORN : PST_ENTER;
if (special1 > 2)
{
special1 = 0;
}
}
}
}
//----------------------------------------------------------------------------
//
// PROC P_CheckFOV
@ -415,26 +518,455 @@ class PlayerPawn : Actor native
player.crouchoffset = -(ViewHeight) * (1 - player.crouchfactor);
}
//----------------------------------------------------------------------------
//
// P_Thrust
//
// moves the given origin along a given angle
//
//----------------------------------------------------------------------------
void ForwardThrust (double move, double angle)
{
if ((waterlevel || bNoGravity) && Pitch != 0)
{
double zpush = move * sin(Pitch);
if (waterlevel && waterlevel < 2 && zpush < 0) zpush = 0;
Vel.Z -= zpush;
move *= cos(Pitch);
}
Thrust(move);
}
//----------------------------------------------------------------------------
//
// P_Bob
// Same as P_Thrust, but only affects bobbing.
//
// killough 10/98: We apply thrust separately between the real physical player
// and the part which affects bobbing. This way, bobbing only comes from player
// motion, nothing external, avoiding many problems, e.g. bobbing should not
// occur on conveyors, unless the player walks on one, and bobbing should be
// reduced at a regular rate, even on ice (where the player coasts).
//
//----------------------------------------------------------------------------
void Bob (double angle, double move, bool forward)
{
if (forward && (waterlevel || bNoGravity) && Pitch != 0)
{
move *= cos(Pitch);
}
player.Vel += AngleToVector(angle, move);
}
//===========================================================================
//
// APlayerPawn :: TweakSpeeds
//
//===========================================================================
double, double TweakSpeeds (double forward, double side)
{
// Strife's player can't run when its health is below 10
if (health <= RunHealth)
{
forward = clamp(forward, -0x1900, 0x1900);
side = clamp(side, -0x1800, 0x1800);
}
// [GRB]
if (abs(forward) < 0x3200)
{
forward *= ForwardMove1;
}
else
{
forward *= ForwardMove2;
}
if (abs(side) < 0x2800)
{
side *= SideMove1;
}
else
{
side *= SideMove2;
}
if (!player.morphTics && Inv != NULL)
{
double factor = Inv.GetSpeedFactor ();
forward *= factor;
side *= factor;
}
return forward, side;
}
//----------------------------------------------------------------------------
//
// PROC P_MovePlayer
//
//----------------------------------------------------------------------------
virtual void MovePlayer ()
{
let player = self.player;
UserCmd cmd = player.cmd;
// [RH] 180-degree turn overrides all other yaws
if (player.turnticks)
{
player.turnticks--;
Angle += (180. / TURN180_TICKS);
}
else
{
Angle += cmd.yaw * (360./65536.);
}
player.onground = (pos.z <= floorz) || bOnMobj || bMBFBouncer || (player.cheats & CF_NOCLIP2);
// killough 10/98:
//
// We must apply thrust to the player and bobbing separately, to avoid
// anomalies. The thrust applied to bobbing is always the same strength on
// ice, because the player still "works just as hard" to move, while the
// thrust applied to the movement varies with 'movefactor'.
if (cmd.forwardmove | cmd.sidemove)
{
double forwardmove, sidemove;
double bobfactor;
double friction, movefactor;
double fm, sm;
[friction, movefactor] = GetFriction();
bobfactor = friction < ORIG_FRICTION ? movefactor : ORIG_FRICTION_FACTOR;
if (!player.onground && !bNoGravity && !waterlevel)
{
// [RH] allow very limited movement if not on ground.
movefactor *= level.aircontrol;
bobfactor*= level.aircontrol;
}
fm = cmd.forwardmove;
sm = cmd.sidemove;
[fm, sm] = TweakSpeeds (fm, sm);
fm *= Speed / 256;
sm *= Speed / 256;
// When crouching, speed and bobbing have to be reduced
if (CanCrouch() && player.crouchfactor != 1)
{
fm *= player.crouchfactor;
sm *= player.crouchfactor;
bobfactor *= player.crouchfactor;
}
forwardmove = fm * movefactor * (35 / TICRATE);
sidemove = sm * movefactor * (35 / TICRATE);
if (forwardmove)
{
Bob(Angle, cmd.forwardmove * bobfactor / 256., true);
ForwardThrust(forwardmove, Angle);
}
if (sidemove)
{
let a = Angle - 90;
Bob(a, cmd.sidemove * bobfactor / 256., false);
Thrust(sidemove, a);
}
if (!(player.cheats & CF_PREDICTING) && (forwardmove != 0 || sidemove != 0))
{
PlayRunning ();
}
if (player.cheats & CF_REVERTPLEASE)
{
player.cheats &= ~CF_REVERTPLEASE;
player.camera = player.mo;
}
}
}
//----------------------------------------------------------------------------
//
// PROC P_CheckPitch
//
//----------------------------------------------------------------------------
virtual void CheckPitch()
{
let player = self.player;
// [RH] Look up/down stuff
if (!level.IsFreelookAllowed())
{
Pitch = 0.;
}
else
{
// The player's view pitch is clamped between -32 and +56 degrees,
// which translates to about half a screen height up and (more than)
// one full screen height down from straight ahead when view panning
// is used.
int clook = player.cmd.pitch;
if (clook != 0)
{
if (clook == -32768)
{ // center view
player.centering = true;
}
else if (!player.centering)
{
// no more overflows with floating point. Yay! :)
Pitch = clamp(Pitch - clook * (360. / 65536.), player.MinPitch, player.MaxPitch);
}
}
}
if (player.centering)
{
if (abs(Pitch) > 2.)
{
Pitch *= (2. / 3.);
}
else
{
Pitch = 0.;
player.centering = false;
if (PlayerNumber() == consoleplayer)
{
LocalViewPitch = 0;
}
}
}
}
//----------------------------------------------------------------------------
//
// PROC P_CheckJump
//
//----------------------------------------------------------------------------
virtual void CheckJump()
{
let player = self.player;
// [RH] check for jump
if (player.cmd.buttons & BT_JUMP)
{
if (player.crouchoffset != 0)
{
// Jumping while crouching will force an un-crouch but not jump
player.crouching = 1;
}
else if (waterlevel >= 2)
{
Vel.Z = 4 * Speed;
}
else if (bNoGravity)
{
Vel.Z = 3.;
}
else if (level.IsJumpingAllowed() && player.onground && player.jumpTics == 0)
{
double jumpvelz = JumpZ * 35 / TICRATE;
double jumpfac = 0;
// [BC] If the player has the high jump power, double his jump velocity.
// (actually, pick the best factors from all active items.)
for (let p = Inv; p != null; p = p.Inv)
{
let pp = PowerHighJump(p);
if (pp)
{
double f = pp.Strength;
if (f > jumpfac) jumpfac = f;
}
}
if (jumpfac > 0) jumpvelz *= jumpfac;
Vel.Z += jumpvelz;
bOnMobj = false;
player.jumpTics = -1;
if (!(player.cheats & CF_PREDICTING)) A_PlaySound("*jump", CHAN_BODY);
}
}
}
//----------------------------------------------------------------------------
//
// PROC P_CheckMoveUpDown
//
//----------------------------------------------------------------------------
virtual void CheckMoveUpDown()
{
let player = self.player;
UserCmd cmd = player.cmd;
if (cmd.upmove == -32768)
{ // Only land if in the air
if (bNoGravity && waterlevel < 2)
{
bNoGravity = false;
}
}
else if (cmd.upmove != 0)
{
// Clamp the speed to some reasonable maximum.
cmd.upmove = clamp(cmd.upmove, -0x300, 0x300);
if (waterlevel >= 2 || bFly || (player.cheats & CF_NOCLIP2))
{
Vel.Z = Speed * cmd.upmove / 128.;
if (waterlevel < 2 && !bNoGravity)
{
bFly = true;
bNoGravity = true;
if ((Vel.Z <= -39) && !(player.cheats & CF_PREDICTING))
{ // Stop falling scream
A_StopSound(CHAN_VOICE);
}
}
}
else if (cmd.upmove > 0 && !(player.cheats & CF_PREDICTING))
{
let fly = FindInventory("ArtiFly");
if (fly != NULL)
{
UseInventory(fly);
}
}
}
}
//----------------------------------------------------------------------------
//
// PROC P_HandleMovement
//
//----------------------------------------------------------------------------
virtual void HandleMovement()
{
let player = self.player;
// [RH] Check for fast turn around
if (player.cmd.buttons & BT_TURN180 && !(player.oldbuttons & BT_TURN180))
{
player.turnticks = TURN180_TICKS;
}
// Handle movement
if (reactiontime)
{ // Player is frozen
reactiontime--;
}
else
{
MovePlayer();
CheckJump();
CheckMoveUpDown();
}
}
//----------------------------------------------------------------------------
//
// PROC P_CheckUndoMorph
//
//----------------------------------------------------------------------------
virtual void CheckUndoMorph()
{
let player = self.player;
// Morph counter
if (player.morphTics)
{
if (player.chickenPeck)
{ // Chicken attack counter
player.chickenPeck -= 3;
}
if (!--player.morphTics)
{ // Attempt to undo the chicken/pig
player.UndoPlayerMorph(player, MRF_UNDOBYTIMEOUT);
}
}
}
//----------------------------------------------------------------------------
//
// PROC P_CheckPoison
//
//----------------------------------------------------------------------------
virtual void CheckPoison()
{
let player = self.player;
if (player.poisoncount && !(level.time & 15))
{
player.poisoncount -= 5;
if (player.poisoncount < 0)
{
player.poisoncount = 0;
}
player.PoisonDamage(player.poisoner, 1, true);
}
}
//----------------------------------------------------------------------------
//
// PROC P_CheckDegeneration
//
//----------------------------------------------------------------------------
virtual void CheckDegeneration()
{
// Apply degeneration.
if (sv_degeneration)
{
let player = self.player;
int maxhealth = GetMaxHealth(true);
if ((level.time % TICRATE) == 0 && player.health > maxhealth)
{
if (player.health - 5 < maxhealth)
player.health = maxhealth;
else
player.health--;
health = player.health;
}
}
}
//----------------------------------------------------------------------------
//
// PROC P_CheckAirSupply
//
//----------------------------------------------------------------------------
virtual void CheckAirSupply()
{
// Handle air supply
//if (level.airsupply > 0)
{
let player = self.player;
if (waterlevel < 3 || (bInvulnerable) || (player.cheats & (CF_GODMODE | CF_NOCLIP2)) || (player.cheats & CF_GODMODE2))
{
ResetAirSupply();
}
else if (player.air_finished <= level.time && !(level.time & 31))
{
DamageMobj(NULL, NULL, 2 + ((level.time - player.air_finished) / TICRATE), 'Drowning');
}
}
}
//----------------------------------------------------------------------------
//
// PROC P_PlayerThink
//
//----------------------------------------------------------------------------
native void CheckMusicChange();
native void DeathThink ();
native void CheckPitch();
native void HandleMovement();
native void CalcHeight ();
native void CheckEnvironment();
native void CheckUse();
native void CheckUndoMorph();
// Cycle psprites
native void CheckPoison();
native void CheckDegeneration();
native void CheckAirSupply();
virtual void PlayerThink()
{
let player = self.player;
@ -519,6 +1051,10 @@ class PlayerPawn : Actor native
native bool ResetAirSupply (bool playgasp = false);
native void CheckWeaponSwitch(class<Inventory> item);
native clearscope static String GetPrintableDisplayName(Class<Actor> cls);
native void CheckMusicChange();
native void CalcHeight ();
native void CheckEnvironment();
native void CheckUse();
}
@ -597,7 +1133,7 @@ struct PlayerInfo native play // this is what internally is known as player_t
native uint8 playerstate;
native readonly uint buttons;
native uint original_oldbuttons;
native readonly Class<PlayerPawn> cls;
native Class<PlayerPawn> cls;
native float DesiredFOV;
native float FOV;
native double viewz;