Skip to content

Commit

Permalink
Add sm_friendlyfire_avoidteammates convar
Browse files Browse the repository at this point in the history
Resolves #9
  • Loading branch information
Mikusch committed Mar 5, 2024
1 parent 0fdb02a commit edc2dbb
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 39 deletions.
3 changes: 2 additions & 1 deletion addons/sourcemod/scripting/friendlyfire.sp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include <tf2_stocks>
#include <tf2utils>

#define PLUGIN_VERSION "1.2.2"
#define PLUGIN_VERSION "1.2.3"

#define TICK_NEVER_THINK -1.0
#define TF_CUSTOM_NONE 0
Expand Down Expand Up @@ -76,6 +76,7 @@ enum

ConVar mp_friendlyfire;
ConVar sm_friendlyfire_medic_allow_healing;
ConVar sm_friendlyfire_avoidteammates;

bool g_isEnabled;
bool g_isMapRunning;
Expand Down
130 changes: 92 additions & 38 deletions addons/sourcemod/scripting/friendlyfire/convars.sp
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,23 @@ enum struct ConVarData
char name[COMMAND_MAX_LENGTH];
char value[COMMAND_MAX_LENGTH];
char initialValue[COMMAND_MAX_LENGTH];
bool enforce;
ConVar relatedConVar;
}

static StringMap g_conVars;
static ArrayList g_conVars;

void ConVars_Initialize()
{
g_conVars = new StringMap();
g_conVars = new ArrayList(sizeof(ConVarData));

CreateConVar("sm_friendlyfire_version", PLUGIN_VERSION, "Plugin version.", FCVAR_SPONLY | FCVAR_REPLICATED | FCVAR_NOTIFY | FCVAR_DONTRECORD);
sm_friendlyfire_medic_allow_healing = CreateConVar("sm_friendlyfire_medic_allow_healing", "0", "Whether Medics are allowed to heal teammates during friendly fire.", _, true, 0.0, true, 1.0);
sm_friendlyfire_avoidteammates = CreateConVar("sm_friendlyfire_avoidteammates", "0", "Controls how teammates interact when colliding.\n 0: Teammates block each other\n 1: Teammates pass through each other, but push each other away", _, true, 0.0, true, 1.0);

mp_friendlyfire = FindConVar("mp_friendlyfire");
mp_friendlyfire.AddChangeHook(ConVarChanged_FriendlyFire);

ConVars_AddConVar("tf_avoidteammates", "0");
ConVars_AddConVar("tf_avoidteammates", _, sm_friendlyfire_avoidteammates);
ConVars_AddConVar("tf_spawn_glows_duration", "0");
}

Expand All @@ -55,50 +56,73 @@ void ConVars_Toggle(bool enable)
mp_friendlyfire.RemoveChangeHook(ConVarChanged_FriendlyFire);
}

StringMapSnapshot snapshot = g_conVars.Snapshot();
for (int i = 0; i < snapshot.Length; i++)
for (int i = 0; i < g_conVars.Length; i++)
{
int size = snapshot.KeyBufferSize(i);
char[] key = new char[size];
snapshot.GetKey(i, key, size);

if (enable)
ConVars_Enable(key);
else
ConVars_Disable(key);
ConVarData data;
if (g_conVars.GetArray(i, data))
{
if (enable)
{
ConVars_Enable(data.name);
}
else
{
ConVars_Disable(data.name);
}
}
}
delete snapshot;
}

static void ConVars_AddConVar(const char[] name, const char[] value, bool enforce = true)
static void ConVars_AddConVar(const char[] name, const char[] value = "", ConVar relatedConVar = null)
{
ConVar convar = FindConVar(name);
if (convar)
if (!convar)
{
// Store ConVar information
ConVarData info;
strcopy(info.name, sizeof(info.name), name);
strcopy(info.value, sizeof(info.value), value);
info.enforce = enforce;

g_conVars.SetArray(name, info, sizeof(info));
LogError("Failed to find convar with name %s", name);
return;
}
else

if (!value[0] && !relatedConVar)
{
LogError("Failed to find convar with name %s", name);
LogError("Invalid data for convar with name %s", name);
return;
}

ConVarData data;
strcopy(data.name, sizeof(data.name), name);
strcopy(data.value, sizeof(data.value), value);
data.relatedConVar = relatedConVar;

g_conVars.PushArray(data);
}

static void ConVars_Enable(const char[] name)
{
int index = g_conVars.FindString(name, ConVarData::name);
if (index == -1)
return;

ConVarData data;
if (g_conVars.GetArray(name, data, sizeof(data)))
if (g_conVars.GetArray(index, data))
{
ConVar convar = FindConVar(data.name);
if (!convar)
return;

// Store the current value so we can later reset the ConVar to it
// Store the current value so we can reset the convar on disable
convar.GetString(data.initialValue, sizeof(data.initialValue));
g_conVars.SetArray(name, data, sizeof(data));

// Copy the value from the setting convar if it isn't set
if (!data.value[0] && data.relatedConVar)
{
char value[COMMAND_MAX_LENGTH];
data.relatedConVar.GetString(value, sizeof(value));
strcopy(data.value, sizeof(data.value), value);

data.relatedConVar.AddChangeHook(OnRelatedConVarChanged);
}

g_conVars.SetArray(index, data);

// Update the current value
convar.SetString(data.value);
Expand All @@ -108,16 +132,23 @@ static void ConVars_Enable(const char[] name)

static void ConVars_Disable(const char[] name)
{
int index = g_conVars.FindString(name, ConVarData::name);
if (index == -1)
return;

ConVarData data;
if (g_conVars.GetArray(name, data, sizeof(data)))
if (g_conVars.GetArray(index, data))
{
ConVar convar = FindConVar(data.name);
if (!convar)
return;

g_conVars.SetArray(name, data, sizeof(data));

// Restore the convar value
// Restore the old convar value
convar.RemoveChangeHook(OnConVarChanged);
convar.SetString(data.initialValue);

if (data.relatedConVar)
data.relatedConVar.RemoveChangeHook(OnRelatedConVarChanged);
}
}

Expand All @@ -126,21 +157,44 @@ static void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] n
char name[COMMAND_MAX_LENGTH];
convar.GetName(name, sizeof(name));

int index = g_conVars.FindString(name, ConVarData::name);
if (index == -1)
return;

ConVarData data;
if (g_conVars.GetArray(name, data, sizeof(data)))
if (g_conVars.GetArray(index, data))
{
if (!StrEqual(newValue, data.value))
{
// Update value to reset
strcopy(data.initialValue, sizeof(data.initialValue), newValue);
g_conVars.SetArray(name, data, sizeof(data));
g_conVars.SetArray(index, data);

// Restore our value if needed
if (data.enforce)
convar.SetString(data.value);
// Restore our desired value
convar.SetString(oldValue);
}
}
}

static void OnRelatedConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue)
{
int index = g_conVars.FindValue(convar, ConVarData::relatedConVar);
if (index == -1)
return;

ConVarData data;
if (g_conVars.GetArray(index, data))
{
ConVar actualConVar = FindConVar(data.name);
if (!actualConVar)
return;

actualConVar.RemoveChangeHook(OnConVarChanged);
actualConVar.SetString(newValue);
actualConVar.AddChangeHook(OnConVarChanged);
}
}

static void ConVarChanged_FriendlyFire(ConVar convar, const char[] oldValue, const char[] newValue)
{
if (g_isEnabled != convar.BoolValue)
Expand Down

0 comments on commit edc2dbb

Please sign in to comment.