From 6b7803d46ef52b79bdf5d92a6c8874c91e35d40a Mon Sep 17 00:00:00 2001 From: Marisa Kirisame Date: Tue, 8 Sep 2026 21:14:42 +0100 Subject: [PATCH] Allow USE anywhere to activate entWatch items --- entWatch4/scripting/entWatch-useanywhere.sp | 203 ++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 entWatch4/scripting/entWatch-useanywhere.sp diff --git a/entWatch4/scripting/entWatch-useanywhere.sp b/entWatch4/scripting/entWatch-useanywhere.sp new file mode 100644 index 0000000..7b32af3 --- /dev/null +++ b/entWatch4/scripting/entWatch-useanywhere.sp @@ -0,0 +1,203 @@ +//==================================================================================================== +// +// Name: [entWatch] UseAnywhere +// Author: marisakirisame.net +// Description: Allow the owner of an item to activate it with their USE key anywhere +// +//==================================================================================================== +#include + +#pragma newdecls required + +#include +#include +#include +#include +#include +#include + +/* BOOLS */ +bool g_bDisabled[MAXPLAYERS+1]; + +/* COOKIES */ +Handle g_hCookie_Disabled; + +/* INTEGERS */ +int g_iLastButtons[MAXPLAYERS+1]; +int g_iActivateTick[MAXPLAYERS+1]; +int g_iActivateButton[MAXPLAYERS+1]; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Plugin myinfo = +{ + name = "[entWatch] UseAnywhere", + author = "marisakirisame.net", + description = "Allow the owner of an item to activate it with their USE key anywhere", + version = "4.0.0" +}; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnPluginStart() +{ + g_hCookie_Disabled = RegClientCookie("EW_UseAnywhereDisabled", "", CookieAccess_Private); + + RegConsoleCmd("sm_euseanywhere", Command_ToggleUseAnywhere); + + for (int client = 1; client <= MaxClients; client++) + { + if (!IsClientInGame(client) || IsFakeClient(client)) + continue; + + OnClientPutInServer(client); + + if (AreClientCookiesCached(client)) + OnClientCookiesCached(client); + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientPutInServer(int client) +{ + g_bDisabled[client] = false; + g_iLastButtons[client] = 0; + g_iActivateTick[client] = 0; + g_iActivateButton[client] = INVALID_ENT_REFERENCE; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientCookiesCached(int client) +{ + g_bDisabled[client] = GetClientCookieBool(client, g_hCookie_Disabled); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action Command_ToggleUseAnywhere(int client, int args) +{ + if (!Client_IsValid(client)) + return Plugin_Handled; + + g_bDisabled[client] = !g_bDisabled[client]; + + if (g_bDisabled[client]) + { + SetClientCookieBool(client, g_hCookie_Disabled, true); + + CReplyToCommand(client, "\x07%s[entWatch] \x07%sYou will now have to aim at the item's trigger to use it.", "E01B5D", "F16767"); + return Plugin_Handled; + } + else + { + SetClientCookieBool(client, g_hCookie_Disabled, false); + + CReplyToCommand(client, "\x07%s[entWatch] \x07%sYou can now use your item by pressing your USE key anywhere.", "E01B5D", "F16767"); + return Plugin_Handled; + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: Activate the clients item on +use, without having to aim at its button. +//---------------------------------------------------------------------------------------------------- +public Action OnPlayerRunCmd(int client, int &buttons) +{ + bool bPressed = view_as((buttons & IN_USE) && !(g_iLastButtons[client] & IN_USE)); + + g_iLastButtons[client] = buttons; + + if (!bPressed || g_bDisabled[client] || !IsPlayerAlive(client)) + return Plugin_Continue; + + int button = FindClientItemButton(client); + + if (button == INVALID_ENT_REFERENCE) + return Plugin_Continue; + + // Fires the buttons Use input, which runs the core's SDKHook_Use handler as if the + // client had aimed at it, so every cooldown, restriction and message is handled there. + AcceptEntityInput(button, "Use", client, client); + + // Set after the input, so the press above is not blocked by its own guard. + g_iActivateTick[client] = GetGameTickCount(); + g_iActivateButton[client] = button; + + return Plugin_Continue; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: Ignore the engines own +use if we already fired this button for the client this tick, +// so aiming at the button while pressing USE cannot activate the item twice. +//---------------------------------------------------------------------------------------------------- +public Action EW_OnClientItemCanActivate(int client, int index) +{ + if (g_iActivateTick[client] != GetGameTickCount()) + return Plugin_Continue; + + CItem item = EW_GetItemData(index); + + if (item.bButton && item.iButton == g_iActivateButton[client]) + return Plugin_Handled; + + return Plugin_Continue; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: Get the button of the clients item, but only if they carry exactly one. +//---------------------------------------------------------------------------------------------------- +stock int FindClientItemButton(int client) +{ + int iFound = -1; + + for (int index; index < EW_GetItemCount(); index++) + { + CItem item = EW_GetItemData(index); + + if (!(item.bClient && item.iClient == client)) + continue; + + if (iFound != -1) + return INVALID_ENT_REFERENCE; + + iFound = index; + } + + if (iFound != -1) + { + CItem itemFound = EW_GetItemData(iFound); + + if (itemFound.bButton && Entity_IsValid(itemFound.iButton)) + return itemFound.iButton; + } + + return INVALID_ENT_REFERENCE; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +stock void SetClientCookieBool(int client, Handle hCookie, bool value) +{ + char sValue[32]; + IntToString(view_as(value), sValue, sizeof(sValue)); + + SetClientCookie(client, hCookie, sValue); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +stock bool GetClientCookieBool(int client, Handle hCookie) +{ + char sValue[32]; + GetClientCookie(client, hCookie, sValue, sizeof(sValue)); + + return view_as(StringToInt(sValue)); +}