diff --git a/addons/sourcemod/configs/shavit-styles.cfg b/addons/sourcemod/configs/shavit-styles.cfg index 134b476b..975f8090 100644 --- a/addons/sourcemod/configs/shavit-styles.cfg +++ b/addons/sourcemod/configs/shavit-styles.cfg @@ -37,9 +37,9 @@ "runspeed" "260.00" // Running speed. Requires DHooks, shavit-misc and shavit_misc_staticprestrafe set to 1. "gravity" "1.0" // Gravity setting, 1.0 for default. Standard for low gravity styles is 0.6. "speed" "1.0" // Speed multiplier, 1.0 for default. Standard for slowmo styles is 0.5. This a multiplier for m_flLaggedMovementValue. - "timescale" "1.0" // Timing will scale with this setting. This is also a multiplier for m_flLaggedMovementValue. + "timescale" "1.0" // Timing will scale with this setting. This is a multiplier for m_flLaggedMovementValue but also affects the timer increase speed. - "tas_timescale" "0" // 1 = enabled. 0 = disabled. Allows player to edit their timescale like a TAS plugin with sm_timescale, sm_timescaleplus, and sm_timescaleminus. Total timescale for the player = style_timescale * user_tas_timescale + "tas_timescale" "0" // TAS-like timescaling. 0 = Disabled. -1 = User can edit the timescale (TAS menu, sm_ts, sm_tsplus, sm_tsminus). >0 = Fixed tas-timescale value for the style (e.g. 0.5 for a fixed timescale). Total time-increase-rate for the player = timescale * tas_timescale "force_timescale" "0" // Force the timescale every jump? Default is 0 for normal timescales. "velocity" "1.0" // % of horizontal velocity to keep per jump. a value 0.9 will make the player lose 10% of their velocity per jump. Likewise, values above 1 will result in speed gains. diff --git a/addons/sourcemod/scripting/include/shavit/core.inc b/addons/sourcemod/scripting/include/shavit/core.inc index 74e65f3b..f58d76ad 100644 --- a/addons/sourcemod/scripting/include/shavit/core.inc +++ b/addons/sourcemod/scripting/include/shavit/core.inc @@ -1181,9 +1181,9 @@ native void Shavit_SaveSnapshot(int client, any[] snapshot, int size = sizeof(ti * @param client Client index. * @param snapshot Full snapshot of the client's timer. * @param size Size of the snapshot buffer, e.g sizeof(timer_snapshot_t) - * @noreturn + * @return Success boolean */ -native void Shavit_LoadSnapshot(int client, any[] snapshot, int size = sizeof(timer_snapshot_t)); +native bool Shavit_LoadSnapshot(int client, any[] snapshot, int size = sizeof(timer_snapshot_t)); /** * Use this native to stop the click sound that plays upon chat messages. @@ -1331,6 +1331,16 @@ native void Shavit_SetClientTimescale(int client, float scale); */ native float Shavit_GetClientTimescale(int client); +/** + * Something to be used by the checkpoint plugin to trigger updating laggedmovement. + * + * @param client Client index + * @param user_timescale Whether to use fTimescale as a multiplier for laggedmovement too. + * + * @noreturn + */ +native void Shavit_UpdateLaggedMovement(int client, bool user_timescale=true); + /** * asdf * @@ -1425,6 +1435,7 @@ public void __pl_shavit_core_SetNTVOptional() MarkNativeAsOptional("Shavit_Core_CookiesRetrieved"); MarkNativeAsOptional("Shavit_ShouldProcessFrame"); MarkNativeAsOptional("Shavit_GotoEnd"); + MarkNativeAsOptional("Shavit_UpdateLaggedMovement"); __pl_shavit_bhopstats_SetNTVOptional(); } diff --git a/addons/sourcemod/scripting/shavit-checkpoints.sp b/addons/sourcemod/scripting/shavit-checkpoints.sp index d78d41b2..b838e2b2 100644 --- a/addons/sourcemod/scripting/shavit-checkpoints.sp +++ b/addons/sourcemod/scripting/shavit-checkpoints.sp @@ -1441,12 +1441,6 @@ void SaveCheckpointCache(int target, cp_cache_t cpcache, bool actually_a_checkpo else { Shavit_SaveSnapshot(target, snapshot); - - // hacky but should be done for timescale_tas stuff... - if (!Shavit_ShouldProcessFrame(target)) - { - cpcache.iMoveType = MOVETYPE_NONE; - } } cpcache.aSnapshot = snapshot; @@ -1583,9 +1577,13 @@ void LoadCheckpointCache(int client, cp_cache_t cpcache, bool isPersistentData) Shavit_SetPracticeMode(client, true, true); } - Shavit_LoadSnapshot(client, cpcache.aSnapshot); + if (!Shavit_LoadSnapshot(client, cpcache.aSnapshot)) + { + Shavit_StopTimer(client); // TODO: Reorg this function so the stoptimer isn't necessary and we just bail out sooner + return; + } - SetEntPropFloat(client, Prop_Send, "m_flLaggedMovementValue", cpcache.fSpeed); + Shavit_UpdateLaggedMovement(client, true); SetEntPropString(client, Prop_Data, "m_iName", cpcache.sTargetname); SetEntPropString(client, Prop_Data, "m_iClassname", cpcache.sClassname); diff --git a/addons/sourcemod/scripting/shavit-core.sp b/addons/sourcemod/scripting/shavit-core.sp index fb1b58b0..273e6c28 100644 --- a/addons/sourcemod/scripting/shavit-core.sp +++ b/addons/sourcemod/scripting/shavit-core.sp @@ -212,6 +212,7 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max CreateNative("Shavit_Core_CookiesRetrieved", Native_Core_CookiesRetrieved); CreateNative("Shavit_ShouldProcessFrame", Native_ShouldProcessFrame); CreateNative("Shavit_GotoEnd", Native_GotoEnd); + CreateNative("Shavit_UpdateLaggedMovement", Native_UpdateLaggedMovement); // registers library, check "bool LibraryExists(const char[] name)" in order to use with other plugins RegPluginLibrary("shavit"); @@ -812,7 +813,7 @@ public Action Command_Timescale(int client, int args) return Plugin_Handled; } - if (!GetStyleSettingInt(gA_Timers[client].bsStyle, "tas_timescale")) + if (GetStyleSettingFloat(gA_Timers[client].bsStyle, "tas_timescale") != -1.0) { Shavit_PrintToChat(client, "%T", "NoEditingTimescale", client); return Plugin_Handled; @@ -844,7 +845,7 @@ public Action Command_TimescalePlus(int client, int args) return Plugin_Handled; } - if (!GetStyleSettingInt(gA_Timers[client].bsStyle, "tas_timescale")) + if (GetStyleSettingFloat(gA_Timers[client].bsStyle, "tas_timescale") != -1.0) { Shavit_PrintToChat(client, "%T", "NoEditingTimescale", client); return Plugin_Handled; @@ -882,7 +883,7 @@ public Action Command_TimescaleMinus(int client, int args) return Plugin_Handled; } - if (!GetStyleSettingInt(gA_Timers[client].bsStyle, "tas_timescale")) + if (GetStyleSettingFloat(gA_Timers[client].bsStyle, "tas_timescale") != -1.0) { Shavit_PrintToChat(client, "%T", "NoEditingTimescale", client); return Plugin_Handled; @@ -1328,22 +1329,32 @@ void CallOnTrackChanged(int client, int oldtrack, int newtrack) } } -void UpdateLaggedMovement(int client, bool eventqueuefix, bool user_timescale) +public any Native_UpdateLaggedMovement(Handle handler, int numParams) { - float speed = - (user_timescale ? gA_Timers[client].fTimescale : 1.0) - * GetStyleSettingFloat(gA_Timers[client].bsStyle, "timescale") + int client = GetNativeCell(1); + bool user_timescale = GetNativeCell(2) != 0; + UpdateLaggedMovement(client, user_timescale); +} + +void UpdateLaggedMovement(int client, bool user_timescale) +{ + float style_laggedmovement = + GetStyleSettingFloat(gA_Timers[client].bsStyle, "timescale") * GetStyleSettingFloat(gA_Timers[client].bsStyle, "speed"); - SetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue", speed * gA_Timers[client].fplayer_speedmod); + float laggedmovement = + (user_timescale ? gA_Timers[client].fTimescale : 1.0) + * style_laggedmovement; - if (eventqueuefix && gB_Eventqueuefix) + SetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue", laggedmovement * gA_Timers[client].fplayer_speedmod); + + if (gB_Eventqueuefix) { - SetEventsTimescale(client, speed); + SetEventsTimescale(client, style_laggedmovement); } } -void CallOnStyleChanged(int client, int oldstyle, int newstyle, bool manual, bool nofoward=false, bool skiptsforward=false) +void CallOnStyleChanged(int client, int oldstyle, int newstyle, bool manual, bool nofoward=false) { gA_Timers[client].bsStyle = newstyle; @@ -1358,16 +1369,16 @@ void CallOnStyleChanged(int client, int oldstyle, int newstyle, bool manual, boo Call_Finish(); } - if (!skiptsforward) - { - if (gA_Timers[client].fTimescale != 1.0) - { - CallOnTimescaleChanged(client, gA_Timers[client].fTimescale, 1.0); - } + float style_ts = GetStyleSettingFloat(newstyle, "tas_timescale"); - UpdateLaggedMovement(client, true, true); + if (style_ts >= 0.0) + { + float newts = (style_ts > 0.0) ? style_ts : 1.0; // 🦎🦎🦎 + Shavit_SetClientTimescale(client, newts); } + UpdateLaggedMovement(client, true); + UpdateStyleSettings(client); SetEntityGravity(client, GetStyleSettingFloat(newstyle, "gravity")); @@ -1498,10 +1509,12 @@ void VelocityChanges(int data) int style = gA_Timers[client].bsStyle; +#if 0 if(GetStyleSettingBool(style, "force_timescale")) { - UpdateLaggedMovement(client, true, true); + UpdateLaggedMovement(client, true); } +#endif float fAbsVelocity[3]; GetEntPropVector(client, Prop_Data, "m_vecAbsVelocity", fAbsVelocity); @@ -2124,22 +2137,32 @@ public int Native_LoadSnapshot(Handle handler, int numParams) GetNativeArray(2, snapshot, sizeof(timer_snapshot_t)); snapshot.fTimescale = (snapshot.fTimescale > 0.0) ? snapshot.fTimescale : 1.0; + if (!Shavit_HasStyleAccess(client, snapshot.bsStyle)) + { + return 0; + } + if (gA_Timers[client].iTimerTrack != snapshot.iTimerTrack) { CallOnTrackChanged(client, gA_Timers[client].iTimerTrack, snapshot.iTimerTrack); } - if (gA_Timers[client].bsStyle != snapshot.bsStyle && Shavit_HasStyleAccess(client, snapshot.bsStyle)) + if (gA_Timers[client].bsStyle != snapshot.bsStyle) { - CallOnStyleChanged(client, gA_Timers[client].bsStyle, snapshot.bsStyle, false, true); + CallOnStyleChanged(client, gA_Timers[client].bsStyle, snapshot.bsStyle, false); } - Shavit_SetClientTimescale(client, snapshot.fTimescale); // will call ts-changed forward & UpdateLaggedMovement + float oldts = gA_Timers[client].fTimescale; gA_Timers[client] = snapshot; gA_Timers[client].bClientPaused = snapshot.bClientPaused && snapshot.bTimerEnabled; - return 0; + if (GetStyleSettingFloat(snapshot.bsStyle, "tas_timescale") < 0.0) + { + Shavit_SetClientTimescale(client, oldts); + } + + return 1; } public int Native_LogMessage(Handle plugin, int numParams) @@ -2186,7 +2209,7 @@ public int Native_SetClientTimescale(Handle handler, int numParams) if (timescale != gA_Timers[client].fTimescale && timescale > 0.0) { CallOnTimescaleChanged(client, gA_Timers[client].fTimescale, timescale); - UpdateLaggedMovement(client, true, true); + UpdateLaggedMovement(client, true); } } @@ -2219,8 +2242,7 @@ public any Native_ShouldProcessFrame(Handle plugin, int numParams) { int client = GetNativeCell(1); return gA_Timers[client].fTimescale == 1.0 - || gA_Timers[client].fNextFrameTime <= 0.0 - || !GetStyleSettingBool(gA_Timers[client].bsStyle, "tas_timescale"); + || gA_Timers[client].fNextFrameTime <= 0.0; } public Action Shavit_OnStartPre(int client, int track) @@ -2320,7 +2342,7 @@ void StartTimer(int client, int track) //gA_Timers[client].fNextFrameTime = 0.0; //gA_Timers[client].fplayer_speedmod = 1.0; - UpdateLaggedMovement(client, true, true); + UpdateLaggedMovement(client, true); SetEntityGravity(client, GetStyleSettingFloat(gA_Timers[client].bsStyle, "gravity")); } @@ -2750,7 +2772,7 @@ public MRESReturn DHook_AcceptInput_player_speedmod_Post(int pThis, DHookReturn float speed = StringToFloat(buf); gA_Timers[activator].fplayer_speedmod = speed; - UpdateLaggedMovement(activator, false, true); + UpdateLaggedMovement(activator, true); #if DEBUG int caller = hParams.Get(3); @@ -2772,8 +2794,17 @@ public MRESReturn DHook_ProcessMovement(Handle hParams) Call_PushCell(client); Call_Finish(); - if (!GetStyleSettingBool(gA_Timers[client].bsStyle, "tas_timescale") || gA_Timers[client].fTimescale == 1.0) + if (IsFakeClient(client) || !IsPlayerAlive(client)) { + SetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue", 1.0); // otherwise you get slow spec noclip + return MRES_Ignored; + } + + MoveType mt = GetEntityMoveType(client); + + if (gA_Timers[client].fTimescale == 1.0 || mt == MOVETYPE_NOCLIP) + { + SetClientEventsPaused(client, gA_Timers[client].bClientPaused); return MRES_Ignored; } @@ -2781,8 +2812,13 @@ public MRESReturn DHook_ProcessMovement(Handle hParams) if (gA_Timers[client].fNextFrameTime <= 0.0) { gA_Timers[client].fNextFrameTime += (1.0 - gA_Timers[client].fTimescale); - gA_Timers[client].iLastMoveTypeTAS = GetEntityMoveType(client); - UpdateLaggedMovement(client, false, false); + + if (mt != MOVETYPE_NONE) + { + gA_Timers[client].iLastMoveTypeTAS = mt; + } + + UpdateLaggedMovement(client, false); } else { @@ -2790,6 +2826,11 @@ public MRESReturn DHook_ProcessMovement(Handle hParams) SetEntityMoveType(client, MOVETYPE_NONE); } + if (gB_Eventqueuefix) + { + SetClientEventsPaused(client, (!Shavit_ShouldProcessFrame(client) || gA_Timers[client].bClientPaused)); + } + return MRES_Ignored; } @@ -2801,10 +2842,15 @@ public MRESReturn DHook_ProcessMovementPost(Handle hParams) Call_PushCell(client); Call_Finish(); - if (GetStyleSettingBool(gA_Timers[client].bsStyle, "tas_timescale") && gA_Timers[client].fTimescale != 1.0) + if (IsFakeClient(client) || !IsPlayerAlive(client)) + { + return MRES_Ignored; + } + + if (gA_Timers[client].fTimescale != 1.0 && GetEntityMoveType(client) != MOVETYPE_NOCLIP) { SetEntityMoveType(client, gA_Timers[client].iLastMoveTypeTAS); - UpdateLaggedMovement(client, true, true); + UpdateLaggedMovement(client, true); } if (gA_Timers[client].bClientPaused || !gA_Timers[client].bTimerEnabled) diff --git a/addons/sourcemod/scripting/shavit-replay-playback.sp b/addons/sourcemod/scripting/shavit-replay-playback.sp index 5fb85f96..3b01dbc9 100644 --- a/addons/sourcemod/scripting/shavit-replay-playback.sp +++ b/addons/sourcemod/scripting/shavit-replay-playback.sp @@ -1939,7 +1939,7 @@ public void OnEntityCreated(int entity, const char[] classname) { // trigger_once | trigger_multiple.. etc // func_door | func_door_rotating - if(StrContains(classname, "trigger_") != -1 || StrContains(classname, "_door") != -1) + if (StrContains(classname, "trigger_") != -1 || StrContains(classname, "_door") != -1 || StrContains(classname, "player_speedmod") != -1) { SDKHook(entity, SDKHook_StartTouch, HookTriggers); SDKHook(entity, SDKHook_EndTouch, HookTriggers);