From 8c992647de71e03240dad0a6b2598dae3e81f1ec Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sun, 30 Apr 2017 16:09:40 -0400 Subject: [PATCH 1/8] - fixed: "vid_renderer" should NEVER be referenced outside of the hardware code. This may fix a crash when changing modes with vid_renderer not matching actual renderer --- src/g_shared/a_dynlight.cpp | 4 ++-- src/p_3dfloors.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/g_shared/a_dynlight.cpp b/src/g_shared/a_dynlight.cpp index 4aaa75fa51..90e81d281f 100644 --- a/src/g_shared/a_dynlight.cpp +++ b/src/g_shared/a_dynlight.cpp @@ -76,7 +76,7 @@ #include "gl/system//gl_interface.h" #include "vm.h" -EXTERN_CVAR(Int, vid_renderer) +extern int currentrenderer; CUSTOM_CVAR (Bool, gl_lights, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) @@ -164,7 +164,7 @@ void ADynamicLight::BeginPlay() specialf1 = DAngle(double(SpawnAngle)).Normalized360().Degrees; visibletoplayer = true; - if (vid_renderer == 1 && gl.legacyMode && (flags4 & MF4_ATTENUATE)) + if (currentrenderer == 1 && gl.legacyMode && (flags4 & MF4_ATTENUATE)) { args[LIGHT_INTENSITY] = args[LIGHT_INTENSITY] * 2 / 3; args[LIGHT_SECONDARY_INTENSITY] = args[LIGHT_SECONDARY_INTENSITY] * 2 / 3; diff --git a/src/p_3dfloors.cpp b/src/p_3dfloors.cpp index 509efa8220..66ab0d7c89 100644 --- a/src/p_3dfloors.cpp +++ b/src/p_3dfloors.cpp @@ -50,7 +50,7 @@ #include "g_levellocals.h" #include "actorinlines.h" -EXTERN_CVAR(Int, vid_renderer) +extern int currentrenderer; //========================================================================== // @@ -197,7 +197,7 @@ static void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flag // kg3D - software renderer only hack // this is really required because of ceilingclip and floorclip - if((vid_renderer == 0) && (flags & FF_BOTHPLANES)) + if((currentrenderer == 0) && (flags & FF_BOTHPLANES)) { P_Add3DFloor(sec, sec2, master, FF_EXISTS | FF_THISINSIDE | FF_RENDERPLANES | FF_NOSHADE | FF_SEETHROUGH | FF_SHOOTTHROUGH | (flags & (FF_INVERTSECTOR | FF_TRANSLUCENT | FF_ADDITIVETRANS)), alpha); From 10deb5ce5657e0fccda2444f942cfe5e193fd65b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 30 Apr 2017 20:29:39 +0200 Subject: [PATCH 2/8] - exported P_PlayerThink to ZScript. --- src/p_pspr.cpp | 6 + src/p_user.cpp | 173 +++++++++++------- wadsrc/static/zscript/shared/player.txt | 147 ++++++++++++++- .../static/zscript/statscreen/statscreen.txt | 4 +- 4 files changed, 254 insertions(+), 76 deletions(-) diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 72920f8944..f2c4b95902 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -1508,6 +1508,12 @@ void player_t::TickPSprites() } } +DEFINE_ACTION_FUNCTION(_PlayerInfo, TickPSprites) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_t); + self->TickPSprites(); + return 0; +} //------------------------------------------------------------------------ // // diff --git a/src/p_user.cpp b/src/p_user.cpp index 9494ae3c36..5e3958bafc 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -3068,6 +3068,98 @@ void P_HandleMovement(player_t *player) } } + +DEFINE_ACTION_FUNCTION(APlayerPawn, CheckFOV) +{ + PARAM_SELF_PROLOGUE(APlayerPawn); + P_CheckFOV(self->player); + return 0; +} +DEFINE_ACTION_FUNCTION(APlayerPawn, CheckCheats) +{ + PARAM_SELF_PROLOGUE(APlayerPawn); + P_CheckCheats(self->player); + return 0; +} +DEFINE_ACTION_FUNCTION(APlayerPawn, CheckFrozen) +{ + PARAM_SELF_PROLOGUE(APlayerPawn); + ACTION_RETURN_BOOL(P_CheckFrozen(self->player)); +} +DEFINE_ACTION_FUNCTION(APlayerPawn, CheckCrouch) +{ + PARAM_SELF_PROLOGUE(APlayerPawn); + PARAM_BOOL(totally); + P_CheckCrouch(self->player, totally); + return 0; +} +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; +} + //---------------------------------------------------------------------------- // // PROC P_PlayerThink @@ -3098,75 +3190,10 @@ void P_PlayerThink (player_t *player) // Don't interpolate the view for more than one tic player->cheats &= ~CF_INTERPVIEW; - P_CheckFOV(player); - - if (player->inventorytics) + IFVIRTUALPTR(player->mo, APlayerPawn, PlayerThink) { - player->inventorytics--; - } - P_CheckCheats(player); - - if (player->mo->flags & MF_JUSTATTACKED) - { // Chainsaw/Gauntlets attack auto forward motion - cmd->ucmd.yaw = 0; - cmd->ucmd.forwardmove = 0xc800/2; - cmd->ucmd.sidemove = 0; - player->mo->flags &= ~MF_JUSTATTACKED; - } - - bool totallyfrozen = P_CheckFrozen(player); - - // Handle crouching - P_CheckCrouch(player, totallyfrozen); - P_CheckMusicChange(player); - - if (player->playerstate == PST_DEAD) - { - P_DeathThink (player); - return; - } - if (player->jumpTics != 0) - { - player->jumpTics--; - if (player->onground && player->jumpTics < -18) - { - player->jumpTics = 0; - } - } - if (player->morphTics && !(player->cheats & CF_PREDICTING)) - { - player->mo->MorphPlayerThink (); - } - - P_CheckPitch(player); - P_HandleMovement(player); - P_CalcHeight (player); - - if (!(player->cheats & CF_PREDICTING)) - { - P_CheckEnvironment(player); - P_CheckUse(player); - P_CheckUndoMorph(player); - // Cycle psprites - player->TickPSprites(); - - // Other Counters - if (player->damagecount) - player->damagecount--; - - if (player->bonuscount) - player->bonuscount--; - - if (player->hazardcount) - { - player->hazardcount--; - if (!(level.time % player->hazardinterval) && player->hazardcount > 16*TICRATE) - P_DamageMobj (player->mo, NULL, NULL, 5, player->hazardtype); - } - - P_CheckPoison(player); - P_CheckDegeneration(player); - P_CheckAirSupply(player); + VMValue param = player->mo; + VMCall(func, ¶m, 1, nullptr, 0); } } @@ -3727,12 +3754,20 @@ DEFINE_FIELD_X(PlayerInfo, player_t, ConversationNPC) DEFINE_FIELD_X(PlayerInfo, player_t, ConversationPC) DEFINE_FIELD_X(PlayerInfo, player_t, ConversationNPCAngle) DEFINE_FIELD_X(PlayerInfo, player_t, ConversationFaceTalker) -DEFINE_FIELD_X(PlayerInfo, player_t, cmd) +DEFINE_FIELD_NAMED_X(PlayerInfo, player_t, cmd.ucmd, cmd) DEFINE_FIELD_X(PlayerInfo, player_t, original_cmd) DEFINE_FIELD_X(PlayerInfo, player_t, userinfo) DEFINE_FIELD_X(PlayerInfo, player_t, weapons) DEFINE_FIELD_NAMED_X(PlayerInfo, player_t, cmd.ucmd.buttons, buttons) +DEFINE_FIELD_X(UserCmd, usercmd_t, buttons) +DEFINE_FIELD_X(UserCmd, usercmd_t, pitch) +DEFINE_FIELD_X(UserCmd, usercmd_t, yaw) +DEFINE_FIELD_X(UserCmd, usercmd_t, roll) +DEFINE_FIELD_X(UserCmd, usercmd_t, forwardmove) +DEFINE_FIELD_X(UserCmd, usercmd_t, sidemove) +DEFINE_FIELD_X(UserCmd, usercmd_t, upmove) + DEFINE_FIELD(FPlayerClass, Type) DEFINE_FIELD(FPlayerClass, Flags) DEFINE_FIELD(FPlayerClass, Skins) diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 43c01044f5..31aa40ad05 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -1,3 +1,15 @@ + +struct UserCmd native +{ + native uint buttons; + native int16 pitch; // up/down + native int16 yaw; // left/right + native int16 roll; // "tilt" + native int16 forwardmove; + native int16 sidemove; + native int16 upmove; +} + class PlayerPawn : Actor native { @@ -94,6 +106,12 @@ class PlayerPawn : Actor native Obituary "$OB_MPDEFAULT"; } + //---------------------------------------------------------------------------- + // + // + // + //---------------------------------------------------------------------------- + virtual void PlayIdle () { if (InStateSequence(CurState, SeeState)) @@ -120,6 +138,12 @@ class PlayerPawn : Actor native { } + //---------------------------------------------------------------------------- + // + // + // + //---------------------------------------------------------------------------- + virtual void OnRespawn() { if (sv_respawnprotect && (multiplayer || alwaysapplydmflags)) @@ -132,6 +156,12 @@ class PlayerPawn : Actor native } } + //---------------------------------------------------------------------------- + // + // + // + //---------------------------------------------------------------------------- + override String GetObituary(Actor victim, Actor inflictor, Name mod, bool playerattack) { if (victim.player != player && victim.IsTeammate(self)) @@ -162,7 +192,12 @@ class PlayerPawn : Actor native } } + //---------------------------------------------------------------------------- + // // This is for SBARINFO. + // + //---------------------------------------------------------------------------- + clearscope int, int GetEffectTicsForItem(class item) const { let pg = (class)(item); @@ -180,6 +215,110 @@ class PlayerPawn : Actor native return -1, -1; } + //---------------------------------------------------------------------------- + // + // PROC P_PlayerThink + // + //---------------------------------------------------------------------------- + + native void CheckFOV(); + native void CheckCheats(); + native bool CheckFrozen(); + native void CheckCrouch(bool totallyfrozen); + 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; + UserCmd cmd = player.cmd; + + CheckFOV(); + + if (player.inventorytics) + { + player.inventorytics--; + } + CheckCheats(); + + if (bJustAttacked) + { // Chainsaw/Gauntlets attack auto forward motion + cmd.yaw = 0; + cmd.forwardmove = 0xc800/2; + cmd.sidemove = 0; + bJustAttacked = false; + } + + bool totallyfrozen = CheckFrozen(); + + // Handle crouching + CheckCrouch(totallyfrozen); + CheckMusicChange(); + + if (player.playerstate == PST_DEAD) + { + DeathThink (); + return; + } + if (player.jumpTics != 0) + { + player.jumpTics--; + if (player.onground && player.jumpTics < -18) + { + player.jumpTics = 0; + } + } + if (player.morphTics && !(player.cheats & CF_PREDICTING)) + { + MorphPlayerThink (); + } + + CheckPitch(); + HandleMovement(); + CalcHeight (); + + if (!(player.cheats & CF_PREDICTING)) + { + CheckEnvironment(); + CheckUse(); + CheckUndoMorph(); + // Cycle psprites + player.TickPSprites(); + + // Other Counters + if (player.damagecount) player.damagecount--; + if (player.bonuscount) player.bonuscount--; + + if (player.hazardcount) + { + player.hazardcount--; + if (!(level.time % player.hazardinterval) && player.hazardcount > 16*TICRATE) + DamageMobj (NULL, NULL, 5, player.hazardtype); + } + + CheckPoison(); + CheckDegeneration(); + CheckAirSupply(); + } + } + + //---------------------------------------------------------------------------- + // + // + // + //---------------------------------------------------------------------------- + native clearscope int GetMaxHealth(bool withupgrades = false) const; native bool ResetAirSupply (bool playgasp = false); native void CheckWeaponSwitch(class item); @@ -341,12 +480,9 @@ struct PlayerInfo native play // this is what internally is known as player_t native double ConversationNPCAngle; native bool ConversationFaceTalker; native @WeaponSlots weapons; + native @UserCmd cmd; + native readonly @UserCmd original_cmd; -/* these are not doable yet -ticcmd_t cmd; -usercmd_t original_cmd; -*/ - native bool MorphPlayer(playerinfo p, Class spawntype, int duration, int style, Class enter_flash = null, Class exit_flash = null); native bool UndoPlayerMorph(playerinfo player, int unmorphflag = 0, bool force = false); @@ -375,6 +511,7 @@ usercmd_t original_cmd; native bool GetNoAutostartMap() const; native void SetFOV(float fov); native clearscope bool HasWeaponsInSlot(int slot) const; + native void TickPSprites(); clearscope int fragSum () const { diff --git a/wadsrc/static/zscript/statscreen/statscreen.txt b/wadsrc/static/zscript/statscreen/statscreen.txt index de6e3d28c4..553432d9ca 100644 --- a/wadsrc/static/zscript/statscreen/statscreen.txt +++ b/wadsrc/static/zscript/statscreen/statscreen.txt @@ -592,8 +592,8 @@ class StatusScreen abstract play version("2.5") PlayerInfo player = players[i]; if (playeringame[i]) { - if ((player.buttons ^ player.oldbuttons) && - ((player.buttons & player.oldbuttons) == player.oldbuttons) && player.Bot == NULL) + if ((player.cmd.buttons ^ player.oldbuttons) && + ((player.cmd.buttons & player.oldbuttons) == player.oldbuttons) && player.Bot == NULL) { acceleratestage = 1; playerready[i] = true; From 6e25c34fdafb7e4d7a27817ec9ac2e6d7ef5e6b5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 30 Apr 2017 22:16:32 +0200 Subject: [PATCH 3/8] - more player code exported --- src/d_player.h | 2 - src/g_level.cpp | 6 + src/p_mobj.cpp | 8 + src/p_user.cpp | 218 ----------------------- wadsrc/static/zscript/actor.txt | 1 + wadsrc/static/zscript/base.txt | 1 + wadsrc/static/zscript/shared/player.txt | 226 +++++++++++++++++++++++- 7 files changed, 238 insertions(+), 224 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index edc611a69e..7c20b85dd0 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -567,8 +567,6 @@ inline bool AActor::IsNoClip2() const return false; } -#define CROUCHSPEED (1./12) - bool P_IsPlayerTotallyFrozen(const player_t *player); #endif // __D_PLAYER_H__ diff --git a/src/g_level.cpp b/src/g_level.cpp index d9d28b72f1..7d1cf41698 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1464,6 +1464,12 @@ bool FLevelLocals::IsCrouchingAllowed() const return !(flags & LEVEL_CROUCH_NO); } +DEFINE_ACTION_FUNCTION(FLevelLocals, IsCrouchingAllowed) +{ + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + ACTION_RETURN_BOOL(self->IsCrouchingAllowed()); +} + //========================================================================== // // diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 12130c2b1c..3c423bbf2e 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3270,6 +3270,14 @@ void P_CheckFakeFloorTriggers (AActor *mo, double oldz, bool oldz_has_viewheight } } +DEFINE_ACTION_FUNCTION(AActor, CheckFakeFloorTriggers) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(oldz); + PARAM_BOOL_DEF(oldz_has_viewh); + P_CheckFakeFloorTriggers(self, oldz, oldz_has_viewh); + return 0; +} //=========================================================================== // // PlayerLandedOnThing diff --git a/src/p_user.cpp b/src/p_user.cpp index 5e3958bafc..ff22ae7ea1 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -2520,200 +2520,6 @@ void P_DeathThink (player_t *player) } } -//---------------------------------------------------------------------------- -// -// PROC P_CrouchMove -// -//---------------------------------------------------------------------------- - -void P_CrouchMove(player_t * player, int direction) -{ - double defaultheight = player->mo->FullHeight; - double savedheight = player->mo->Height; - double crouchspeed = direction * CROUCHSPEED; - double oldheight = player->viewheight; - - player->crouchdir = (signed char) direction; - player->crouchfactor += crouchspeed; - - // check whether the move is ok - player->mo->Height = defaultheight * player->crouchfactor; - if (!P_TryMove(player->mo, player->mo->Pos(), false, NULL)) - { - player->mo->Height = savedheight; - if (direction > 0) - { - // doesn't fit - player->crouchfactor -= crouchspeed; - return; - } - } - player->mo->Height = savedheight; - - player->crouchfactor = clamp(player->crouchfactor, 0.5, 1.); - player->viewheight = player->mo->ViewHeight * player->crouchfactor; - player->crouchviewdelta = player->viewheight - player->mo->ViewHeight; - - // Check for eyes going above/below fake floor due to crouching motion. - P_CheckFakeFloorTriggers(player->mo, player->mo->Z() + oldheight, true); -} - -//---------------------------------------------------------------------------- -// -// PROC P_CheckFOV -// -//---------------------------------------------------------------------------- - -void P_CheckFOV(player_t *player) -{ - // [RH] Zoom the player's FOV - float desired = player->DesiredFOV; - // Adjust FOV using on the currently held weapon. - if (player->playerstate != PST_DEAD && // No adjustment while dead. - player->ReadyWeapon != NULL && // No adjustment if no weapon. - player->ReadyWeapon->FOVScale != 0) // No adjustment if the adjustment is zero. - { - // A negative scale is used to prevent G_AddViewAngle/G_AddViewPitch - // from scaling with the FOV scale. - desired *= fabsf(player->ReadyWeapon->FOVScale); - } - if (player->FOV != desired) - { - if (fabsf(player->FOV - desired) < 7.f) - { - player->FOV = desired; - } - else - { - float zoom = MAX(7.f, fabsf(player->FOV - desired) * 0.025f); - if (player->FOV > desired) - { - player->FOV = player->FOV - zoom; - } - else - { - player->FOV = player->FOV + zoom; - } - } - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_CheckCheats -// -//---------------------------------------------------------------------------- - -void P_CheckCheats(player_t *player) -{ - // No-clip cheat - if ((player->cheats & (CF_NOCLIP | CF_NOCLIP2)) == CF_NOCLIP2) - { // No noclip2 without noclip - player->cheats &= ~CF_NOCLIP2; - } - if (player->cheats & (CF_NOCLIP | CF_NOCLIP2) || (player->mo->GetDefault()->flags & MF_NOCLIP)) - { - player->mo->flags |= MF_NOCLIP; - } - else - { - player->mo->flags &= ~MF_NOCLIP; - } - if (player->cheats & CF_NOCLIP2) - { - player->mo->flags |= MF_NOGRAVITY; - } - else if (!(player->mo->flags2 & MF2_FLY) && !(player->mo->GetDefault()->flags & MF_NOGRAVITY)) - { - player->mo->flags &= ~MF_NOGRAVITY; - } -} - - -//---------------------------------------------------------------------------- -// -// PROC P_CheckFrozen -// -//---------------------------------------------------------------------------- - -bool P_CheckFrozen(player_t *player) -{ - auto cmd = &player->cmd; - bool totallyfrozen = P_IsPlayerTotallyFrozen(player); - - // [RH] Being totally frozen zeros out most input parameters. - if (totallyfrozen) - { - if (gamestate == GS_TITLELEVEL) - { - cmd->ucmd.buttons = 0; - } - else - { - cmd->ucmd.buttons &= BT_USE; - } - cmd->ucmd.pitch = 0; - cmd->ucmd.yaw = 0; - cmd->ucmd.roll = 0; - cmd->ucmd.forwardmove = 0; - cmd->ucmd.sidemove = 0; - cmd->ucmd.upmove = 0; - player->turnticks = 0; - } - else if (player->cheats & CF_FROZEN) - { - cmd->ucmd.forwardmove = 0; - cmd->ucmd.sidemove = 0; - cmd->ucmd.upmove = 0; - } - return totallyfrozen; -} - -//---------------------------------------------------------------------------- -// -// PROC P_CheckCrouch -// -//---------------------------------------------------------------------------- - -void P_CheckCrouch(player_t *player, bool totallyfrozen) -{ - if (player->cmd.ucmd.buttons & BT_JUMP) - { - player->cmd.ucmd.buttons &= ~BT_CROUCH; - } - if (player->CanCrouch() && player->health > 0 && level.IsCrouchingAllowed()) - { - if (!totallyfrozen) - { - int crouchdir = player->crouching; - - if (crouchdir == 0) - { - crouchdir = (player->cmd.ucmd.buttons & BT_CROUCH) ? -1 : 1; - } - else if (player->cmd.ucmd.buttons & BT_CROUCH) - { - player->crouching = 0; - } - if (crouchdir == 1 && player->crouchfactor < 1 && - player->mo->Top() < player->mo->ceilingz) - { - P_CrouchMove(player, 1); - } - else if (crouchdir == -1 && player->crouchfactor > 0.5) - { - P_CrouchMove(player, -1); - } - } - } - else - { - player->Uncrouch(); - } - - player->crouchoffset = -(player->mo->ViewHeight) * (1 - player->crouchfactor); -} - //---------------------------------------------------------------------------- // // PROC P_CheckMusicChange @@ -3069,30 +2875,6 @@ void P_HandleMovement(player_t *player) } -DEFINE_ACTION_FUNCTION(APlayerPawn, CheckFOV) -{ - PARAM_SELF_PROLOGUE(APlayerPawn); - P_CheckFOV(self->player); - return 0; -} -DEFINE_ACTION_FUNCTION(APlayerPawn, CheckCheats) -{ - PARAM_SELF_PROLOGUE(APlayerPawn); - P_CheckCheats(self->player); - return 0; -} -DEFINE_ACTION_FUNCTION(APlayerPawn, CheckFrozen) -{ - PARAM_SELF_PROLOGUE(APlayerPawn); - ACTION_RETURN_BOOL(P_CheckFrozen(self->player)); -} -DEFINE_ACTION_FUNCTION(APlayerPawn, CheckCrouch) -{ - PARAM_SELF_PROLOGUE(APlayerPawn); - PARAM_BOOL(totally); - P_CheckCrouch(self->player, totally); - return 0; -} DEFINE_ACTION_FUNCTION(APlayerPawn, CheckMusicChange) { PARAM_SELF_PROLOGUE(APlayerPawn); diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 9b7836d171..961168922d 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -540,6 +540,7 @@ class Actor : Thinker native native void SetXYZ(vector3 newpos); native Actor GetPointer(int aaptr); native double BulletSlope(out FTranslatedLineTarget pLineTarget = null, int aimflags = 0); + native void CheckFakeFloorTriggers (double oldz, bool oldz_has_viewheight = false); native bool CheckMissileSpawn(double maxdist); native bool CheckPosition(Vector2 pos, bool actorsonly = false, FCheckPosition tm = null); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 7b920f524c..ec72249099 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -530,6 +530,7 @@ struct LevelLocals native native static void RemoveAllBots(bool fromlist); native void SetInterMusic(String nextmap); native String FormatMapName(int mapnamecolor); + native bool IsCrouchingAllowed() const; String TimeFormatted(bool totals = false) { diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 31aa40ad05..1ab9cd06ed 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -12,6 +12,7 @@ struct UserCmd native class PlayerPawn : Actor native { + const CROUCHSPEED = (1./12); native int crouchsprite; native int MaxHealth; @@ -215,16 +216,211 @@ class PlayerPawn : Actor native return -1, -1; } + //---------------------------------------------------------------------------- + // + // PROC P_CheckFOV + // + //---------------------------------------------------------------------------- + + virtual void CheckFOV() + { + let player = self.player; + + // [RH] Zoom the player's FOV + float desired = player.DesiredFOV; + // Adjust FOV using on the currently held weapon. + if (player.playerstate != PST_DEAD && // No adjustment while dead. + player.ReadyWeapon != NULL && // No adjustment if no weapon. + player.ReadyWeapon.FOVScale != 0) // No adjustment if the adjustment is zero. + { + // A negative scale is used to prevent G_AddViewAngle/G_AddViewPitch + // from scaling with the FOV scale. + desired *= abs(player.ReadyWeapon.FOVScale); + } + if (player.FOV != desired) + { + if (abs(player.FOV - desired) < 7.) + { + player.FOV = desired; + } + else + { + float zoom = MAX(7., abs(player.FOV - desired) * 0.025); + if (player.FOV > desired) + { + player.FOV = player.FOV - zoom; + } + else + { + player.FOV = player.FOV + zoom; + } + } + } + } + + //---------------------------------------------------------------------------- + // + // PROC P_CheckCheats + // + //---------------------------------------------------------------------------- + + virtual void CheckCheats() + { + let player = self.player; + // No-clip cheat + if ((player.cheats & (CF_NOCLIP | CF_NOCLIP2)) == CF_NOCLIP2) + { // No noclip2 without noclip + player.cheats &= ~CF_NOCLIP2; + } + bNoClip = (player.cheats & (CF_NOCLIP | CF_NOCLIP2) || Default.bNoClip); + if (player.cheats & CF_NOCLIP2) + { + bNoGravity = true; + } + else if (!bFly && !Default.bNoGravity) + { + bNoGravity = false; + } + } + + //---------------------------------------------------------------------------- + // + // PROC P_CheckFrozen + // + //---------------------------------------------------------------------------- + + virtual bool CheckFrozen() + { + let player = self.player; + UserCmd cmd = player.cmd; + bool totallyfrozen = player.IsTotallyFrozen(); + + // [RH] Being totally frozen zeros out most input parameters. + if (totallyfrozen) + { + if (gamestate == GS_TITLELEVEL) + { + cmd.buttons = 0; + } + else + { + cmd.buttons &= BT_USE; + } + cmd.pitch = 0; + cmd.yaw = 0; + cmd.roll = 0; + cmd.forwardmove = 0; + cmd.sidemove = 0; + cmd.upmove = 0; + player.turnticks = 0; + } + else if (player.cheats & CF_FROZEN) + { + cmd.forwardmove = 0; + cmd.sidemove = 0; + cmd.upmove = 0; + } + return totallyfrozen; + } + + virtual bool CanCrouch() const + { + return player.morphTics == 0 || bCrouchableMorph; + } + + //---------------------------------------------------------------------------- + // + // PROC P_CrouchMove + // + //---------------------------------------------------------------------------- + + virtual void CrouchMove(int direction) + { + let player = self.player; + + double defaultheight = FullHeight; + double savedheight = Height; + double crouchspeed = direction * CROUCHSPEED; + double oldheight = player.viewheight; + + player.crouchdir = direction; + player.crouchfactor += crouchspeed; + + // check whether the move is ok + Height = defaultheight * player.crouchfactor; + if (!TryMove(Pos.XY, false, NULL)) + { + Height = savedheight; + if (direction > 0) + { + // doesn't fit + player.crouchfactor -= crouchspeed; + return; + } + } + Height = savedheight; + + player.crouchfactor = clamp(player.crouchfactor, 0.5, 1.); + player.viewheight = ViewHeight * player.crouchfactor; + player.crouchviewdelta = player.viewheight - ViewHeight; + + // Check for eyes going above/below fake floor due to crouching motion. + CheckFakeFloorTriggers(pos.Z + oldheight, true); + } + + //---------------------------------------------------------------------------- + // + // PROC P_CheckCrouch + // + //---------------------------------------------------------------------------- + + virtual void CheckCrouch(bool totallyfrozen) + { + let player = self.player; + UserCmd cmd = player.cmd; + + if (cmd.buttons & BT_JUMP) + { + cmd.buttons &= ~BT_CROUCH; + } + if (CanCrouch() && player.health > 0 && level.IsCrouchingAllowed()) + { + if (!totallyfrozen) + { + int crouchdir = player.crouching; + + if (crouchdir == 0) + { + crouchdir = (cmd.buttons & BT_CROUCH) ? -1 : 1; + } + else if (cmd.buttons & BT_CROUCH) + { + player.crouching = 0; + } + if (crouchdir == 1 && player.crouchfactor < 1 && pos.Z + height < ceilingz) + { + CrouchMove(1); + } + else if (crouchdir == -1 && player.crouchfactor > 0.5) + { + CrouchMove(-1); + } + } + } + else + { + player.Uncrouch(); + } + + player.crouchoffset = -(ViewHeight) * (1 - player.crouchfactor); + } + //---------------------------------------------------------------------------- // // PROC P_PlayerThink // //---------------------------------------------------------------------------- - native void CheckFOV(); - native void CheckCheats(); - native bool CheckFrozen(); - native void CheckCrouch(bool totallyfrozen); native void CheckMusicChange(); native void DeathThink (); native void CheckPitch(); @@ -512,7 +708,29 @@ struct PlayerInfo native play // this is what internally is known as player_t native void SetFOV(float fov); native clearscope bool HasWeaponsInSlot(int slot) const; native void TickPSprites(); + + bool IsTotallyFrozen() + { + return + gamestate == GS_TITLELEVEL || + (cheats & CF_TOTALLYFROZEN) || + (level.frozen && timefreezer == 0); + } + + void Uncrouch() + { + if (crouchfactor != 1) + { + crouchfactor = 1; + crouchoffset = 0; + crouchdir = 0; + crouching = 0; + crouchviewdelta = 0; + viewheight = mo.ViewHeight; + } + } + clearscope int fragSum () const { int i; From dfa5a3cd071503e5cc125ba836a2a8822d50cdac Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sun, 30 Apr 2017 16:18:19 -0400 Subject: [PATCH 4/8] - Changed cocoa backend's s_currentRenderer to match PC version's 'currentrenderer' to address a possible Mac compilation issue. --- src/posix/cocoa/i_video.mm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/posix/cocoa/i_video.mm b/src/posix/cocoa/i_video.mm index 67f23fc5a4..cf77b250f9 100644 --- a/src/posix/cocoa/i_video.mm +++ b/src/posix/cocoa/i_video.mm @@ -157,14 +157,14 @@ CUSTOM_CVAR(Bool, vid_autoswitch, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_ Printf("You must restart " GAMENAME " to apply graphics switching mode\n"); } -static int s_currentRenderer; +int currentrenderer; CUSTOM_CVAR(Int, vid_renderer, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) { // 0: Software renderer // 1: OpenGL renderer - if (self != s_currentRenderer) + if (self != currentrenderer) { switch (self) { @@ -657,7 +657,7 @@ DFrameBuffer* CocoaVideo::CreateFrameBuffer(const int width, const int height, c DFrameBuffer* fb = NULL; - if (1 == s_currentRenderer) + if (1 == currentrenderer) { fb = new OpenGLFrameBuffer(NULL, width, height, 32, 60, fullscreen); } @@ -1360,13 +1360,13 @@ static void I_DeleteRenderer() void I_CreateRenderer() { - s_currentRenderer = vid_renderer; + currentrenderer = vid_renderer; if (NULL == Renderer) { extern FRenderer* gl_CreateInterface(); - Renderer = 1 == s_currentRenderer + Renderer = 1 == currentrenderer ? gl_CreateInterface() : new FSoftwareRenderer; atterm(I_DeleteRenderer); From 65399bf0753a791ca40ba98324dffaa4082e716a Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sun, 30 Apr 2017 16:35:16 -0400 Subject: [PATCH 5/8] - fixed: Added currentrenderer checks to SDL and COCOA implementations of 'swtruecolor' --- src/posix/cocoa/i_video.mm | 17 ++++++++++------- src/posix/sdl/hardware.cpp | 11 +++++++---- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/posix/cocoa/i_video.mm b/src/posix/cocoa/i_video.mm index cf77b250f9..ed833e883a 100644 --- a/src/posix/cocoa/i_video.mm +++ b/src/posix/cocoa/i_video.mm @@ -116,6 +116,8 @@ DFrameBuffer *CreateGLSWFrameBuffer(int width, int height, bool bgra, bool fullscreen); +int currentrenderer; + CUSTOM_CVAR(Bool, vid_glswfb, true, CVAR_NOINITCALL | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) { Printf("This won't take effect until " GAMENAME " is restarted.\n"); @@ -135,11 +137,14 @@ CUSTOM_CVAR(Bool, swtruecolor, TRUECOLOR_DEFAULT, CVAR_ARCHIVE | CVAR_GLOBALCONF { // Strictly speaking this doesn't require a mode switch, but it is the easiest // way to force a CreateFramebuffer call without a lot of refactoring. - extern int NewWidth, NewHeight, NewBits, DisplayBits; - NewWidth = screen->GetWidth(); - NewHeight = screen->GetHeight(); - NewBits = DisplayBits; - setmodeneeded = true; + if (currentrenderer == 0) + { + extern int NewWidth, NewHeight, NewBits, DisplayBits; + NewWidth = screen->GetWidth(); + NewHeight = screen->GetHeight(); + NewBits = DisplayBits; + setmodeneeded = true; + } } CUSTOM_CVAR(Bool, fullscreen, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) @@ -157,8 +162,6 @@ CUSTOM_CVAR(Bool, vid_autoswitch, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_ Printf("You must restart " GAMENAME " to apply graphics switching mode\n"); } -int currentrenderer; - CUSTOM_CVAR(Int, vid_renderer, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) { // 0: Software renderer diff --git a/src/posix/sdl/hardware.cpp b/src/posix/sdl/hardware.cpp index 580c5a1b06..20ff59325d 100644 --- a/src/posix/sdl/hardware.cpp +++ b/src/posix/sdl/hardware.cpp @@ -323,10 +323,13 @@ CUSTOM_CVAR(Bool, swtruecolor, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITC { // Strictly speaking this doesn't require a mode switch, but it is the easiest // way to force a CreateFramebuffer call without a lot of refactoring. - NewWidth = screen->GetWidth(); - NewHeight = screen->GetHeight(); - NewBits = DisplayBits; - setmodeneeded = true; + if (currentrenderer == 0) + { + NewWidth = screen->GetWidth(); + NewHeight = screen->GetHeight(); + NewBits = DisplayBits; + setmodeneeded = true; + } } CUSTOM_CVAR (Bool, fullscreen, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) From 6044c876ab8f43e9e43217d5a23e239f2cbb6767 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 30 Apr 2017 12:01:38 -0700 Subject: [PATCH 6/8] Update LASTRUNVERSION to handle the snd_hrtf change Also snd_hrtf now uses -1 for "auto" and 0 for "off", which makes more sense. --- src/gameconfigfile.cpp | 8 ++++++-- src/sound/i_sound.cpp | 2 +- src/sound/oalsound.cpp | 2 +- src/version.h | 2 +- wadsrc/static/menudef.txt | 8 ++++---- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/gameconfigfile.cpp b/src/gameconfigfile.cpp index ad9a87b208..cfbbe5fb79 100644 --- a/src/gameconfigfile.cpp +++ b/src/gameconfigfile.cpp @@ -378,9 +378,13 @@ void FGameConfigFile::DoGlobalSetup () if (var != NULL) var->ResetToDefault(); var = FindCVar("uiscale", NULL); if (var != NULL) var->ResetToDefault(); - } - + if (last < 215) + { + // Previously a true/false boolean. Now an on/off/auto tri-state with auto as the default. + FBaseCVar *var = FindCVar("snd_hrtf", NULL); + if (var != NULL) var->ResetToDefault(); + } } } } diff --git a/src/sound/i_sound.cpp b/src/sound/i_sound.cpp index f80ec68654..0540620334 100644 --- a/src/sound/i_sound.cpp +++ b/src/sound/i_sound.cpp @@ -66,7 +66,7 @@ EXTERN_CVAR (Float, snd_sfxvolume) CVAR (Int, snd_samplerate, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Int, snd_buffersize, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (String, snd_output, "default", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -CVAR (Int, snd_hrtf, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CVAR (Int, snd_hrtf, -1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) #if !defined(NO_OPENAL) #define DEF_BACKEND "openal" diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index b1235dfdd8..1354bb6793 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -756,7 +756,7 @@ OpenALSoundRenderer::OpenALSoundRenderer() if(ALC.SOFT_HRTF) { attribs.Push(ALC_HRTF_SOFT); - if(*snd_hrtf < 0) + if(*snd_hrtf == 0) attribs.Push(ALC_FALSE); else if(*snd_hrtf > 0) attribs.Push(ALC_TRUE); diff --git a/src/version.h b/src/version.h index f4b7555799..cc4c9ed36e 100644 --- a/src/version.h +++ b/src/version.h @@ -68,7 +68,7 @@ const char *GetVersionString(); // Version stored in the ini's [LastRun] section. // Bump it if you made some configuration change that you want to // be able to migrate in FGameConfigFile::DoGlobalSetup(). -#define LASTRUNVERSION "214" +#define LASTRUNVERSION "215" // Protocol version used in demos. // Bump it if you change existing DEM_ commands or add new ones. diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 12e54978a6..5bc698684e 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -309,10 +309,10 @@ OptionValue "OffOn" 1, "$OPTVAL_OFF" } -OptionValue OffAutoOn +OptionValue AutoOffOn { - -1, "$OPTVAL_OFF" - 0, "$OPTVAL_AUTO" + -1, "$OPTVAL_AUTO" + 0, "$OPTVAL_OFF" 1, "$OPTVAL_ON" } @@ -1636,7 +1636,7 @@ OptionMenu AdvSoundOptions { Title "$ADVSNDMNU_TITLE" Option "$ADVSNDMNU_SAMPLERATE", "snd_samplerate", "SampleRates" - Option "$ADVSNDMNU_HRTF", "snd_hrtf", "OffAutoOn" + Option "$ADVSNDMNU_HRTF", "snd_hrtf", "AutoOffOn" StaticText " " StaticText "$ADVSNDMNU_OPLSYNTHESIS", 1 Slider "$ADVSNDMNU_OPLNUMCHIPS", "opl_numchips", 1, 8, 1, 0 From abee2805cb31a129947f839099db78777e3026fc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 1 May 2017 00:25:21 +0200 Subject: [PATCH 7/8] - the last scriptified bits of P_PlayerThink. --- src/d_player.h | 3 - src/g_level.cpp | 15 + src/p_user.cpp | 668 +----------------------- src/r_utility.cpp | 1 + wadsrc/static/zscript/actor.txt | 2 + wadsrc/static/zscript/base.txt | 4 + wadsrc/static/zscript/shared/player.txt | 566 +++++++++++++++++++- 7 files changed, 591 insertions(+), 668 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 7c20b85dd0..011335a852 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -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 (); diff --git a/src/g_level.cpp b/src/g_level.cpp index 7d1cf41698..ec48fd939b 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -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) diff --git a/src/p_user.cpp b/src/p_user.cpp index ff22ae7ea1..e2d803afb4 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -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(forward, -0x1900, 0x1900); - side = clamp(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(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; -} //---------------------------------------------------------------------------- // diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 7a90a03ec5..9aa8b4cb02 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -154,6 +154,7 @@ FCanvasTextureInfo *FCanvasTextureInfo::List; DVector3a view; DAngle viewpitch; +DEFINE_GLOBAL(LocalViewPitch); // CODE -------------------------------------------------------------------- static void R_Shutdown (); diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 961168922d..2abd552c90 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -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. diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index ec72249099..d6f7f318ea 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -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) { diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 1ab9cd06ed..1caf03c8ea 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -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 item); native clearscope static String GetPrintableDisplayName(Class 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 cls; + native Class cls; native float DesiredFOV; native float FOV; native double viewz; From b84f7bcadad55a925d5a2226cc3d307b98f1d059 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 1 May 2017 01:55:35 +0200 Subject: [PATCH 8/8] - scriptified the weapon firing logic. --- src/d_player.h | 2 - src/g_inventory/a_weapons.cpp | 40 --- src/g_inventory/a_weapons.h | 2 - src/p_pspr.cpp | 275 +----------------- src/p_pspr.h | 1 - src/p_user.cpp | 47 +-- .../zscript/inventory/stateprovider.txt | 38 ++- wadsrc/static/zscript/shared/player.txt | 246 +++++++++++++++- 8 files changed, 289 insertions(+), 362 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 011335a852..7d8dbf380c 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -100,7 +100,6 @@ public: void ActivateMorphWeapon (); AWeapon *PickNewWeapon (PClassActor *ammotype); AWeapon *BestWeapon (PClassActor *ammotype); - void CheckWeaponSwitch(PClassActor *ammotype); void GiveDeathmatchInventory (); void FilterCoopRespawnInventory (APlayerPawn *oldplayer); @@ -109,7 +108,6 @@ public: // These are virtual on the script side only. void PlayIdle(); - void PlayAttacking (); void PlayAttacking2 (); const char *GetSoundClass () const; diff --git a/src/g_inventory/a_weapons.cpp b/src/g_inventory/a_weapons.cpp index 5086d7832c..440c67f9b7 100644 --- a/src/g_inventory/a_weapons.cpp +++ b/src/g_inventory/a_weapons.cpp @@ -446,46 +446,6 @@ FState *AWeapon::GetReadyState () return nullptr; } -//=========================================================================== -// -// AWeapon :: GetAtkState -// -//=========================================================================== - -FState *AWeapon::GetAtkState (bool hold) -{ - IFVIRTUAL(AWeapon, GetAtkState) - { - VMValue params[2] = { (DObject*)this, hold }; - VMReturn ret; - FState *retval; - ret.PointerAt((void**)&retval); - VMCall(func, params, 2, &ret, 1); - return retval; - } - return nullptr; -} - -//=========================================================================== -// -// AWeapon :: GetAtkState -// -//=========================================================================== - -FState *AWeapon::GetAltAtkState (bool hold) -{ - IFVIRTUAL(AWeapon, GetAltAtkState) - { - VMValue params[2] = { (DObject*)this, hold }; - VMReturn ret; - FState *retval; - ret.PointerAt((void**)&retval); - VMCall(func, params, 2, &ret, 1); - return retval; - } - return nullptr; -} - //=========================================================================== // // AWeapon :: GetStateForButtonName diff --git a/src/g_inventory/a_weapons.h b/src/g_inventory/a_weapons.h index 9841d1a5ad..9b397e402c 100644 --- a/src/g_inventory/a_weapons.h +++ b/src/g_inventory/a_weapons.h @@ -132,8 +132,6 @@ public: FState *GetUpState (); FState *GetDownState (); FState *GetReadyState (); - FState *GetAtkState (bool hold); - FState *GetAltAtkState (bool hold); FState *GetStateForButtonName (FName button); diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index f2c4b95902..bd2e4219c2 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -126,6 +126,7 @@ DEFINE_FIELD(DPSprite, Next) DEFINE_FIELD(DPSprite, Owner) DEFINE_FIELD(DPSprite, Sprite) DEFINE_FIELD(DPSprite, Frame) +DEFINE_FIELD(DPSprite, Flags) DEFINE_FIELD(DPSprite, ID) DEFINE_FIELD(DPSprite, processPending) DEFINE_FIELD(DPSprite, x) @@ -601,82 +602,6 @@ DEFINE_ACTION_FUNCTION(_PlayerInfo, BringUpWeapon) return 0; } -//--------------------------------------------------------------------------- -// -// PROC P_FireWeapon -// -//--------------------------------------------------------------------------- - -void P_FireWeapon (player_t *player, FState *state) -{ - AWeapon *weapon; - - // [SO] 9/2/02: People were able to do an awful lot of damage - // when they were observers... - if (player->Bot == nullptr && bot_observer) - { - return; - } - - weapon = player->ReadyWeapon; - if (weapon == nullptr || !weapon->CheckAmmo (AWeapon::PrimaryFire, true)) - { - return; - } - - player->WeaponState &= ~WF_WEAPONBOBBING; - player->mo->PlayAttacking (); - weapon->bAltFire = false; - if (state == nullptr) - { - state = weapon->GetAtkState(!!player->refire); - } - P_SetPsprite(player, PSP_WEAPON, state); - if (!(weapon->WeaponFlags & WIF_NOALERT)) - { - P_NoiseAlert (player->mo, player->mo, false); - } -} - -//--------------------------------------------------------------------------- -// -// PROC P_FireWeaponAlt -// -//--------------------------------------------------------------------------- - -void P_FireWeaponAlt (player_t *player, FState *state) -{ - AWeapon *weapon; - - // [SO] 9/2/02: People were able to do an awful lot of damage - // when they were observers... - if (player->Bot == nullptr && bot_observer) - { - return; - } - - weapon = player->ReadyWeapon; - if (weapon == nullptr || weapon->FindState(NAME_AltFire) == nullptr || !weapon->CheckAmmo (AWeapon::AltFire, true)) - { - return; - } - - player->WeaponState &= ~WF_WEAPONBOBBING; - player->mo->PlayAttacking (); - weapon->bAltFire = true; - - if (state == nullptr) - { - state = weapon->GetAltAtkState(!!player->refire); - } - - P_SetPsprite(player, PSP_WEAPON, state); - if (!(weapon->WeaponFlags & WIF_NOALERT)) - { - P_NoiseAlert (player->mo, player->mo, false); - } -} - //--------------------------------------------------------------------------- // // PROC P_DropWeapon @@ -935,78 +860,6 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_WeaponReady) return 0; } -//--------------------------------------------------------------------------- -// -// PROC P_CheckWeaponFire -// -// The player can fire the weapon. -// [RH] This was in A_WeaponReady before, but that only works well when the -// weapon's ready frames have a one tic delay. -// -//--------------------------------------------------------------------------- - -void P_CheckWeaponFire (player_t *player) -{ - AWeapon *weapon = player->ReadyWeapon; - - if (weapon == NULL) - return; - - // Check for fire. Some weapons do not auto fire. - if ((player->WeaponState & WF_WEAPONREADY) && (player->cmd.ucmd.buttons & BT_ATTACK)) - { - if (!player->attackdown || !(weapon->WeaponFlags & WIF_NOAUTOFIRE)) - { - player->attackdown = true; - P_FireWeapon (player, NULL); - return; - } - } - else if ((player->WeaponState & WF_WEAPONREADYALT) && (player->cmd.ucmd.buttons & BT_ALTATTACK)) - { - if (!player->attackdown || !(weapon->WeaponFlags & WIF_NOAUTOFIRE)) - { - player->attackdown = true; - P_FireWeaponAlt (player, NULL); - return; - } - } - else - { - player->attackdown = false; - } -} - -//--------------------------------------------------------------------------- -// -// PROC P_CheckWeaponSwitch -// -// The player can change to another weapon at this time. -// [GZ] This was cut from P_CheckWeaponFire. -// -//--------------------------------------------------------------------------- - -void P_CheckWeaponSwitch (player_t *player) -{ - if (player == NULL) - { - return; - } - if ((player->WeaponState & WF_DISABLESWITCH) || // Weapon changing has been disabled. - player->morphTics != 0) // Morphed classes cannot change weapons. - { // ...so throw away any pending weapon requests. - player->PendingWeapon = WP_NOCHANGE; - } - - // Put the weapon away if the player has a pending weapon or has died, and - // we're at a place in the state sequence where dropping the weapon is okay. - if ((player->PendingWeapon != WP_NOCHANGE || player->health <= 0) && - player->WeaponState & WF_WEAPONSWITCHOK) - { - P_DropWeapon(player); - } -} - //--------------------------------------------------------------------------- // // PROC P_CheckWeaponButtons @@ -1046,53 +899,13 @@ static void P_CheckWeaponButtons (player_t *player) } } -//--------------------------------------------------------------------------- -// -// PROC A_ReFire -// -// The player can re-fire the weapon without lowering it entirely. -// -//--------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AStateProvider, A_ReFire) +DEFINE_ACTION_FUNCTION(APlayerPawn, CheckWeaponButtons) { - PARAM_ACTION_PROLOGUE(AStateProvider); - PARAM_STATE_ACTION_DEF(state); - A_ReFire(self, state); + PARAM_SELF_PROLOGUE(APlayerPawn); + P_CheckWeaponButtons(self->player); return 0; } -void A_ReFire(AActor *self, FState *state) -{ - player_t *player = self->player; - bool pending; - - if (NULL == player) - { - return; - } - pending = player->PendingWeapon != WP_NOCHANGE && (player->WeaponState & WF_REFIRESWITCHOK); - if ((player->cmd.ucmd.buttons & BT_ATTACK) - && !player->ReadyWeapon->bAltFire && !pending && player->health > 0) - { - player->refire++; - P_FireWeapon (player, state); - } - else if ((player->cmd.ucmd.buttons & BT_ALTATTACK) - && player->ReadyWeapon->bAltFire && !pending && player->health > 0) - { - player->refire++; - P_FireWeaponAlt (player, state); - } - else - { - player->refire = 0; - player->ReadyWeapon->CheckAmmo (player->ReadyWeapon->bAltFire - ? AWeapon::AltFire : AWeapon::PrimaryFire, true); - } -} - - //--------------------------------------------------------------------------- // // PROC A_OverlayOffset @@ -1459,86 +1272,6 @@ void P_SetupPsprites(player_t *player, bool startweaponup) P_BringUpWeapon (player); } -//------------------------------------------------------------------------ -// -// PROC P_MovePsprites -// -// Called every tic by player thinking routine -// -//------------------------------------------------------------------------ - -void player_t::TickPSprites() -{ - DPSprite *pspr = psprites; - while (pspr) - { - // Destroy the psprite if it's from a weapon that isn't currently selected by the player - // or if it's from an inventory item that the player no longer owns. - if ((pspr->Caller == nullptr || - (pspr->Caller->IsKindOf(RUNTIME_CLASS(AInventory)) && barrier_cast(pspr->Caller)->Owner != pspr->Owner->mo) || - (pspr->Caller->IsKindOf(NAME_Weapon) && pspr->Caller != pspr->Owner->ReadyWeapon))) - { - pspr->Destroy(); - } - else - { - pspr->Tick(); - } - - pspr = pspr->Next; - } - - if ((health > 0) || (ReadyWeapon != nullptr && !(ReadyWeapon->WeaponFlags & WIF_NODEATHINPUT))) - { - if (ReadyWeapon == nullptr) - { - if (PendingWeapon != WP_NOCHANGE) - P_BringUpWeapon(this); - } - else - { - P_CheckWeaponSwitch(this); - if (WeaponState & (WF_WEAPONREADY | WF_WEAPONREADYALT)) - { - P_CheckWeaponFire(this); - } - // Check custom buttons - P_CheckWeaponButtons(this); - } - } -} - -DEFINE_ACTION_FUNCTION(_PlayerInfo, TickPSprites) -{ - PARAM_SELF_STRUCT_PROLOGUE(player_t); - self->TickPSprites(); - return 0; -} -//------------------------------------------------------------------------ -// -// -// -//------------------------------------------------------------------------ - -void DPSprite::Tick() -{ - if (processPending) - { - // drop tic count and possibly change state - if (Tics != -1) // a -1 tic count never changes - { - Tics--; - - // [BC] Apply double firing speed. - if ((Flags & PSPF_POWDOUBLE) && Tics && (Owner->mo->FindInventory (PClass::FindActor(NAME_PowerDoubleFiringSpeed), true))) - Tics--; - - if (!Tics) - SetState(State->GetNextState()); - } - } -} - //------------------------------------------------------------------------ // // diff --git a/src/p_pspr.h b/src/p_pspr.h index 615af3c3c9..5964ace208 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -103,7 +103,6 @@ private: DPSprite () {} void Serialize(FSerializer &arc); - void Tick(); public: // must be public to be able to generate the field export tables. Grrr... TObjPtr Caller; diff --git a/src/p_user.cpp b/src/p_user.cpp index e2d803afb4..7ca8258b27 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1217,6 +1217,12 @@ AWeapon *APlayerPawn::BestWeapon(PClassActor *ammotype) return bestMatch; } +DEFINE_ACTION_FUNCTION(APlayerPawn, BestWeapon) +{ + PARAM_SELF_PROLOGUE(APlayerPawn); + PARAM_CLASS(ammo, AActor); + ACTION_RETURN_POINTER(self->BestWeapon(ammo)); +} //=========================================================================== // // APlayerPawn :: PickNewWeapon @@ -1246,38 +1252,6 @@ AWeapon *APlayerPawn::PickNewWeapon(PClassActor *ammotype) return best; } - -//=========================================================================== -// -// APlayerPawn :: CheckWeaponSwitch -// -// Checks if weapons should be changed after picking up ammo -// -//=========================================================================== - -void APlayerPawn::CheckWeaponSwitch(PClassActor *ammotype) -{ - if (!player->userinfo.GetNeverSwitch() && - player->PendingWeapon == WP_NOCHANGE && - (player->ReadyWeapon == NULL || - (player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))) - { - AWeapon *best = BestWeapon (ammotype); - if (best != NULL && (player->ReadyWeapon == NULL || - best->SelectionOrder < player->ReadyWeapon->SelectionOrder)) - { - player->PendingWeapon = best; - } - } -} - -DEFINE_ACTION_FUNCTION(APlayerPawn, CheckWeaponSwitch) -{ - PARAM_SELF_PROLOGUE(APlayerPawn); - PARAM_POINTER(ammotype, PClassActor); - self->CheckWeaponSwitch(ammotype); - return 0; -} //=========================================================================== // // APlayerPawn :: GiveDeathmatchInventory @@ -1541,15 +1515,6 @@ void APlayerPawn::PlayIdle () } } -void APlayerPawn::PlayAttacking () -{ - IFVIRTUAL(APlayerPawn, PlayAttacking) - { - VMValue params[1] = { (DObject*)this }; - VMCall(func, params, 1, nullptr, 0); - } -} - void APlayerPawn::PlayAttacking2 () { IFVIRTUAL(APlayerPawn, PlayAttacking2) diff --git a/wadsrc/static/zscript/inventory/stateprovider.txt b/wadsrc/static/zscript/inventory/stateprovider.txt index 4d842dc809..abbc8db71c 100644 --- a/wadsrc/static/zscript/inventory/stateprovider.txt +++ b/wadsrc/static/zscript/inventory/stateprovider.txt @@ -8,7 +8,43 @@ class StateProvider : Inventory native action native void A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = 0, color color2 = 0, int flags = 0, double maxdiff = 0, class pufftype = "BulletPuff", double spread_xy = 0, double spread_z = 0, double range = 0, int duration = 0, double sparsity = 1.0, double driftspeed = 1.0, class spawnclass = "none", double spawnofs_z = 0, int spiraloffset = 270, int limit = 0); action native void A_WeaponReady(int flags = 0); - action native void A_ReFire(statelabel flash = null); + //--------------------------------------------------------------------------- + // + // PROC A_ReFire + // + // The player can re-fire the weapon without lowering it entirely. + // + //--------------------------------------------------------------------------- + + action void A_ReFire(statelabel flash = null) + { + let player = self.player; + bool pending; + + if (NULL == player) + { + return; + } + pending = player.PendingWeapon != WP_NOCHANGE && (player.WeaponState & WF_REFIRESWITCHOK); + if ((player.cmd.buttons & BT_ATTACK) + && !player.ReadyWeapon.bAltFire && !pending && player.health > 0) + { + player.refire++; + player.mo.FireWeapon(ResolveState(flash)); + } + else if ((player.cmd.buttons & BT_ALTATTACK) + && player.ReadyWeapon.bAltFire && !pending && player.health > 0) + { + player.refire++; + player.mo.FireWeaponAlt(ResolveState(flash)); + } + else + { + player.refire = 0; + player.ReadyWeapon.CheckAmmo (player.ReadyWeapon.bAltFire? Weapon.AltFire : Weapon.PrimaryFire, true); + } + } + action native state A_CheckForReload(int counter, statelabel label, bool dontincrement = false); action native void A_ResetReloadCounter(); diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 1caf03c8ea..380ffd2d87 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -218,6 +218,224 @@ class PlayerPawn : Actor native return -1, -1; } + + //=========================================================================== + // + // APlayerPawn :: CheckWeaponSwitch + // + // Checks if weapons should be changed after picking up ammo + // + //=========================================================================== + + void CheckWeaponSwitch(Class ammotype) + { + let player = self.player; + if (!player.GetNeverSwitch() && player.PendingWeapon == WP_NOCHANGE && + (player.ReadyWeapon == NULL || player.ReadyWeapon.bWimpy_Weapon)) + { + let best = BestWeapon (ammotype); + if (best != NULL && (player.ReadyWeapon == NULL || + best.SelectionOrder < player.ReadyWeapon.SelectionOrder)) + { + player.PendingWeapon = best; + } + } + } + + //--------------------------------------------------------------------------- + // + // PROC P_FireWeapon + // + //--------------------------------------------------------------------------- + + virtual void FireWeapon (State stat) + { + let player = self.player; + + // [SO] 9/2/02: People were able to do an awful lot of damage + // when they were observers... + if (player.Bot == null && bot_observer) + { + return; + } + + let weapn = player.ReadyWeapon; + if (weapn == null || !weapn.CheckAmmo (Weapon.PrimaryFire, true)) + { + return; + } + + player.WeaponState &= ~WF_WEAPONBOBBING; + PlayAttacking (); + weapn.bAltFire = false; + if (stat == null) + { + stat = weapn.GetAtkState(!!player.refire); + } + player.SetPsprite(PSP_WEAPON, stat); + if (!weapn.bNoAlert) + { + SoundAlert (self, false); + } + } + + //--------------------------------------------------------------------------- + // + // PROC P_FireWeaponAlt + // + //--------------------------------------------------------------------------- + + virtual void FireWeaponAlt (State stat) + { + // [SO] 9/2/02: People were able to do an awful lot of damage + // when they were observers... + if (player.Bot == null && bot_observer) + { + return; + } + + let weapn = player.ReadyWeapon; + if (weapn == null || weapn.FindState('AltFire') == null || !weapn.CheckAmmo (Weapon.AltFire, true)) + { + return; + } + + player.WeaponState &= ~WF_WEAPONBOBBING; + PlayAttacking (); + weapn.bAltFire = true; + + if (stat == null) + { + stat = weapn.GetAltAtkState(!!player.refire); + } + + player.SetPsprite(PSP_WEAPON, stat); + if (!weapn.bNoAlert) + { + SoundAlert (self, false); + } + } + + //--------------------------------------------------------------------------- + // + // PROC P_CheckWeaponFire + // + // The player can fire the weapon. + // [RH] This was in A_WeaponReady before, but that only works well when the + // weapon's ready frames have a one tic delay. + // + //--------------------------------------------------------------------------- + + void CheckWeaponFire () + { + let player = self.player; + let weapon = player.ReadyWeapon; + + if (weapon == NULL) + return; + + // Check for fire. Some weapons do not auto fire. + if ((player.WeaponState & WF_WEAPONREADY) && (player.cmd.buttons & BT_ATTACK)) + { + if (!player.attackdown || !weapon.bNoAutofire) + { + player.attackdown = true; + FireWeapon (NULL); + return; + } + } + else if ((player.WeaponState & WF_WEAPONREADYALT) && (player.cmd.buttons & BT_ALTATTACK)) + { + if (!player.attackdown || !weapon.bNoAutofire) + { + player.attackdown = true; + FireWeaponAlt (NULL); + return; + } + } + else + { + player.attackdown = false; + } + } + + //--------------------------------------------------------------------------- + // + // PROC P_CheckWeaponChange + // + // The player can change to another weapon at this time. + // [GZ] This was cut from P_CheckWeaponFire. + // + //--------------------------------------------------------------------------- + + virtual void CheckWeaponChange () + { + let player = self.player; + if ((player.WeaponState & WF_DISABLESWITCH) || // Weapon changing has been disabled. + player.morphTics != 0) // Morphed classes cannot change weapons. + { // ...so throw away any pending weapon requests. + player.PendingWeapon = WP_NOCHANGE; + } + + // Put the weapon away if the player has a pending weapon or has died, and + // we're at a place in the state sequence where dropping the weapon is okay. + if ((player.PendingWeapon != WP_NOCHANGE || player.health <= 0) && + player.WeaponState & WF_WEAPONSWITCHOK) + { + player.DropWeapon(); + } + } + + //------------------------------------------------------------------------ + // + // PROC P_MovePsprites + // + // Called every tic by player thinking routine + // + //------------------------------------------------------------------------ + + virtual void TickPSprites() + { + let player = self.player; + let pspr = player.psprites; + while (pspr) + { + // Destroy the psprite if it's from a weapon that isn't currently selected by the player + // or if it's from an inventory item that the player no longer owns. + if ((pspr.Caller == null || + (pspr.Caller is "Inventory" && Inventory(pspr.Caller).Owner != pspr.Owner.mo) || + (pspr.Caller is "Weapon" && pspr.Caller != pspr.Owner.ReadyWeapon))) + { + pspr.Destroy(); + } + else + { + pspr.Tick(); + } + + pspr = pspr.Next; + } + + if ((health > 0) || (player.ReadyWeapon != null && !player.ReadyWeapon.bNoDeathInput)) + { + if (player.ReadyWeapon == null) + { + if (player.PendingWeapon != WP_NOCHANGE) + player.BringUpWeapon(); + } + else + { + CheckWeaponChange(); + if (player.WeaponState & (WF_WEAPONREADY | WF_WEAPONREADYALT)) + { + CheckWeaponFire(); + } + // Check custom buttons + CheckWeaponButtons(); + } + } + } + //========================================================================== // // P_DeathThink @@ -231,7 +449,7 @@ class PlayerPawn : Actor native double delta; player.Uncrouch(); - player.TickPSprites(); + TickPSprites(); player.onground = (pos.Z <= floorz); if (self is "PlayerChunk") @@ -1022,7 +1240,7 @@ class PlayerPawn : Actor native CheckUse(); CheckUndoMorph(); // Cycle psprites - player.TickPSprites(); + TickPSprites(); // Other Counters if (player.damagecount) player.damagecount--; @@ -1049,12 +1267,13 @@ class PlayerPawn : Actor native native clearscope int GetMaxHealth(bool withupgrades = false) const; native bool ResetAirSupply (bool playgasp = false); - native void CheckWeaponSwitch(class item); native clearscope static String GetPrintableDisplayName(Class cls); native void CheckMusicChange(); native void CalcHeight (); native void CheckEnvironment(); native void CheckUse(); + native void CheckWeaponButtons(); + native Weapon BestWeapon(class ammotype); } @@ -1112,6 +1331,26 @@ class PSprite : Object native play native void SetState(State newstate, bool pending = false); + //------------------------------------------------------------------------ + // + // + // + //------------------------------------------------------------------------ + + void Tick() + { + if (processPending) + { + // drop tic count and possibly change state + if (Tics != -1) // a -1 tic count never changes + { + Tics--; + // [BC] Apply double firing speed. + if (bPowDouble && Tics && (Owner.mo.FindInventory ("PowerDoubleFiringSpeed", true))) Tics--; + if (!Tics) SetState(CurState.NextState); + } + } + } } enum EPlayerState @@ -1243,7 +1482,6 @@ struct PlayerInfo native play // this is what internally is known as player_t native bool GetNoAutostartMap() const; native void SetFOV(float fov); native clearscope bool HasWeaponsInSlot(int slot) const; - native void TickPSprites(); bool IsTotallyFrozen() {