Skip to content

Commit

Permalink
1.2.5 (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
Katsute authored Mar 31, 2024
1 parent 7fe8308 commit 6968580
Show file tree
Hide file tree
Showing 6 changed files with 337 additions and 303 deletions.
77 changes: 30 additions & 47 deletions addons/sourcemod/scripting/friendlyfire.sp
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,10 @@
#include <tf2_stocks>
#include <tf2utils>

#define PLUGIN_VERSION "1.1.3"
#define PLUGIN_VERSION "1.2.5"

#define TICK_NEVER_THINK -1.0

#define TF_CUSTOM_NONE 0

#define TF_GAMETYPE_ARENA 4

enum
Expand Down Expand Up @@ -78,13 +76,14 @@ enum

ConVar mp_friendlyfire;
ConVar sm_friendlyfire_medic_allow_healing;
ConVar sm_friendlyfire_avoidteammates;

bool g_isEnabled;
bool g_isMapRunning;

#include "friendlyfire/convars.sp"
#include "friendlyfire/data.sp"
#include "friendlyfire/dhooks.sp"
#include "friendlyfire/entity.sp"
#include "friendlyfire/sdkcalls.sp"
#include "friendlyfire/sdkhooks.sp"
#include "friendlyfire/util.sp"
Expand All @@ -102,6 +101,8 @@ public void OnPluginStart()
{
RegPluginLibrary("friendlyfire");

Entity.Initialize();

ConVars_Initialize();
SDKHooks_Initialize();

Expand Down Expand Up @@ -144,51 +145,44 @@ public void OnPluginEnd()
TogglePlugin(false);
}

public void OnClientPutInServer(int client)
{
if (!g_isEnabled)
return;

DHooks_OnClientPutInServer(client);
SDKHooks_OnClientPutInServer(client);
}

public void OnEntityCreated(int entity, const char[] classname)
{
if (!g_isEnabled || !g_isMapRunning)
return;

DHooks_OnEntityCreated(entity, classname);
SDKHooks_OnEntityCreated(entity, classname);
DHooks_HookEntity(entity, classname);
SDKHooks_HookEntity(entity, classname);
}

public void OnEntityDestroyed(int entity)
{
if (!g_isEnabled)
return;

if (!IsValidEntity(entity))
return;
SDKHooks_UnhookEntity(entity);

// If an entity was removed prematurely, reset its owner's team as far back as we need to.
// This can happen with projectiles when they collide with the world, not calling the post-hook.
for (int i = 0; i < Entity(entity).TeamCount; i++)
if (Entity.IsEntityTracked(entity))
{
int owner = FindParentOwnerEntity(entity);
if (owner != -1)
Entity obj = Entity(entity);

// If an entity is removed while it still has a team history, we need to reset its owner's team.
// This can happen if the entity is deleted in-between pre-hook and post-hook callbacks e.g. from a projectile that collided with worldspawn.
for (int i = 0; i < obj.TeamCount; i++)
{
Entity(owner).ResetTeam();
int owner = FindParentOwnerEntity(entity);
if (owner != -1)
obj.ResetTeam();
}
}

Entity(entity).Destroy();
obj.Destroy();
}
}

// public Action TF2_OnPlayerTeleport(int client, int teleporter, bool& result)
// {
// if (!g_isEnabled)
// return Plugin_Continue;

//
// result = IsObjectFriendly(teleporter, client);
// return Plugin_Handled;
// }
Expand All @@ -200,34 +194,23 @@ void TogglePlugin(bool enable)
ConVars_Toggle(enable);
DHooks_Toggle(enable);

if (enable)
int entity = -1;
while ((entity = FindEntityByClassname(entity, "*")) != -1)
{
for (int client = 1; client <= MaxClients; client++)
if (enable)
{
if (!IsClientInGame(client))
char classname[64];
if (!GetEntityClassname(entity, classname, sizeof(classname)))
continue;

OnClientPutInServer(client);
OnEntityCreated(entity, classname);
}

int entity = -1;
while ((entity = FindEntityByClassname(entity, "*")) != -1)
else
{
char classname[64];
if (GetEntityClassname(entity, classname, sizeof(classname)))
{
OnEntityCreated(entity, classname);
}
}
}
else
{
for (int client = 1; client <= MaxClients; client++)
{
if (!IsClientInGame(client))
continue;
SDKHooks_UnhookEntity(entity);

SDKHooks_UnhookClient(client);
if (Entity.IsEntityTracked(entity))
Entity(entity).Destroy();
}
}
}
144 changes: 97 additions & 47 deletions addons/sourcemod/scripting/friendlyfire/convars.sp
Original file line number Diff line number Diff line change
Expand Up @@ -25,80 +25,95 @@ 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");
}

void ConVars_Toggle(bool enable)
{
if (enable)
for (int i = 0; i < g_conVars.Length; i++)
{
mp_friendlyfire.AddChangeHook(ConVarChanged_FriendlyFire);
}
else
{
mp_friendlyfire.RemoveChangeHook(ConVarChanged_FriendlyFire);
}

StringMapSnapshot snapshot = g_conVars.Snapshot();
for (int i = 0; i < snapshot.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);
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 +123,28 @@ static void ConVars_Enable(const char[] name)

static void ConVars_Disable(const char[] name)
{
int index = g_conVars.FindString(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.value[0] = EOS;
data.relatedConVar.RemoveChangeHook(OnRelatedConVarChanged);

g_conVars.SetArray(index, data);
}
}
}

Expand All @@ -126,21 +153,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);
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
Loading

0 comments on commit 6968580

Please sign in to comment.