Skip to content

Commit

Permalink
New Plugin: L4D Auto Mod
Browse files Browse the repository at this point in the history
  • Loading branch information
caxanga334 committed Jun 23, 2024
1 parent 10134f6 commit 190c855
Show file tree
Hide file tree
Showing 12 changed files with 522 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .github/workflows/build_plugins.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ jobs:
rsync -rv ${{ github.workspace }}/sourcefiles/plugins/discordstatus_v2/scripting/* ${{ env.BUILD_PATH }}/
rsync -rv ${{ github.workspace }}/sourcefiles/plugins/tf_mvm_credits/scripting/* ${{ env.BUILD_PATH }}/
rsync -rv ${{ github.workspace }}/sourcefiles/plugins/autorecorder/scripting/* ${{ env.BUILD_PATH }}/
rsync -rv ${{ github.workspace }}/sourcefiles/plugins/l4d_automod/scripting/* ${{ env.BUILD_PATH }}/
cp ${{ github.workspace }}/sourcefiles/source/connectlog.sp ${{ env.BUILD_PATH }}/
cp ${{ github.workspace }}/sourcefiles/source/l4d_antiearlyvote.sp ${{ env.BUILD_PATH }}/
cp ${{ github.workspace }}/sourcefiles/source/sessionbans.sp ${{ env.BUILD_PATH }}/
Expand All @@ -151,6 +152,8 @@ jobs:
- name: Move Additional Files to Package Directory
run: |
rsync -rv ${{ github.workspace }}/sourcefiles/plugins/discordstatus_v2/configs/* ${{ env.CONFIGS_PATH }}/
rsync -rv ${{ github.workspace }}/sourcefiles/plugins/l4d_automod/configs/* ${{ env.CONFIGS_PATH }}/
rsync -rv ${{ github.workspace }}/sourcefiles/plugins/l4d_automod/translations/* ${{ env.LOC_PATH }}/
- name: Fetch Short SHA
uses: benjlevesque/[email protected]
Expand Down
2 changes: 1 addition & 1 deletion plugins/discordstatus_v2/scripting/discord_serverstatus.sp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#pragma newdecls required
#pragma semicolon 1

#define PLUGIN_VERSION "1.1.9"
#define PLUGIN_VERSION "1.1.10"

bool g_started; // Has the server started?
bool g_hasip;
Expand Down
14 changes: 14 additions & 0 deletions plugins/discordstatus_v2/scripting/serverstatus/messages.sp
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,20 @@ void SendMessage_L4D_OnNativeVote(int client, const char[] issue, const char[] o
EmbedField field3 = new EmbedField("Option", voteoption, true);
embed1.AddField(field3);

#if defined _stvmngr_included

if (g_sourcetvmanager && SourceTV_IsRecording())
{
SourceTV_GetDemoFileName(buffer, sizeof(buffer));
EmbedField field4 = new EmbedField("Demo File", buffer, false);
embed1.AddField(field4);
Formatex(buffer, sizeof(buffer), "%i", SourceTV_GetRecordingTick());
EmbedField field5 = new EmbedField("Tick", buffer, false);
embed1.AddField(field5);
}

#endif

webhook.AddEmbed(embed1);

Config_GetWebHookURL("SourceBans", cfg_NativeVotes.key, s_webhook_url, sizeof(s_webhook_url));
Expand Down
4 changes: 4 additions & 0 deletions plugins/l4d_automod/README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Left 4 Dead 2 Auto Moderator
=======

A very basic auto moderator for Left 4 Dead 2 servers.
27 changes: 27 additions & 0 deletions plugins/l4d_automod/configs/l4d_automod.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"automod"
{
// Plugin actions:
// 0 - log only
// 1 - warn admins on the server
// 2 - public notice (print a public message on chat)
// 3 - kill the player if applicable
// 4 - kick the player
// 5 - apply a local ban (ban via the engine's built in ban system)
// 6 - apply a ban via a ban management system (IE: SourceBans). Fallbacks to local bans if not available

"settings"
{
// ban time in minutes
"default_ban_length" "120"
// Action to take on excessive friendly fire events
"friendlyfire_action" "0"
// If a player deals this amount of FF damage in a time period, take action
"friendlyfire_limit" "150"
// If more than N seconds have passed since the last FF damage, reset the total damage dealt
"friendlyfire_time" "10.0"
// Ignore friendly fire damage dealt against bots
"friendlyfire_ignore_bots" "no"
// Ignore fire damage (IE: molotovs)
"friendlyfire_ignore_fire" "no"
}
}
143 changes: 143 additions & 0 deletions plugins/l4d_automod/scripting/l4d_automod.sp
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#include <sourcemod>
#include <left4dhooks>
#include <sdkhooks>

#undef REQUIRE_PLUGIN
#tryinclude <sourcebanspp>

#undef REQUIRE_EXTENSIONS
#tryinclude <sourcetvmanager>

#define PLUGIN_VERSION "1.0.0"

public Plugin myinfo =
{
name = "[L4D2] Auto Moderator",
author = "caxanga334",
description = "A very basic auto moderator for Left 4 Dead 2 servers.",
version = PLUGIN_VERSION,
url = "https://github.com/caxanga334/sm-plugins"
};

#if defined _stvmngr_included
bool g_sourcetvmanager;
#endif

#if defined _sourcebanspp_included
bool g_sourcebans;
#endif

#include "l4d_automod/logger.sp"
#include "l4d_automod/config.sp"
#include "l4d_automod/data.sp"
#include "l4d_automod/action.sp"

public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
EngineVersion engine = GetEngineVersion();

if (engine == Engine_Left4Dead || engine == Engine_Left4Dead2)
{
return APLRes_Success;
}

strcopy(error, err_max, "This plugins is for Left 4 Dead/ 2 only!");
return APLRes_Failure;
}

public void OnLibraryAdded(const char[] name)
{
#if defined _sourcebanspp_included
if (strcmp(name, "sourcebans++") == 0)
{
g_sourcebans = true;
}
#endif
}

public void OnLibraryRemoved(const char[] name)
{
#if defined _sourcebanspp_included
if (strcmp(name, "sourcebans++") == 0)
{
g_sourcebans = false;
}
#endif
}

public void OnPluginStart()
{
LoadTranslations("common.phrases.txt");
LoadTranslations("l4d_automod.phrases.txt");

HookEvent("player_hurt_concise", EV_PlayerHurt, EventHookMode_Post);

Config_Init();
}

public void OnAllPluginsLoaded()
{
#if defined _stvmngr_included
g_sourcetvmanager = LibraryExists("sourcetvmanager");
#endif
}

public void OnClientPutInServer(int client)
{
Player player = Player(client);
player.Reset();
}

public void OnMapStart()
{
Logger_BuildFilePath();
Config_Load();
}

void EV_PlayerHurt(Event event, const char[] name, bool dontBroadcast)
{
Player victim = Player(GetClientOfUserId(event.GetInt("userid")));
Player attacker = Player(event.GetInt("attackerentid"));

if (!victim.IsValid() || attacker.IsValid())
{
// both victim and attacker must be a player entity and must be in-game
return;
}

if (g_cfg.ff_ignore_bots && IsFakeClient(victim.index))
{
// ignore bots enabled
return;
}

// We only care about survivors
if (L4D_GetClientTeam(victim.index) != L4DTeam_Survivor)
{
return;
}

// Not friendly fire
if (GetClientTeam(victim.index) != GetClientTeam(attacker.index))
{
return;
}

int dmgtype = event.GetInt("type");

if (g_cfg.ff_ignore_fire && (dmgtype & DMG_BURN) != 0)
{
// ignoring fire (burn) damage
return;
}

int damage = event.GetInt("dmg_health");

if (damage <= 0)
{
return;
}

attacker.OnFriendlyFireDamage(damage);
Action_OnFriendlyFire(attacker, victim);
}
123 changes: 123 additions & 0 deletions plugins/l4d_automod/scripting/l4d_automod/action.sp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@

/**
* prefix - message before the translation token
* token - translation token
*/
void Action_WarnAdmins(const char[] prefix, const char[] token)
{
for (int i = 0; i <= MaxClients; i++)
{
if (IsClientInGame(i) && CheckCommandAccess(i, "sm_ban", ADMFLAG_BAN))
{
PrintToChat(i, "[SM] %s %t", prefix, token);
}
}
}

/**
* prefix - message before the translation token
* token - translation token
*/
void Action_PublicNotice(const char[] prefix, const char[] token)
{
PrintToChatAll("[SM] %s %t", prefix, token);
}

void Action_KillClient(int client, const char[] logmsg)
{
SDKHooks_TakeDamage(client, 0, 0, 50000.0, DMG_FALL, -1);
LogAction(0, client, "%L was killed for %s.", client, logmsg);
}

void Action_KickClient(int client, const char[] logmsg, const char[] kickmsg)
{
KickClient(client, kickmsg);
LogAction(0, client, "%L was kicked for %s.", client, logmsg);
}

void Action_LocalBanClient(int client, int length, const char[] logmsg, const char[] banreason)
{
BanClient(client, length, BANFLAG_AUTO, banreason, banreason, "l4d_automod");
LogAction(0, client, "%L was banned for %s.", client, logmsg);
}

void Action_BanClient(int client, int length, const char[] logmsg, const char[] banreason)
{
#if defined _sourcebanspp_included
if (g_sourcebans)
{
// SB++ is available
SBPP_BanPlayer(0, client, length, banreason);
LogAction(0, client, "%L was banned for %s.", client, logmsg);
}
else
{
// SB++ not available
Action_LocalBanClient(client, length, logmsg, banreason);
return;
}
#else
// Plugin was not compiled with sourcebans++
Action_LocalBanClient(client, length, logmsg, banreason);
#endif
}

void Action_TakeFriendlyFireAction(Player attacker, Player victim)
{
attacker.OnFriendlyFireActionTaken();

Logger_LogFriendlyFire(attacker.index, victim.index);

if (g_cfg.ff_action == ACTION_LOGONLY)
{
return;
}

if (g_cfg.ff_action == ACTION_WARN_ADMINS)
{
char prefix[MAX_NAME_LENGTH];
FormatEx(prefix, sizeof(prefix), "%N", attacker.index);
Action_WarnAdmins(prefix, "Notice_FriendlyFire");
return;
}

if (g_cfg.ff_action == ACTION_PUBLIC_NOTICE)
{
char prefix[MAX_NAME_LENGTH];
FormatEx(prefix, sizeof(prefix), "%N", attacker.index);
Action_PublicNotice(prefix, "Notice_FriendlyFire");
return;
}

if (g_cfg.ff_action == ACTION_KILL)
{
Action_KillClient(attacker.index, "excessive friendly fire damage.")
return;
}

if (g_cfg.ff_action == ACTION_KICK)
{
Action_KickClient(attacker.index, "excessive friendly fire damage.", "Excessive friendly fire.");
return;
}

if (g_cfg.ff_action == ACTION_LOCALBAN)
{
Action_LocalBanClient(attacker.index, g_cfg.default_ban_length, "excessive friendly fire damage.", "Excessive friendly fire.");
return;
}

if (g_cfg.ff_action == ACTION_BAN)
{
Action_BanClient(attacker.index, g_cfg.default_ban_length, "excessive friendly fire damage.", "Excessive friendly fire.");
return;
}
}

void Action_OnFriendlyFire(Player attacker, Player victim)
{
if (attacker.GetAccumulatedFriendlyFireDamage() > g_cfg.max_ff_damage)
{
Action_TakeFriendlyFireAction(attacker, victim);
}
}
Loading

0 comments on commit 190c855

Please sign in to comment.