sm-plugins/entWatch4/scripting/entWatch-core.sp

788 lines
22 KiB
SourcePawn

//====================================================================================================
//
// Name: [entWatch] Core
// Author: zaCade & Prometheum
// Description: Handle the core functions of [entWatch]
//
//====================================================================================================
#include <multicolors>
#pragma newdecls required
#include <sourcemod>
#include <sdkhooks>
#include <sdktools>
#include <entWatch_core>
#include <entWatch_helpers>
/* BOOLS */
bool g_bLate;
bool g_bLoaded;
bool g_bLoadPending;
bool g_bIntermission;
/* ARRAYS */
ArrayList g_hArray_Items;
ArrayList g_hArray_Configs;
/* FORWARDS */
Handle g_hFwd_OnClientItemDrop;
Handle g_hFwd_OnClientItemDeath;
Handle g_hFwd_OnClientItemPickup;
Handle g_hFwd_OnClientItemActivate;
Handle g_hFwd_OnClientItemDisconnect;
/* HOOKS */
Handle g_hFwd_OnClientItemCanPickup;
Handle g_hFwd_OnClientItemCanActivate;
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public Plugin myinfo =
{
name = "[entWatch] Core",
author = "zaCade & Prometheum",
description = "Handle the core functions of [entWatch]",
version = "4.0.0"
};
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public APLRes AskPluginLoad2(Handle hMyself, bool bLate, char[] sError, int errorSize)
{
g_bLate = bLate;
CreateNative("EW_GetItemCount", Native_GetItemCount);
CreateNative("EW_GetItemData", Native_GetItemData);
CreateNative("EW_ClientHasItem", Native_ClientHasItem);
RegPluginLibrary("entWatch-core");
return APLRes_Success;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnPluginStart()
{
g_hFwd_OnClientItemDrop = CreateGlobalForward("EW_OnClientItemDrop", ET_Ignore, Param_Cell, Param_Cell);
g_hFwd_OnClientItemDeath = CreateGlobalForward("EW_OnClientItemDeath", ET_Ignore, Param_Cell, Param_Cell);
g_hFwd_OnClientItemPickup = CreateGlobalForward("EW_OnClientItemPickup", ET_Ignore, Param_Cell, Param_Cell);
g_hFwd_OnClientItemActivate = CreateGlobalForward("EW_OnClientItemActivate", ET_Ignore, Param_Cell, Param_Cell);
g_hFwd_OnClientItemDisconnect = CreateGlobalForward("EW_OnClientItemDisconnect", ET_Ignore, Param_Cell, Param_Cell);
g_hFwd_OnClientItemCanPickup = CreateGlobalForward("EW_OnClientItemCanPickup", ET_Hook, Param_Cell, Param_Cell);
g_hFwd_OnClientItemCanActivate = CreateGlobalForward("EW_OnClientItemCanActivate", ET_Hook, Param_Cell, Param_Cell);
g_hArray_Items = new ArrayList();
g_hArray_Configs = new ArrayList();
RegAdminCmd("sm_ereload", Command_ReloadConfig, ADMFLAG_BAN);
HookEvent("player_death", OnClientDeath);
HookEvent("round_start", OnRoundStart);
HookEvent("round_end", OnRoundEnd);
if (g_bLate)
{
for (int client = 1; client <= MaxClients; client++)
{
if (!IsClientInGame(client) || IsFakeClient(client))
continue;
SDKHook(client, SDKHook_WeaponEquipPost, OnWeaponPickup);
SDKHook(client, SDKHook_WeaponDropPost, OnWeaponDrop);
SDKHook(client, SDKHook_WeaponCanUse, OnWeaponTouch);
}
}
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public Action Command_ReloadConfig(int client, int args)
{
if (g_bLoaded)
{
g_bLoadPending = !g_bLoadPending;
if (g_bLoadPending)
{
CReplyToCommand(client, "\x07%s[entWatch] \x07%sConfig load pending, loading at roundstart.", "E01B5D", "F16767");
return Plugin_Handled;
}
else
{
CReplyToCommand(client, "\x07%s[entWatch] \x07%sPending config load cancelled!", "E01B5D", "F16767");
return Plugin_Handled;
}
}
else
{
g_bLoaded = LoadConfig();
if (g_bLoaded)
{
CReplyToCommand(client, "\x07%s[entWatch] \x07%sConfig load successful.", "E01B5D", "F16767");
return Plugin_Handled;
}
else
{
CReplyToCommand(client, "\x07%s[entWatch] \x07%sConfig load failed!", "E01B5D", "F16767");
return Plugin_Handled;
}
}
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnMapStart()
{
g_bLoaded = LoadConfig();
g_bLoadPending = false;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
stock bool LoadConfig()
{
g_hArray_Items.Clear();
g_hArray_Configs.Clear();
char sCurrentMap[128];
GetCurrentMap(sCurrentMap, sizeof(sCurrentMap));
String_ToLower(sCurrentMap, sCurrentMap, sizeof(sCurrentMap));
char sFilePathDefault[PLATFORM_MAX_PATH];
char sFilePathOverride[PLATFORM_MAX_PATH];
BuildPath(Path_SM, sFilePathDefault, sizeof(sFilePathDefault), "configs/entwatch/%s.cfg", sCurrentMap);
BuildPath(Path_SM, sFilePathOverride, sizeof(sFilePathOverride), "configs/entwatch/%s.override.cfg", sCurrentMap);
KeyValues hConfig = new KeyValues("items");
if (FileExists(sFilePathOverride))
{
if (!hConfig.ImportFromFile(sFilePathOverride))
{
LogMessage("Unable to load config \"%s\"!", sFilePathOverride);
delete hConfig;
return false;
}
else LogMessage("Loaded config \"%s\"", sFilePathOverride);
}
else
{
if (!hConfig.ImportFromFile(sFilePathDefault))
{
LogMessage("Unable to load config \"%s\"!", sFilePathDefault);
delete hConfig;
return false;
}
else LogMessage("Loaded config \"%s\"", sFilePathDefault);
}
if (hConfig.GotoFirstSubKey())
{
int iConfigID;
do
{
CConfig config = new CConfig();
char sName[64], sShort[64], sColor[64], sFilter[64];
hConfig.GetString("name", sName, sizeof(sName));
hConfig.GetString("short", sShort, sizeof(sShort));
hConfig.GetString("color", sColor, sizeof(sColor));
hConfig.GetString("filter", sFilter, sizeof(sFilter));
config.SetName(sName);
config.SetShort(sShort);
config.SetColor(sColor);
config.SetFilter(sFilter);
config.iConfigID = iConfigID++;
config.iWeaponID = hConfig.GetNum("weaponid");
config.iButtonID = hConfig.GetNum("buttonid");
config.iTriggerID = hConfig.GetNum("triggerid");
config.iDisplay = hConfig.GetNum("display");
config.iSlot = hConfig.GetNum("slot");
config.iMode = hConfig.GetNum("mode");
config.iMaxUses = hConfig.GetNum("maxuses");
config.iCooldown = hConfig.GetNum("cooldown");
g_hArray_Configs.Push(config);
}
while (hConfig.GotoNextKey());
}
if (g_bLate)
{
int entity = INVALID_ENT_REFERENCE;
while ((entity = FindEntityByClassname(entity, "*")) != INVALID_ENT_REFERENCE)
{
char sClassname[64];
if(GetEntityClassname(entity, sClassname, sizeof(sClassname)))
OnEntitySpawned(entity, sClassname);
}
}
delete hConfig;
return true;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnRoundStart(Event hEvent, const char[] sEvent, bool bDontBroadcast)
{
if (g_bLoadPending)
{
g_bLoaded = LoadConfig();
if (g_bLoaded)
{
CPrintToChatAll("\x07%s[entWatch] \x07%sPending config load successfull.", "E01B5D", "F16767");
}
}
g_bLoadPending = false;
g_bIntermission = false;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnRoundEnd(Event hEvent, const char[] sEvent, bool bDontBroadcast)
{
if (g_hArray_Items.Length)
g_hArray_Items.Clear();
g_bIntermission = true;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnEntitySpawned(int entity, const char[] classname)
{
if (Entity_IsValid(entity) && g_hArray_Configs.Length)
{
int iHammerID = Entity_GetHammerID(entity);
for (int index; index < g_hArray_Configs.Length; index++)
{
CConfig config = g_hArray_Configs.Get(index);
if (config.iWeaponID && config.iWeaponID == iHammerID)
{
if (!RegisterExistingItem(config, entity, REGISTER_WEAPON))
{
CItem item = new CItem(config);
if (RegisterItemEntity(item, entity, REGISTER_WEAPON))
{
g_hArray_Items.Push(item);
SortADTArrayCustom(g_hArray_Items, SortItemsArray);
}
}
}
else if (config.iButtonID && config.iButtonID == iHammerID)
{
if (!RegisterExistingItem(config, entity, REGISTER_BUTTON))
{
CItem item = new CItem(config);
if (RegisterItemEntity(item, entity, REGISTER_BUTTON))
{
g_hArray_Items.Push(item);
SortADTArrayCustom(g_hArray_Items, SortItemsArray);
}
}
}
else if (config.iTriggerID && config.iTriggerID == iHammerID)
{
if (!RegisterExistingItem(config, entity, REGISTER_TRIGGER))
{
CItem item = new CItem(config);
if (RegisterItemEntity(item, entity, REGISTER_TRIGGER))
{
g_hArray_Items.Push(item);
SortADTArrayCustom(g_hArray_Items, SortItemsArray);
}
}
}
}
}
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
stock bool RegisterExistingItem(CConfig config, int entity, int type)
{
if (Entity_IsValid(entity) && g_hArray_Items.Length)
{
for (int index; index < g_hArray_Items.Length; index++)
{
CItem item = g_hArray_Items.Get(index);
if (item.dConfig == config)
{
if (RegisterItemEntity(item, entity, type))
return true;
}
}
}
return false;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
stock bool RegisterItemEntity(CItem item, int entity, int type)
{
if (Entity_IsValid(entity))
{
int iOwner = Entity_GetOwner(entity);
int iParent = Entity_GetParent(entity);
switch(type)
{
case REGISTER_WEAPON:
{
if (!item.bWeapon && (iOwner == INVALID_ENT_REFERENCE))
{
item.iWeapon = entity;
return true;
}
}
case REGISTER_BUTTON:
{
if (!item.bButton && (iParent == INVALID_ENT_REFERENCE || (item.bWeapon && iParent == item.iWeapon)))
{
SDKHook(entity, SDKHook_Use, OnButtonPress);
item.iButton = entity;
return true;
}
}
case REGISTER_TRIGGER:
{
if (!item.bTrigger && (iParent == INVALID_ENT_REFERENCE || (item.bWeapon && iParent == item.iWeapon)))
{
SDKHook(entity, SDKHook_StartTouch, OnTriggerTouch);
SDKHook(entity, SDKHook_EndTouch, OnTriggerTouch);
SDKHook(entity, SDKHook_Touch, OnTriggerTouch);
item.iTrigger = entity;
return true;
}
}
}
}
return false;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnEntityDestroyed(int entity)
{
if (Entity_IsValid(entity) && g_hArray_Items.Length)
{
for (int index; index < g_hArray_Items.Length; index++)
{
CItem item = g_hArray_Items.Get(index);
if (item.bWeapon && item.iWeapon == entity)
{
item.iClient = INVALID_ENT_REFERENCE;
item.iWeapon = INVALID_ENT_REFERENCE;
return;
}
else if (item.bButton && item.iButton == entity)
{
item.iButton = INVALID_ENT_REFERENCE;
return;
}
else if (item.bTrigger && item.iTrigger == entity)
{
item.iTrigger = INVALID_ENT_REFERENCE;
return;
}
}
}
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public int SortItemsArray(int index1, int index2, Handle array, Handle hndl)
{
CConfig config1 = view_as<CItem>(g_hArray_Items.Get(index1)).dConfig;
CConfig config2 = view_as<CItem>(g_hArray_Items.Get(index2)).dConfig;
if (config1.iConfigID < config2.iConfigID) return -1;
if (config1.iConfigID > config2.iConfigID) return 1;
return 0;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnClientPutInServer(int client)
{
if (!IsFakeClient(client))
{
SDKHook(client, SDKHook_WeaponEquipPost, OnWeaponPickup);
SDKHook(client, SDKHook_WeaponDropPost, OnWeaponDrop);
SDKHook(client, SDKHook_WeaponCanUse, OnWeaponTouch);
}
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnClientDisconnect(int client)
{
if (!IsFakeClient(client) && g_hArray_Items.Length)
{
for (int index; index < g_hArray_Items.Length; index++)
{
CItem item = g_hArray_Items.Get(index);
if (item.bClient && item.iClient == client)
{
if (item.bWeapon && !(item.dConfig.iSlot == SLOT_NONE || item.dConfig.iSlot == SLOT_KNIFE))
{
SDKHooks_DropWeapon(item.iClient, item.iWeapon, NULL_VECTOR, NULL_VECTOR);
}
item.iClient = INVALID_ENT_REFERENCE;
Call_StartForward(g_hFwd_OnClientItemDisconnect);
Call_PushCell(client);
Call_PushCell(index);
Call_Finish();
}
}
}
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnClientDeath(Event hEvent, const char[] sEvent, bool bDontBroadcast)
{
int client = GetClientOfUserId(hEvent.GetInt("userid"));
if (Client_IsValid(client) && !IsFakeClient(client) && g_hArray_Items.Length)
{
for (int index; index < g_hArray_Items.Length; index++)
{
CItem item = g_hArray_Items.Get(index);
if (item.bClient && item.iClient == client)
{
if (item.bWeapon && !(item.dConfig.iSlot == SLOT_NONE || item.dConfig.iSlot == SLOT_KNIFE))
{
SDKHooks_DropWeapon(item.iClient, item.iWeapon, NULL_VECTOR, NULL_VECTOR);
}
item.iClient = INVALID_ENT_REFERENCE;
Call_StartForward(g_hFwd_OnClientItemDeath);
Call_PushCell(client);
Call_PushCell(index);
Call_Finish();
}
}
}
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public Action OnWeaponPickup(int client, int weapon)
{
if (Client_IsValid(client) && Entity_IsValid(weapon) && g_hArray_Items.Length)
{
for (int index; index < g_hArray_Items.Length; index++)
{
CItem item = g_hArray_Items.Get(index);
if (item.bWeapon && item.iWeapon == weapon)
{
item.iClient = client;
Call_StartForward(g_hFwd_OnClientItemPickup);
Call_PushCell(client);
Call_PushCell(index);
Call_Finish();
return Plugin_Handled;
}
}
}
return Plugin_Handled;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public Action OnWeaponDrop(int client, int weapon)
{
if (Client_IsValid(client) && Entity_IsValid(weapon) && g_hArray_Items.Length)
{
for (int index; index < g_hArray_Items.Length; index++)
{
CItem item = g_hArray_Items.Get(index);
if (item.bWeapon && item.iWeapon == weapon)
{
item.iClient = INVALID_ENT_REFERENCE;
Call_StartForward(g_hFwd_OnClientItemDrop);
Call_PushCell(client);
Call_PushCell(index);
Call_Finish();
return Plugin_Handled;
}
}
}
return Plugin_Handled;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public Action OnButtonPress(int button, int client)
{
if (Client_IsValid(client) && Entity_IsValid(button) && g_hArray_Items.Length)
{
if (HasEntProp(button, Prop_Data, "m_bLocked") &&
GetEntProp(button, Prop_Data, "m_bLocked"))
return Plugin_Handled;
for (int index; index < g_hArray_Items.Length; index++)
{
CItem item = g_hArray_Items.Get(index);
if ((item.bButton && item.iButton == button) &&
(item.bClient && item.iClient == client))
{
Action aResult;
Call_StartForward(g_hFwd_OnClientItemCanActivate);
Call_PushCell(client);
Call_PushCell(index);
Call_Finish(aResult);
switch(aResult)
{
case Plugin_Continue, Plugin_Changed:
{
if (HasEntProp(button, Prop_Data, "m_flWait"))
{
if (item.flWait < GetEngineTime())
{
item.flWait = GetEngineTime() + GetEntPropFloat(button, Prop_Data, "m_flWait");
}
else return Plugin_Handled;
}
switch(item.dConfig.iMode)
{
case MODE_COOLDOWN:
{
if (item.flTimeReady < GetEngineTime())
{
item.flTimeReady = GetEngineTime() + item.dConfig.iCooldown;
}
else return Plugin_Handled;
}
case MODE_MAXUSES:
{
if (item.iTimesUsed < item.dConfig.iMaxUses)
{
item.iTimesUsed++;
}
else return Plugin_Handled;
}
case MODE_COOLDOWNMAXUSES:
{
if (item.flTimeReady < GetEngineTime() && item.iTimesUsed < item.dConfig.iMaxUses)
{
item.flTimeReady = GetEngineTime() + item.dConfig.iCooldown;
item.iTimesUsed++;
}
else return Plugin_Handled;
}
case MODE_COOLDOWNCHARGES:
{
if (item.flTimeReady < GetEngineTime())
{
item.iTimesUsed++;
if (item.iTimesUsed >= item.dConfig.iMaxUses)
{
item.flTimeReady = GetEngineTime() + item.dConfig.iCooldown;
item.iTimesUsed = 0;
}
}
else return Plugin_Handled;
}
}
char sFilter[64];
if (item.dConfig.GetFilter(sFilter, sizeof(sFilter)) && sFilter[0])
Entity_SetName(client, sFilter);
Call_StartForward(g_hFwd_OnClientItemActivate);
Call_PushCell(client);
Call_PushCell(index);
Call_Finish();
}
}
return aResult;
}
}
}
return Plugin_Handled;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public Action OnTriggerTouch(int trigger, int client)
{
if (Client_IsValid(client) && Entity_IsValid(trigger) && g_hArray_Items.Length)
{
for (int index; index < g_hArray_Items.Length; index++)
{
CItem item = g_hArray_Items.Get(index);
if (item.bTrigger && item.iTrigger == trigger)
{
if (g_bIntermission)
return Plugin_Handled;
Action aResult;
Call_StartForward(g_hFwd_OnClientItemCanPickup);
Call_PushCell(client);
Call_PushCell(index);
Call_Finish(aResult);
return aResult;
}
}
}
return Plugin_Handled;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public Action OnWeaponTouch(int client, int weapon)
{
if (Client_IsValid(client) && Entity_IsValid(weapon) && g_hArray_Items.Length)
{
for (int index; index < g_hArray_Items.Length; index++)
{
CItem item = g_hArray_Items.Get(index);
if (item.bWeapon && item.iWeapon == weapon)
{
if (g_bIntermission)
return Plugin_Handled;
Action aResult;
Call_StartForward(g_hFwd_OnClientItemCanPickup);
Call_PushCell(client);
Call_PushCell(index);
Call_Finish(aResult);
return aResult;
}
}
}
return Plugin_Continue;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public int Native_GetItemCount(Handle hPlugin, int numParams)
{
return g_hArray_Items.Length;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public int Native_GetItemData(Handle hPlugin, int numParams)
{
int index = GetNativeCell(1);
if ((index < 0) || (index > g_hArray_Items.Length))
{
return ThrowNativeError(SP_ERROR_INDEX, "Item index %d is invalid.", index);
}
return view_as<int>(g_hArray_Items.Get(index));
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public int Native_ClientHasItem(Handle hPlugin, int numParams)
{
int client = GetNativeCell(1);
if(client > MaxClients || client <= 0)
{
return ThrowNativeError(SP_ERROR_NATIVE, "Client is not valid.");
}
if(!IsClientInGame(client))
{
ThrowNativeError(SP_ERROR_NATIVE, "Client is not in game.");
}
for (int index; index < g_hArray_Items.Length; index++)
{
CItem item = g_hArray_Items.Get(index);
if (item.bClient && item.iClient == client)
{
return 1;
}
}
return 0;
}