diff --git a/addons/sourcemod/configs/shavit-styles.cfg b/addons/sourcemod/configs/shavit-styles.cfg index ad6ad9f7..390e83a0 100644 --- a/addons/sourcemod/configs/shavit-styles.cfg +++ b/addons/sourcemod/configs/shavit-styles.cfg @@ -37,6 +37,9 @@ "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. "timescale" "1.0" // Timing will scale with this setting. + + "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 + "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. "bonus_velocity" "0.0" // Bonus velocity to gain per jump. If set to e.g. 100.0, the player will gain 100 bonus velocity per jump. diff --git a/addons/sourcemod/scripting/include/shavit/core.inc b/addons/sourcemod/scripting/include/shavit/core.inc index c7509172..c8cfb1bf 100644 --- a/addons/sourcemod/scripting/include/shavit/core.inc +++ b/addons/sourcemod/scripting/include/shavit/core.inc @@ -140,6 +140,11 @@ enum struct timer_snapshot_t MoveType iLastMoveType; float fStrafeWarning; float fLastInputVel[2]; + + float fplayer_speedmod; + float fNextFrameTime; + + MoveType iLastMoveTypeTAS; } stock void Shavit_LogQuery(const char[] query) @@ -1303,6 +1308,15 @@ native float Shavit_GetClientTimescale(int client); */ native bool Shavit_Core_CookiesRetrieved(int client); +/** + * When using the timer's timescale_tas stuff, this returns whether the current frame should be recorded by replay plugins. + * + * @param client Client index + * + * @return true if the current frame should be recorded.... + */ +native bool Shavit_ShouldProcessFrame(int client); + public SharedPlugin __pl_shavit_core = { name = "shavit", @@ -1367,6 +1381,7 @@ public void __pl_shavit_core_SetNTVOptional() MarkNativeAsOptional("Shavit_SetStyleSettingBool"); MarkNativeAsOptional("Shavit_SetStyleSettingInt"); MarkNativeAsOptional("Shavit_Core_CookiesRetrieved"); + MarkNativeAsOptional("Shavit_ShouldProcessFrame"); __pl_shavit_bhopstats_SetNTVOptional(); } diff --git a/addons/sourcemod/scripting/include/shavit/style-settings.sp b/addons/sourcemod/scripting/include/shavit/style-settings.sp index 62d1b92c..db569672 100644 --- a/addons/sourcemod/scripting/include/shavit/style-settings.sp +++ b/addons/sourcemod/scripting/include/shavit/style-settings.sp @@ -162,6 +162,9 @@ public SMCResult OnStyleEnterSection(SMCParser smc, const char[] name, bool opt_ SetStyleSettingFloat(gI_CurrentParserIndex, "speed", 1.0); SetStyleSettingInt (gI_CurrentParserIndex, "halftime", 0); SetStyleSettingFloat(gI_CurrentParserIndex, "timescale", 1.0); + + SetStyleSettingInt (gI_CurrentParserIndex, "tas_timescale", 0); + SetStyleSettingInt (gI_CurrentParserIndex, "force_timescale", 0); SetStyleSettingFloat(gI_CurrentParserIndex, "velocity", 1.0); SetStyleSettingFloat(gI_CurrentParserIndex, "bonus_velocity", 0.0); diff --git a/addons/sourcemod/scripting/shavit-checkpoints.sp b/addons/sourcemod/scripting/shavit-checkpoints.sp index 66c0168b..d78d41b2 100644 --- a/addons/sourcemod/scripting/shavit-checkpoints.sp +++ b/addons/sourcemod/scripting/shavit-checkpoints.sp @@ -1441,6 +1441,12 @@ 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; diff --git a/addons/sourcemod/scripting/shavit-core.sp b/addons/sourcemod/scripting/shavit-core.sp index 2187cdf5..729b382e 100644 --- a/addons/sourcemod/scripting/shavit-core.sp +++ b/addons/sourcemod/scripting/shavit-core.sp @@ -208,6 +208,7 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max CreateNative("Shavit_SetAvgVelocity", Native_SetAvgVelocity); CreateNative("Shavit_SetMaxVelocity", Native_SetMaxVelocity); CreateNative("Shavit_Core_CookiesRetrieved", Native_Core_CookiesRetrieved); + CreateNative("Shavit_ShouldProcessFrame", Native_ShouldProcessFrame); // registers library, check "bool LibraryExists(const char[] name)" in order to use with other plugins RegPluginLibrary("shavit"); @@ -318,6 +319,14 @@ public void OnPluginStart() RegConsoleCmd("sm_autobhop", Command_AutoBhop, "Toggle autobhop."); gH_AutoBhopCookie = RegClientCookie("shavit_autobhop", "Autobhop cookie", CookieAccess_Protected); + // Timescale commandssssssssss + RegConsoleCmd("sm_timescale", Command_Timescale, "Sets your timescale on TAS styles."); + RegConsoleCmd("sm_ts", Command_Timescale, "Sets your timescale on TAS styles."); + RegConsoleCmd("sm_timescaleplus", Command_TimescalePlus, "Adds the value to your current timescale."); + RegConsoleCmd("sm_tsplus", Command_TimescalePlus, "Adds the value to your current timescale."); + RegConsoleCmd("sm_timescaleminus", Command_TimescaleMinus, "Subtracts the value from your current timescale."); + RegConsoleCmd("sm_tsminus", Command_TimescaleMinus, "Subtracts the value from your current timescale."); + #if DEBUG RegConsoleCmd("sm_finishtest", Command_FinishTest); RegConsoleCmd("sm_fling", Command_Fling); @@ -799,6 +808,124 @@ public Action Command_TogglePause(int client, int args) return Plugin_Handled; } +public Action Command_Timescale(int client, int args) +{ + if (!IsValidClient(client, true)) + { + return Plugin_Handled; + } + + if (!GetStyleSettingInt(gA_Timers[client].bsStyle, "tas_timescale")) + { + Shavit_PrintToChat(client, "%T", "NoEditingTimescale", client); + return Plugin_Handled; + } + + if (args < 1) + { + Shavit_PrintToChat(client, "!timescale "); + return Plugin_Handled; + } + + char sArg[16]; + GetCmdArg(1, sArg, 16); + float ts = StringToFloat(sArg); + + if (ts == -1.0) + { + ts = GetStyleSettingFloat(gA_Timers[client].bsStyle, "timescale"); + } + + if (ts >= 0.0001 && ts <= 1.0) + { + Shavit_SetClientTimescale(client, ts); + Shavit_PrintToChat(client, "%f", ts); + } + + return Plugin_Handled; +} + +public Action Command_TimescalePlus(int client, int args) +{ + if (!IsValidClient(client, true)) + { + return Plugin_Handled; + } + + if (!GetStyleSettingInt(gA_Timers[client].bsStyle, "tas_timescale")) + { + Shavit_PrintToChat(client, "%T", "NoEditingTimescale", client); + return Plugin_Handled; + } + + float ts = 0.1; + + if (args > 0) + { + char sArg[16]; + GetCmdArg(1, sArg, 16); + ts = StringToFloat(sArg); + } + + if (ts >= 0.0001) + { + ts += gA_Timers[client].fTimescale; + + if (ts > 1.0) + { + ts = 1.0; + } + + Shavit_SetClientTimescale(client, ts); + Shavit_PrintToChat(client, "%f", ts); + } + + return Plugin_Handled; +} + +public Action Command_TimescaleMinus(int client, int args) +{ + if (!IsValidClient(client, true)) + { + return Plugin_Handled; + } + + if (!GetStyleSettingInt(gA_Timers[client].bsStyle, "tas_timescale")) + { + Shavit_PrintToChat(client, "%T", "NoEditingTimescale", client); + return Plugin_Handled; + } + + float ts = 0.1; + + if (args > 0) + { + char sArg[16]; + GetCmdArg(1, sArg, 16); + ts = StringToFloat(sArg); + } + + if (ts >= 0.0001) + { + float newts = gA_Timers[client].fTimescale - ts; + + if (newts < ts) + { + newts = ts; + } + + if (newts < 0.0001) + { + newts = 0.0001; + } + + Shavit_SetClientTimescale(client, newts); + Shavit_PrintToChat(client, "%f", newts); + } + + return Plugin_Handled; +} + #if DEBUG public Action Command_FinishTest(int client, int args) { @@ -1185,6 +1312,17 @@ void CallOnTrackChanged(int client, int oldtrack, int newtrack) } } +void UpdateLaggedMovement(int client, bool eventqueuefix) +{ + float speed = gA_Timers[client].fTimescale * GetStyleSettingFloat(gA_Timers[client].bsStyle, "speed") * gA_Timers[client].fplayer_speedmod; + SetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue", speed); // might be problematic with the shavit-kz stuff TODO + + if (eventqueuefix && gB_Eventqueuefix) + { + SetEventsTimescale(client, speed); + } +} + void CallOnStyleChanged(int client, int oldstyle, int newstyle, bool manual, bool nofoward=false) { if (!nofoward) @@ -1210,13 +1348,7 @@ void CallOnStyleChanged(int client, int oldstyle, int newstyle, bool manual, boo UpdateStyleSettings(client); - float newLaggedMovement = fNewTimescale * GetStyleSettingFloat(newstyle, "speed"); - SetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue", newLaggedMovement); // might be problematic with the shavit-kz stuff TODO - - if (gB_Eventqueuefix) - { - SetEventsTimescale(client, newLaggedMovement); - } + UpdateLaggedMovement(client, true); SetEntityGravity(client, GetStyleSettingFloat(newstyle, "gravity")); } @@ -1338,13 +1470,7 @@ void VelocityChanges(int data) if(GetStyleSettingBool(style, "force_timescale")) { - float mod = gA_Timers[client].fTimescale * GetStyleSettingFloat(gA_Timers[client].bsStyle, "speed"); - SetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue", mod); - - if (gB_Eventqueuefix) - { - SetEventsTimescale(client, mod); - } + UpdateLaggedMovement(client, true); } float fAbsVelocity[3]; @@ -2008,6 +2134,7 @@ public int Native_SetClientTimescale(Handle handler, int numParams) { CallOnTimescaleChanged(client, gA_Timers[client].fTimescale, timescale); gA_Timers[client].fTimescale = timescale; + UpdateLaggedMovement(client, true); } } @@ -2036,6 +2163,14 @@ public any Native_Core_CookiesRetrieved(Handle plugin, int numParams) return gB_CookiesRetrieved[GetNativeCell(1)]; } +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"); +} + public Action Shavit_OnStartPre(int client, int track) { if (GetTimerStatus(client) == Timer_Paused && gCV_PauseMovement.BoolValue) @@ -2129,13 +2264,11 @@ void StartTimer(int client, int track) gA_Timers[client].fAvgVelocity = curVel; gA_Timers[client].fMaxVelocity = curVel; - float mod = gA_Timers[client].fTimescale * GetStyleSettingFloat(gA_Timers[client].bsStyle, "speed"); - SetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue", mod); + // TODO: Look into when this should be reset (since resetting it here disables timescale while in startzone). + //gA_Timers[client].fNextFrameTime = 0.0; - if (gB_Eventqueuefix) - { - SetEventsTimescale(client, mod); - } + //gA_Timers[client].fplayer_speedmod = 1.0; + UpdateLaggedMovement(client, true); SetEntityGravity(client, GetStyleSettingFloat(gA_Timers[client].bsStyle, "gravity")); } @@ -2264,6 +2397,8 @@ public void OnClientPutInServer(int client) gA_Timers[client].iFullTicks = 0; gA_Timers[client].iFractionalTicks = 0; gA_Timers[client].iZoneIncrement = 0; + gA_Timers[client].fNextFrameTime = 0.0; + gA_Timers[client].fplayer_speedmod = 1.0; gS_DeleteMap[client][0] = 0; gB_CookiesRetrieved[client] = false; @@ -2559,10 +2694,9 @@ public MRESReturn DHook_AcceptInput_player_speedmod_Post(int pThis, DHookReturn hParams.GetObjectVarString(4, 0, ObjectValueType_String, buf, sizeof(buf)); float speed = StringToFloat(buf); - int style = gA_Timers[activator].bsStyle; - speed *= gA_Timers[activator].fTimescale * GetStyleSettingFloat(style, "speed"); - SetEntPropFloat(activator, Prop_Data, "m_flLaggedMovementValue", speed); + gA_Timers[activator].fplayer_speedmod = speed; + UpdateLaggedMovement(activator, false); #if DEBUG int caller = hParams.Get(3); @@ -2584,6 +2718,25 @@ 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) + { + return MRES_Ignored; + } + + // i got this code from kid-tas by kid fearless + if (gA_Timers[client].fNextFrameTime <= 0.0) + { + gA_Timers[client].fNextFrameTime += (1.0 - gA_Timers[client].fTimescale); + gA_Timers[client].iLastMoveTypeTAS = GetEntityMoveType(client); + SetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue", + gA_Timers[client].fplayer_speedmod * GetStyleSettingFloat(gA_Timers[client].bsStyle, "speed")); + } + else + { + gA_Timers[client].fNextFrameTime -= gA_Timers[client].fTimescale; + SetEntityMoveType(client, MOVETYPE_NONE); + } + return MRES_Ignored; } @@ -2595,6 +2748,12 @@ 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) + { + SetEntityMoveType(client, gA_Timers[client].iLastMoveTypeTAS); + UpdateLaggedMovement(client, true); + } + if (gA_Timers[client].bClientPaused || !gA_Timers[client].bTimerEnabled) { return MRES_Ignored; diff --git a/addons/sourcemod/scripting/shavit-replay-recorder.sp b/addons/sourcemod/scripting/shavit-replay-recorder.sp index e8d97301..582bb614 100644 --- a/addons/sourcemod/scripting/shavit-replay-recorder.sp +++ b/addons/sourcemod/scripting/shavit-replay-recorder.sp @@ -87,7 +87,6 @@ int gI_PlayerFinishFrame[MAXPLAYERS+1]; int gI_PlayerFrames[MAXPLAYERS+1]; int gI_PlayerPrerunFrames[MAXPLAYERS+1]; ArrayList gA_PlayerFrames[MAXPLAYERS+1]; -float gF_NextFrameTime[MAXPLAYERS+1]; int gI_HijackFrames[MAXPLAYERS+1]; float gF_HijackedAngles[MAXPLAYERS+1][2]; @@ -249,18 +248,12 @@ void ClearFrames(int client) delete gA_PlayerFrames[client]; gA_PlayerFrames[client] = new ArrayList(sizeof(frame_t)); gI_PlayerFrames[client] = 0; - gF_NextFrameTime[client] = 0.0; gI_PlayerPrerunFrames[client] = 0; gI_PlayerFinishFrame[client] = 0; gI_HijackFrames[client] = 0; gB_HijackFramesKeepOnStart[client] = false; } -public void Shavit_OnTimescaleChanged(int client, float oldtimescale, float newtimescale) -{ - gF_NextFrameTime[client] = 0.0; -} - public Action Shavit_OnStart(int client) { gB_RecordingEnabled[client] = true; @@ -518,15 +511,8 @@ public void OnPlayerRunCmdPost(int client, int buttons, int impulse, const float return; } - float fTimescale = Shavit_GetClientTimescale(client); - - if (gF_NextFrameTime[client] > 0.0) + if (!Shavit_ShouldProcessFrame(client)) { - if (fTimescale != -1.0) - { - gF_NextFrameTime[client] -= fTimescale; - } - return; } @@ -561,11 +547,6 @@ public void OnPlayerRunCmdPost(int client, int buttons, int impulse, const float aFrame.vel = LimitMoveVelFloat(vel[0]) | (LimitMoveVelFloat(vel[1]) << 16); gA_PlayerFrames[client].SetArray(gI_PlayerFrames[client]++, aFrame, sizeof(frame_t)); - - if (fTimescale != -1.0) - { - gF_NextFrameTime[client] += (1.0 - fTimescale); - } } stock int LimitMoveVelFloat(float vel) diff --git a/addons/sourcemod/translations/shavit-core.phrases.txt b/addons/sourcemod/translations/shavit-core.phrases.txt index f4ac0ef7..36d786bd 100644 --- a/addons/sourcemod/translations/shavit-core.phrases.txt +++ b/addons/sourcemod/translations/shavit-core.phrases.txt @@ -26,6 +26,10 @@ "#format" "{1:s},{2:s}" "en" "You lack the {1}permissions{2} for this style." } + "NoEditingTimescale" + { + "en" "This style doesn't allow you to change timescale." + } // ---------- Errors ---------- // "VerificationFailed" {