Skip to content

Commit

Permalink
Provide 'buffering' on respawn overrides
Browse files Browse the repository at this point in the history
This makes it easier on developers, allowing them to persist their
respawn time override after the game clears out the property on the
player.
  • Loading branch information
nosoop committed Mar 16, 2022
1 parent f4831b8 commit 03fa5f7
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 8 deletions.
23 changes: 16 additions & 7 deletions scripting/include/tf2utils.inc
Original file line number Diff line number Diff line change
Expand Up @@ -135,12 +135,19 @@ native void TF2Util_SetPlayerBurnDuration(int client, float duration);
* Returns the player's respawn time override, if any. This is the number of seconds that a
* player will spend waiting to be respawned after their last death (CTFPlayer::m_flDeathTime).
*
* When a player dies, the game will set this value to -1.0 or the RespawnTime value of an
* active trigger_player_respawn_override entity that the player died in, if one exists.
* (This happens *after* the `player_death` event is fired, so you cannot retrieve their respawn
* time override during a hook on that event.)
*
* The amount of time remaining can be computed as follows:
*
*
* flRemainingTime = flDeathTime + flRespawnTimeOverride - GetGameTime();
*
* If the player does not have an override on their respawn time (i.e. they are part of normal
* respawn waves), this will return -1.0.
* respawn waves), this will return -1.0. If the player is alive, this will return whatever is
* stored on the entity (normally -1.0), and *not* any buffered value that was set using
* `TF2Util_SetPlayerRespawnTimeOverride`.
*
* @error Invalid client.
*/
Expand All @@ -150,11 +157,13 @@ native float TF2Util_GetPlayerRespawnTimeOverride(int client);
* Changes the player's respawn time override. See `TF2Util_GetPlayerRespawnTimeOverride` above
* for an explanation of the value.
*
* Setting this value to -1.0 will remove any existing respawn time overrides.
*
* When a player dies, the game will set this value to -1.0 or the RespawnTime value of an
* active trigger_player_respawn_override entity that the player died in, if one exists.
* (This happens *after* the `player_death` event is fired.)
* If the player is not alive, setting this value to -1.0 will remove any existing respawn time
* overrides, and the player will respawn in the next wave they are allowed to spawn in.
*
* If the player is alive, setting this value to one other than -1.0 will cause TF2Utils to
* buffer the value and update the player's respawn time override at some point after they die
* (allowing plugins to set a respawn time override while the player is alive or during a
* `player_death` event hook).
*
* @error Invalid client.
*/
Expand Down
21 changes: 20 additions & 1 deletion scripting/tf2utils.sp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ Address offs_CTFPlayer_aObjects;
Address offs_CTFPlayer_aHealers;
any offs_CTFPlayer_flRespawnTimeOverride;

float g_flRespawnTimeOverride[MAXPLAYERS + 1] = { -1.0, ... };

Address offs_CTFPlayer_hMyWearables;

Address offs_CTFPlayerShared_flBurnDuration;
Expand Down Expand Up @@ -279,6 +281,7 @@ public void OnMapStart() {

public void OnClientPutInServer(int client) {
g_bDeferredSpeedUpdate[client] = false;
g_flRespawnTimeOverride[client] = -1.0;

SDKHook(client, SDKHook_PreThinkPost, OnPreThinkPost);
}
Expand All @@ -287,6 +290,11 @@ void OnPreThinkPost(int client) {
if (g_bDeferredSpeedUpdate[client]) {
ForceSpeedUpdate(client);
}

if (!IsPlayerAlive(client) && g_flRespawnTimeOverride[client] != -1.0) {
SetPlayerRespawnTimeOverrideInternal(client, g_flRespawnTimeOverride[client]);
g_flRespawnTimeOverride[client] = -1.0;
}
}

// force speed update; any previous deferred calls are now fulfilled
Expand Down Expand Up @@ -362,6 +370,7 @@ int Native_GetMaxHealthBoost(Handle plugin, int nParams) {
bIgnoreAttributes, bIgnoreOverheal);
}

// void(int client, int wearable);
int Native_EquipPlayerWearable(Handle plugin, int numParams) {
int client = GetNativeCell(1);
if (client < 1 || client > MaxClients || !IsClientInGame(client)) {
Expand Down Expand Up @@ -684,7 +693,13 @@ any Native_SetPlayerRespawnTimeOverride(Handle plugin, int numParams) {
if (client < 1 || client > MaxClients || !IsClientInGame(client)) {
ThrowNativeError(SP_ERROR_NATIVE, "Client index %d is invalid", client);
}
SetEntDataFloat(client, offs_CTFPlayer_flRespawnTimeOverride, time);

if (!IsPlayerAlive(client)) {
SetPlayerRespawnTimeOverrideInternal(client, time);
g_flRespawnTimeOverride[client] = -1.0;
} else {
g_flRespawnTimeOverride[client] = time;
}
return;
}

Expand All @@ -704,6 +719,10 @@ bool IsEntityWearable(int entity) {
return SDKCall(g_SDKCallIsEntityWearable, entity);
}

static void SetPlayerRespawnTimeOverrideInternal(int client, float time) {
SetEntDataFloat(client, offs_CTFPlayer_flRespawnTimeOverride, time);
}

static Address GetConditionData(int client, TFCond cond) {
Address pCondMemory = DereferencePointer(GetEntityAddress(client)
+ view_as<Address>(FindSendPropInfo("CTFPlayer", "m_Shared"))
Expand Down

0 comments on commit 03fa5f7

Please sign in to comment.