Skip to content

Commit

Permalink
refactor(sprinting): Fix prediction errors & rewrite sprint class
Browse files Browse the repository at this point in the history
  • Loading branch information
saibotk committed Oct 19, 2023
1 parent f51ae62 commit 916c146
Show file tree
Hide file tree
Showing 14 changed files with 172 additions and 257 deletions.
8 changes: 7 additions & 1 deletion gamemodes/terrortown/entities/weapons/weapon_tttbase.lua
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,13 @@ if CLIENT then

local client = LocalPlayer()

if not enable_crosshair:GetBool() or not IsValid(client) or client:GetSprintingPredicted() and not GetGlobalBool("ttt2_sprint_crosshair", false) then return end
if
not enable_crosshair:GetBool()
or not IsValid(client)
or SPRINT:IsSprinting(client) and not SPRINT.convars.showCrosshair:GetBool()
then
return
end

local sights = not self.NoSights and self:GetIronsights()
local x = math.floor(ScrW() * 0.5)
Expand Down
41 changes: 0 additions & 41 deletions gamemodes/terrortown/gamemode/client/cl_keys.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
-- @section key_manager

local IsValid = IsValid
local UpdateInputSprint = UpdateInputSprint
local cv_sv_cheats = GetConVar("sv_cheats")

local function SendWeaponDrop()
Expand Down Expand Up @@ -132,43 +131,3 @@ function GM:PlayerBindPress(ply, bindName, pressed)
RunConsoleCommand("ttt_quickslot", "5")
end
end

---
-- Called whenever a @{Player} pressed a key included within the IN keys.<br />
-- For a more general purpose function that handles all kinds of input, see @{GM:PlayerButtonDown}.
-- @warning Due to this being a predicted hook, <a href="https://wiki.garrysmod.com/page/Global/ParticleEffect">ParticleEffects</a>
-- created only serverside from this hook will not be networked to the client, so make sure to do that on both realms
-- @predicted
-- @param Player ply The @{Player} pressing the key. If running client-side, this will always be LocalPlayer
-- @param number key The key that the player pressed using <a href="https://wiki.garrysmod.com/page/Enums/IN">IN_Enums</a>.
-- @note Note that for some reason KeyPress and KeyRelease are called multiple times
-- for the same key event in multiplayer.
-- @hook
-- @realm client
-- @ref https://wiki.facepunch.com/gmod/GM:KeyPress
-- @local
function GM:KeyPress(ply, key)
if not IsFirstTimePredicted() or not IsValid(ply) or ply ~= LocalPlayer() then return end

if key == IN_FORWARD or key == IN_BACK or key == IN_MOVERIGHT or key == IN_MOVELEFT then
UpdateInputSprint(ply, key, true)
end
end

---
-- Runs when a IN key was released by a player.<br />
-- For a more general purpose function that handles all kinds of input, see @{GM:PlayerButtonUp}.
-- @param Player ply The @{Player} releasing the key. If running client-side, this will always be LocalPlayer
-- @param number key The key that the player released using <a href="https://wiki.garrysmod.com/page/Enums/IN">IN_Enums</a>.
-- @predicted
-- @hook
-- @realm client
-- @ref https://wiki.facepunch.com/gmod/GM:KeyRelease
-- @local
function GM:KeyRelease(ply, key)
if not IsFirstTimePredicted() or not IsValid(ply) or ply ~= LocalPlayer() then return end

if key == IN_FORWARD or key == IN_BACK or key == IN_MOVERIGHT or key == IN_MOVELEFT then
UpdateInputSprint(ply, key, false)
end
end
1 change: 0 additions & 1 deletion gamemodes/terrortown/gamemode/client/cl_main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,6 @@ function GM:ClearClientState()
client.last_id = nil
client.radio = nil
client.called_corpses = {}
client.sprintProgress = 1

client:SetTargetPlayer(nil)

Expand Down
2 changes: 2 additions & 0 deletions gamemodes/terrortown/gamemode/server/sv_player.lua
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ end
-- @ref https://wiki.facepunch.com/gmod/GM:PlayerSpawn
-- @local
function GM:PlayerSpawn(ply)
player_manager.SetPlayerClass(ply, "player_ttt")

-- reset any cached weapons
ply:ResetCachedWeapons()

Expand Down
3 changes: 0 additions & 3 deletions gamemodes/terrortown/gamemode/server/sv_player_ext.lua
Original file line number Diff line number Diff line change
Expand Up @@ -664,9 +664,6 @@ function plymeta:InitialSpawn()

self:ResetStatus()

-- Always reset sprint
self.sprintProgress = 1

-- Start off with clean, full karma (unless it can and should be loaded)
self:InitKarma()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ if CLIENT then
-- sprint bar
local sbh = 8 -- spring bar height

if GetGlobalBool("ttt2_sprint_enabled", true) then
self:PaintBar(x + margin, ammo_y + bar_height + 5, bar_width, sbh, self.sprint_colors, client.sprintProgress)
if SPRINT.convars.enabled:GetBool() then
self:PaintBar(x + margin, ammo_y + bar_height + 5, bar_width, sbh, self.sprint_colors, client:GetSprintStamina())
end

local hastewidth = self.hastewidth
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,8 @@ if CLIENT then
-- sprint bar
ty = ty + bh + spc

if GetGlobalBool("ttt2_sprint_enabled", true) then
self:DrawBar(nx, ty, bw, sbh, color_sprint, client.sprintProgress, t_scale, "")
if SPRINT.convars.enabled:GetBool() then
self:DrawBar(nx, ty, bw, sbh, color_sprint, client:GetSprintStamina(), t_scale, "")
end

-- coin info
Expand Down
1 change: 1 addition & 0 deletions gamemodes/terrortown/gamemode/shared/sh_include.lua
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ TTTFiles = {
sh_main = {file = "sh_main.lua", on = "shared"},
sh_network_sync = {file = "sh_network_sync.lua", on = "shared"},
sh_player_ext = {file = "sh_player_ext.lua", on = "shared"},
sh_playerclass = { file = "sh_playerclass.lua", on = "shared" },
sh_printmessage_override = {file = "sh_printmessage_override.lua", on = "shared"},
sh_cvar_handler = {file = "sh_cvar_handler.lua", on = "shared"},
sh_role_module = {file = "sh_role_module.lua", on = "shared"},
Expand Down
1 change: 1 addition & 0 deletions gamemodes/terrortown/gamemode/shared/sh_init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,7 @@ ttt_include("sh_hudelement_module")
ttt_include("sh_equip_items")
ttt_include("sh_role_module")
ttt_include("sh_item_module")
ttt_include("sh_playerclass")

---
-- Returns the equipment's file name
Expand Down
21 changes: 14 additions & 7 deletions gamemodes/terrortown/gamemode/shared/sh_main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
local IsValid = IsValid
local hook = hook
local team = team
local UpdateSprint = UpdateSprint

local MAX_DROWN_TIME = 8

Expand Down Expand Up @@ -243,10 +242,22 @@ function GM:Move(ply, moveData)

local mul = ply:GetSpeedMultiplier()

mul = mul * SPRINT:HandleSpeedMultiplierCalculation(ply)

moveData:SetMaxClientSpeed(moveData:GetMaxClientSpeed() * mul)
moveData:SetMaxSpeed(moveData:GetMaxSpeed() * mul)
end

-- @param Player ply The player
-- @param MoveData moveData Movement information
-- @predicted
-- @hook
-- @realm shared
-- @ref https://wiki.facepunch.com/gmod/GM:FinishMove
function GM:FinishMove(ply, moveData)
SPRINT:HandleStaminaCalculation(ply)
end

local ttt_playercolors = {
all = {
COLOR_WHITE,
Expand Down Expand Up @@ -308,8 +319,6 @@ end
-- @realm shared
-- @ref https://wiki.facepunch.com/gmod/GM:Think
function GM:Think()
UpdateSprint()

if CLIENT then
EPOP:Think()
end
Expand All @@ -321,10 +330,8 @@ end
-- @param Player ply The player whose sprint speed should be changed
-- @param table sprintMultiplierModifier The modieable table with the sprint speed multiplier
-- @hook
-- @realm server
function GM:TTT2PlayerSprintMultiplier(ply, sprintMultiplierModifier)

end
-- @realm shared
function GM:TTT2PlayerSprintMultiplier(ply, sprintMultiplierModifier) end

---
-- A hook that is called whenever the gamemode needs to check if the player is in the superadmin usergroup.
Expand Down
24 changes: 4 additions & 20 deletions gamemodes/terrortown/gamemode/shared/sh_player_ext.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,18 @@ local IsValid = IsValid
local hook = hook
local math = math

---@class Player
local plymeta = FindMetaTable("Player")
if not plymeta then
Error("FAILED TO FIND PLAYER TABLE")

return
end

---
-- Dummy functions that will be replaced when SetupDataTables runs. These are
-- here for when that does not happen (due to e.g. stacking base classes)
-- @return[default=false] boolean
-- @realm shared
function plymeta:GetSprintingPredicted()
return false
end

---
-- Dummy functions that will be replaced when SetupDataTables runs. These are
-- here for when that does not happen (due to e.g. stacking base classes)
-- @realm shared
function plymeta:SetSprintingPredicted()

end

function plymeta:SetupDataTables()
self:NetworkVar("Bool", 3, "SprintingPredicted")

plymeta.SetupDataTables(self)
-- This has to be transferred, because we need the value when predicting the player movement
-- It turned out that this is the only reliable way to fix all prediction errors.
self:NetworkVar("Float", 0, "SprintStamina")
end

---
Expand Down
16 changes: 16 additions & 0 deletions gamemodes/terrortown/gamemode/shared/sh_playerclass.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
DEFINE_BASECLASS("player_default")

local PLAYER = {}

PLAYER.WalkSpeed = 220
PLAYER.RunSpeed = 220
PLAYER.JumpPower = 160
PLAYER.CrouchedWalkSpeed = 0.3

-- This is needed to allow adding custom networked variables to the player entity
-- Can be useful for e.g. variables necessary for prediction like the stamina.
function PLAYER:SetupDataTables()
self.Player:SetupDataTables()
end

player_manager.RegisterClass("player_ttt", PLAYER, "player_default")
50 changes: 22 additions & 28 deletions gamemodes/terrortown/gamemode/shared/sh_speed.lua
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
---
-- @class SPEED
---@class SPEED

local plymeta = assert(FindMetaTable("Player"), "FAILED TO FIND ENTITY TABLE")

SPEED = SPEED or {}
SPEED = {}

---
-- Handles the speed calculation based on the @{GM:TTTPlayerSpeedModifier} hook
-- @param Player ply The player whose speed should be changed
-- @param MoveData moveData The move data
-- @internal
-- @realm shared
--- Handles the speed calculation based on the @{GM:TTTPlayerSpeedModifier} hook
--- Note: Does not handle the sprinting speed calculation, to not show sprinting as a status.
---@param ply Player The player whose speed should be changed
---@param moveData MoveData The move data
---@internal
---@realm shared
function SPEED:HandleSpeedCalculation(ply, moveData)
if not ply:IsTerror() then return end
if not ply:IsTerror() then
return
end

local baseMultiplier = 1
local isSlowed = false
Expand All @@ -23,17 +24,9 @@ function SPEED:HandleSpeedCalculation(ply, moveData)
if IsValid(wep) and wep.GetIronsights and wep:GetIronsights() then
baseMultiplier = 120 / 220
isSlowed = true
elseif ply:GetSprintingPredicted() and (ply.sprintProgress or 0) > 0 then
local sprintMultiplierModifier = {1}

---
-- @realm shared
hook.Run("TTT2PlayerSprintMultiplier", ply, sprintMultiplierModifier)

baseMultiplier = (1 + GetGlobalFloat("ttt2_sprint_max", 0)) * sprintMultiplierModifier[1]
end

local speedMultiplierModifier = {1}
local speedMultiplierModifier = { 1 }

---
-- @realm shared
Expand All @@ -42,7 +35,9 @@ function SPEED:HandleSpeedCalculation(ply, moveData)
local oldval = ply:GetSpeedMultiplier()
ply.speedModifier = baseMultiplier * returnMultiplier * speedMultiplierModifier[1]

if SERVER then return end
if SERVER then
return
end

local newval = math.Round(ply.speedModifier, 1)

Expand All @@ -68,9 +63,7 @@ end
-- @return[deprecated] number The deprecated way of changing the player speed
-- @hook
-- @realm shared
function GM:TTTPlayerSpeedModifier(ply, isSlowed, moveData, speedMultiplierModifier)

end
function GM:TTTPlayerSpeedModifier(ply, isSlowed, moveData, speedMultiplierModifier) end

if CLIENT then
---
Expand All @@ -80,28 +73,29 @@ if CLIENT then
function SPEED:Initialize()
STATUS:RegisterStatus("ttt_speed_status_good", {
hud = {
Material("vgui/ttt/perks/hud_speedrun.png")
Material("vgui/ttt/perks/hud_speedrun.png"),
},
type = "good",
DrawInfo = function()
return math.Round(LocalPlayer():GetSpeedMultiplier(), 1)
end
end,
})

STATUS:RegisterStatus("ttt_speed_status_bad", {
hud = {
Material("vgui/ttt/perks/hud_speedrun.png")
Material("vgui/ttt/perks/hud_speedrun.png"),
},
type = "bad",
DrawInfo = function()
return math.Round(LocalPlayer():GetSpeedMultiplier(), 1)
end
end,
})
end
end

---
-- @class Player
---@class Player
local plymeta = assert(FindMetaTable("Player"), "FAILED TO FIND ENTITY TABLE")

---
-- Returns the current player speed modifier
Expand Down
Loading

0 comments on commit 916c146

Please sign in to comment.