From 613802344b8fad1f5fd79ad58ab79f81ac6112a3 Mon Sep 17 00:00:00 2001 From: Jackz Date: Wed, 24 Aug 2022 11:00:07 -0500 Subject: [PATCH 1/6] Work on prophunt --- plugins/l4d2_prophunt.smx | Bin 0 -> 8376 bytes scripting/include/prophunt/phcmds.inc | 333 ++++++++++++++++++++ scripting/include/prophunt/phcore.inc | 171 +++++++++++ scripting/include/prophunt/phents.inc | 128 ++++++++ scripting/include/prophunt/phgame.inc | 390 ++++++++++++++++++++++++ scripting/include/prophunt/phtimers.inc | 70 +++++ scripting/l4d2_prophunt.sp | 151 +++++++++ 7 files changed, 1243 insertions(+) create mode 100644 plugins/l4d2_prophunt.smx create mode 100644 scripting/include/prophunt/phcmds.inc create mode 100644 scripting/include/prophunt/phcore.inc create mode 100644 scripting/include/prophunt/phents.inc create mode 100644 scripting/include/prophunt/phgame.inc create mode 100644 scripting/include/prophunt/phtimers.inc create mode 100644 scripting/l4d2_prophunt.sp diff --git a/plugins/l4d2_prophunt.smx b/plugins/l4d2_prophunt.smx new file mode 100644 index 0000000000000000000000000000000000000000..afcdef1a06aa43af88f0348da62657e9e14d9a60 GIT binary patch literal 8376 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 literal 0 HcmV?d00001 diff --git a/scripting/include/prophunt/phcmds.inc b/scripting/include/prophunt/phcmds.inc new file mode 100644 index 0000000..6399ca5 --- /dev/null +++ b/scripting/include/prophunt/phcmds.inc @@ -0,0 +1,333 @@ +#define GAMEMODE_PROP_NAME "phprop" +#define GAMEMODE_BLOCKER_NAME "phblocker" + + + +public Action Command_PropHunt(int client, int args) { + if(!isEnabled) ReplyToCommand(client, "Warn: %s is not active", GAMEMODE_NAME); + if(args > 0) { + char subcmd[32]; + GetCmdArg(1, subcmd, sizeof(subcmd)); + if(StrEqual(subcmd, "r") || StrEqual(subcmd, "reload", false)) { + GetCurrentMap(g_currentMap, sizeof(g_currentMap)); + char arg[4]; + GetCmdArg(2, arg, sizeof(arg)); + if(ReloadMapDB()) { + if(!LoadConfigForMap(g_currentMap)) { + ReplyToCommand(client, "Warn: Map has no config file"); + } + Game.Cleanup(true); + if(arg[0] == 'f') { + InitGamemode(); + } + SetupEntities(Game.Blockers, Game.Props, Game.Portals); + ReplyToCommand(client, "Reloaded map from config"); + } else { + ReplyToCommand(client, "Error occurred while reloading map file"); + } + } else if(StrEqual(subcmd, "set", false)) { + char set[16]; + if(args == 1) { + ReplyToCommand(client, "Current Map Set: \"%s\" (Specify with /gw set )", g_currentSet); + if(validSets.Length == 0) ReplyToCommand(client, "Available Sets: (no map config found)"); + else { + ReplyToCommand(client, "Available Sets: "); + for(int i = 0; i < validSets.Length; i++) { + validSets.GetString(i, set, sizeof(set)); + ReplyToCommand(client, "%d. %s", i + 1, set); + } + } + } else { + GetCmdArg(2, g_currentSet, sizeof(g_currentSet)); + for(int i = 0; i < validSets.Length; i++) { + validSets.GetString(i, set, sizeof(set)); + if(StrEqual(set, g_currentSet)) { + if(!LoadConfigForMap(g_currentMap)) { + ReplyToCommand(client, "Warn: No config entry for %s", g_currentMap); + } + Game.Cleanup(); + SetupEntities(Game.Blockers, Game.Props, Game.Portals); + PrintToChatAll("[PropHunt] Map set has been changed to \"%s\"", g_currentSet); + return Plugin_Handled; + } + } + ReplyToCommand(client, "Warning: Set was not found, use /gw r to force load."); + } + } else if(StrEqual(subcmd, "toggle")) { + char type[32]; + GetCmdArg(2, type, sizeof(type)); + bool doAll = StrEqual(type, "all"); + bool isUnknown = true; + + if(doAll || StrEqual(type, "blockers", false)) { + if(Game.Blockers) { + EntFire(GAMEMODE_BLOCKER_NAME, "Disable"); + ReplyToCommand(client, "Disabled all custom gamemode blockers"); + } else { + EntFire(GAMEMODE_BLOCKER_NAME, "Enable"); + ReplyToCommand(client, "Enabled all custom gamemode blockers"); + } + Game.Blockers = !Game.Blockers; + isUnknown = false; + } + if(doAll || StrEqual(type, "props", false)) { + if(Game.Props) { + EntFire(GAMEMODE_PROP_NAME, "Disable"); + EntFire(GAMEMODE_PROP_NAME, "DisableCollision"); + ReplyToCommand(client, "Disabled all custom gamemode props"); + } else { + EntFire(GAMEMODE_PROP_NAME, "Enable"); + EntFire(GAMEMODE_PROP_NAME, "EnableCollision"); + ReplyToCommand(client, "Enabled all custom gamemode props"); + } + Game.Props = !Game.Props; + isUnknown = false; + } + if(isUnknown) ReplyToCommand(client, "Specify the type to affect: 'blockers', 'props', or 'all'"); + } else if(StrEqual(subcmd, "clear", false)) { + static char arg[16]; + GetCmdArg(2, arg, sizeof(arg)); + if(StrEqual(arg, "all")) { + Game.Cleanup(); + ReplyToCommand(client, "Cleaned up everything."); + } else if(StrEqual(arg, "props")) { + EntFire(GAMEMODE_PROP_NAME, "kill"); + ReplyToCommand(client, "Removed all custom gamemode props"); + } else if(StrEqual(arg, "blockers")) { + EntFire(GAMEMODE_BLOCKER_NAME, "kill"); + ReplyToCommand(client, "Removed all custom gamemode blockers"); + } else ReplyToCommand(client, "Specify the type to affect: 'blockers', 'props', or 'all'"); + } else if(StrEqual(subcmd, "settime")) { + int prev = Game.MapTime; + static char arg[16]; + GetCmdArg(2, arg, sizeof(arg)); + int time = StringToInt(arg); + mapConfig.mapTime = time; + Game.MapTime = time; + ReplyToCommand(client, "Map's time is temporarily set to %d seconds (was %d)", time, prev); + } else if(StrEqual(subcmd, "settick")) { + static char arg[16]; + GetCmdArg(2, arg, sizeof(arg)); + int tick = -StringToInt(arg); + Game.Tick = tick; + ReplyToCommand(client, "Set tick time to %d", tick); + } else if(StrContains(subcmd, "map") >= 0) { + static char arg[16]; + GetCmdArg(2, arg, sizeof(arg)); + if(StrEqual(arg, "list")) { + ReplyToCommand(client, "See the console for available maps"); + char map[64]; + for(int i = 0; i < validMaps.Length; i++) { + validMaps.GetString(i, map, sizeof(map)); + PrintToConsole(client, "%d. %s", i + 1, map); + } + } else if(StrEqual(arg, "random")) { + bool foundMap; + char map[64]; + do { + int mapIndex = GetURandomInt() % validMaps.Length; + validMaps.GetString(mapIndex, map, sizeof(map)); + if(!StrEqual(g_currentMap, map, false)) { + foundMap = true; + } + } while(!foundMap); + PrintToChatAll("%s Switching map to %s", GAMEMODE_PREFIX, map); + ChangeMap(map); + } else if(StrEqual(arg, "next", false)) { + if(args == 1) { + ReplyToCommand(client, "Specify the map to change on the next round: 'next '"); + } else { + char arg2[64]; + GetCmdArg(3, arg2, sizeof(arg2)); + if(IsMapValid(arg2)) { + strcopy(nextRoundMap, sizeof(nextRoundMap), arg2); + PrintToChatAll("%s Switching map next round to %s", GAMEMODE_PREFIX, arg2); + ForceChangeLevel(arg, "SetMapSelect"); + } else { + ReplyToCommand(client, "Map is not valid"); + } + } + } else if(StrEqual(arg, "force", false)) { + if(args == 1) { + ReplyToCommand(client, "Specify the map to change to: 'force '"); + } else { + char arg2[64]; + GetCmdArg(3, arg2, sizeof(arg2)); + if(IsMapValid(arg2)) { + PrintToChatAll("[H&S] Switching map to %s", arg2); + ChangeMap(arg2); + } else { + ReplyToCommand(client, "Map is not valid"); + } + } + } else { + ReplyToCommand(client, "Syntax: 'map /next >"); + } + return Plugin_Handled; + } else if(StrEqual(subcmd, "pos", false)) { + float pos[3]; + GetAbsOrigin(client, pos); + ReplyToCommand(client, "\"origin\" \"%f %f %f\"", pos[0], pos[1], pos[2]); + GetClientEyeAngles(client, pos); + ReplyToCommand(client, "\"rotation\" \"%f %f %f\"", pos[0], pos[1], pos[2]); + } else if(StrEqual(subcmd, "prop", false)) { + float pos[3]; + GetAbsOrigin(client, pos); + ReplyToCommand(client, "\"MYPROP\""); + ReplyToCommand(client, "{"); + ReplyToCommand(client, "\t\"origin\" \"%f %f %f\"", pos[0], pos[1], pos[2]); + GetClientAbsAngles(client, pos); + ReplyToCommand(client, "\t\"rotation\" \"%f %f %f\"", pos[0], pos[1], pos[2]); + ReplyToCommand(client, "\t\"type\" \"prop_dynamic\""); + ReplyToCommand(client, "\t\"model\" \"props_junk/dumpster_2.mdl\""); + ReplyToCommand(client, "}"); + } else if(StrEqual(subcmd, "setspawn", false)) { + GetClientAbsOrigin(client, mapConfig.spawnpoint); + ReplyToCommand(client, "Set map's temporarily spawnpoint to your location."); + } else if(StrEqual(subcmd, "stuck")) { + TeleportEntity(client, mapConfig.spawnpoint, NULL_VECTOR, NULL_VECTOR); + } else if(StrEqual(subcmd, "peekfix")) { + if(!PeekCam.Exists()) { + PeekCam.Target = client; + } + + for(int i = 1; i <= MaxClients; i++) { + if(IsClientConnected(i) && IsClientInGame(i)) { + PeekCam.SetViewing(client, true); + PeekCam.SetViewing(client, false); + } + } + PeekCam.Destroy(); + ReplyToCommand(client, "Killing active camera"); + } else if(StrEqual(subcmd, "seeker")) { + if(args == 2) { + char arg1[32]; + GetCmdArg(2, arg1, sizeof(arg1)); + char target_name[MAX_TARGET_LENGTH]; + int target_list[1], target_count; + bool tn_is_ml; + if ((target_count = ProcessTargetString( + arg1, + client, + target_list, + 1, + 0, + target_name, + sizeof(target_name), + tn_is_ml)) <= 0 + || target_list[0] <= 0){ + /* This function replies to the admin with a failure message */ + ReplyToTargetError(client, target_count); + return Plugin_Handled; + } + Game.ForceSetSeeker(target_list[0]); + ReplyToCommand(client, "Set the current seeker to %N", target_list[0]); + } else { + ReplyToCommand(client, "The current seeker is: %N", Game.Seeker); + } + } else if(StrEqual(subcmd, "debug")) { + ReplyToCommand(client, "- Game Info -"); + ReplyToCommand(client, "State: %d | Tick: %d", view_as(Game.State), Game.Tick); + + ReplyToCommand(client, "- Map Info -"); + ReplyToCommand(client, "Map: %s (set %s)", g_currentMap, g_currentSet); + if(mapConfig.hasSpawnpoint) + ReplyToCommand(client, "Has Spawnpoint: yes (%f %f %f)", mapConfig.spawnpoint[0], mapConfig.spawnpoint[1], mapConfig.spawnpoint[2]); + else + ReplyToCommand(client, "Has Spawnpoint: no (possibly map spawn %f %f %f)", mapConfig.spawnpoint[0], mapConfig.spawnpoint[1], mapConfig.spawnpoint[2]); + ReplyToCommand(client, "Map Time: %d", mapConfig.mapTime); + ReplyToCommand(client, "Flow Bounds: (%f, %f)", movePoints.MinFlow, movePoints.MaxFlow); + } else if(StrEqual(subcmd, "test")) { + + } else { + ReplyToCommand(client, "Unknown option. Leave blank for help"); + } + return Plugin_Handled; + } + ReplyToCommand(client, " === [ %s Commands ] ===", GAMEMODE_NAME); + if(GetUserAdmin(client) != INVALID_ADMIN_ID) { + ReplyToCommand(client, "- Dev Commands -"); + ReplyToCommand(client, "r/reload [force]: Reloads map config from file"); + ReplyToCommand(client, "toggle : Toggles all specified entities"); + ReplyToCommand(client, "clear : Clear all specified"); + ReplyToCommand(client, "settime [seconds]: Sets the time override for the map"); + ReplyToCommand(client, "settick [tick]: Sets the current tick timer value"); + ReplyToCommand(client, "- Admin Commands -"); + ReplyToCommand(client, "set [new set]: Change the prop set or view current"); + ReplyToCommand(client, "setspawn: Sets the temporary spawnpoint for the map"); + ReplyToCommand(client, "peekfix - Clear peek camera from all players"); + ReplyToCommand(client, "seeker [new seeker]: Get the active seeker, or set a new one."); + ReplyToCommand(client, "- User Commands -"); + } + ReplyToCommand(client, "stuck: Teleports you to spawn to unstuck yourself"); + return Plugin_Handled; +} + +public Action OnClientSayCommand(int client, const char[] command, const char[] sArgs) { + if(isEnabled) { + if(!StrEqual(command, "say")) { //Is team message + if(currentSeeker <= 0 || currentSeeker == client) { + return Plugin_Continue; + } + for(int i = 1; i <= MaxClients; i++) { + if(IsClientConnected(i) && IsClientInGame(i) && i != currentSeeker) + PrintToChat(i, "[Hiders] %N: %s", client, sArgs); + } + return Plugin_Handled; + } + } + return Plugin_Continue; +} + + +public Action Command_Join(int client, int args) { + if(!isEnabled) return Plugin_Continue; + static float tpLoc[3]; + FindSpawnPosition(tpLoc); + if(args == 1) { + static char arg1[32]; + GetCmdArg(1, arg1, sizeof(arg1)); + char target_name[MAX_TARGET_LENGTH]; + int target_list[MAXPLAYERS], target_count; + bool tn_is_ml; + if ((target_count = ProcessTargetString( + arg1, + client, + target_list, + MAXPLAYERS, + 0, + target_name, + sizeof(target_name), + tn_is_ml)) <= 0) + { + /* This function replies to the admin with a failure message */ + ReplyToTargetError(client, target_count); + return Plugin_Handled; + } + for (int i = 0; i < target_count; i++) { + int target = target_list[i]; + if(GetClientTeam(target) != 2) { + ChangeClientTeam(target, 2); + L4D_RespawnPlayer(target); + TeleportEntity(target, tpLoc, NULL_VECTOR, NULL_VECTOR); + isPendingPlay[client] = false; + CheatCommand(target, "give", "knife"); + } + } + ReplyToCommand(client, "Joined %s", target_name); + } else { + if(currentSeeker == client) { + ReplyToCommand(client, "You are already in-game as a seeker."); + return Plugin_Handled; + } + isPendingPlay[client] = false; + ChangeClientTeam(client, 2); + L4D_RespawnPlayer(client); + TeleportEntity(client, tpLoc, NULL_VECTOR, NULL_VECTOR); + Game.SetupPlayer(client); + if(!ArePlayersJoining()) { + InitGamemode(); + } + } + return Plugin_Handled; +} diff --git a/scripting/include/prophunt/phcore.inc b/scripting/include/prophunt/phcore.inc new file mode 100644 index 0000000..c63b043 --- /dev/null +++ b/scripting/include/prophunt/phcore.inc @@ -0,0 +1,171 @@ +#define FOLDER_PERMS ( FPERM_U_READ | FPERM_U_WRITE | FPERM_U_EXEC | FPERM_G_EXEC | FPERM_G_WRITE | FPERM_G_READ | FPERM_O_EXEC ) + +#include +#include +#include +#include + + +static KeyValues kv; +StringMap mapConfigs; + +bool ReloadMapDB() { + if(kv != null) { + delete kv; + } + kv = new KeyValues("prophunt"); + + char sPath[PLATFORM_MAX_PATH]; + BuildPath(Path_SM, sPath, sizeof(sPath), "data/prophunt"); + CreateDirectory(sPath, FOLDER_PERMS); + Format(sPath, sizeof(sPath), "%s/config.cfg", sPath); + + if(!FileExists(sPath) || !kv.ImportFromFile(sPath)) { + delete kv; + return false; + } + + validMaps.Clear(); + + char map[64]; + kv.GotoFirstSubKey(true); + do { + kv.GetSectionName(map, sizeof(map)); + validMaps.PushString(map); + } while(kv.GotoNextKey(true)); + kv.GoBack(); + return true; +} + +static float DEFAULT_SCALE[3] = { 5.0, 5.0, 5.0 }; + +bool LoadConfigForMap(const char[] map) { + kv.Rewind(); + if (kv.JumpToKey(map)) { + MapConfig config; + config.entities = new ArrayList(sizeof(EntityConfig)); + config.inputs = new ArrayList(ByteCountToCells(64)); + validSets.Clear(); + + static char buffer[64]; + buffer[0] = '\0'; + if(StrEqual(g_currentSet, "default") && kv.GetString("defaultset", buffer, sizeof(buffer)) && buffer[0] != '\0') { + strcopy(g_currentSet, sizeof(g_currentSet), buffer); + } + PrintToServer("[PropHunt] Loading config data for set %s on %s", g_currentSet, map); + + if(kv.JumpToKey("ents")) { + kv.GotoFirstSubKey(); + do { + EntityConfig entCfg; + kv.GetVector("origin", entCfg.origin, NULL_VECTOR); + kv.GetVector("rotation", entCfg.rotation, NULL_VECTOR); + kv.GetString("type", entCfg.type, sizeof(entCfg.type), "env_physics_blocker"); + kv.GetString("model", entCfg.model, sizeof(entCfg.model), ""); + if(entCfg.model[0] != '\0') + Format(entCfg.model, sizeof(entCfg.model), "models/%s", entCfg.model); + kv.GetVector("scale", entCfg.scale, DEFAULT_SCALE); + kv.GetVector("offset", entCfg.offset, NULL_VECTOR); + kv.GetString("set", buffer, sizeof(buffer), "default"); + if(validSets.FindString(buffer) == -1) { + validSets.PushString(buffer); + } + if(StrEqual(buffer, "default") || StrEqual(g_currentSet, buffer, false)) { + + config.entities.PushArray(entCfg); + } else { + kv.GetSectionName(buffer, sizeof(buffer)); + PrintToServer("Skipping %s", buffer); + } + } while (kv.GotoNextKey()); + // JumpToKey and GotoFirstSubKey both traverse, i guess, go back + kv.GoBack(); + kv.GoBack(); + } + if(kv.JumpToKey("inputs")) { + kv.GotoFirstSubKey(false); + do { + kv.GetSectionName(buffer, sizeof(buffer)); + config.inputs.PushString(buffer); + + kv.GetString(NULL_STRING, buffer, sizeof(buffer)); + config.inputs.PushString(buffer); + } while (kv.GotoNextKey(false)); + kv.GoBack(); + kv.GoBack(); + } + int mapTime; + + config.hasSpawnpoint = false; + config.canClimb = true; + config.pressButtons = true; + if(!StrEqual(g_currentSet, "default") && kv.JumpToKey("sets")) { + char set[16]; + kv.GotoFirstSubKey(true); + do { + kv.GetSectionName(set, sizeof(set)); + if(validSets.FindString(set) == -1) { + validSets.PushString(set); + } + if(StrEqual(g_currentSet, set, false)) { + kv.GetVector("spawnpoint", config.spawnpoint); + if(config.spawnpoint[0] != 0.0 && config.spawnpoint[1] != 0.0 && config.spawnpoint[2] != 0.0) { + PrintToServer("[PropHunt] Using provided custom spawnpoint for set %s at %0.1f, %0.1f, %0.1f", g_currentSet, config.spawnpoint[0], config.spawnpoint[1], config.spawnpoint[2]); + config.hasSpawnpoint = true; + } + mapTime = kv.GetNum("maptime", 0); + if(kv.JumpToKey("inputs")) { + kv.GotoFirstSubKey(false); + do { + kv.GetSectionName(buffer, sizeof(buffer)); + config.inputs.PushString(buffer); + + kv.GetString(NULL_STRING, buffer, sizeof(buffer)); + config.inputs.PushString(buffer); + } while (kv.GotoNextKey(false)); + kv.GoBack(); + kv.GoBack(); + } + break; + } + + } while(kv.GotoNextKey(true)); + kv.GoBack(); + kv.GoBack(); + } + + if(!config.hasSpawnpoint) { + kv.GetVector("spawnpoint", config.spawnpoint); + if(config.spawnpoint[0] != 0.0 && config.spawnpoint[1] != 0.0 && config.spawnpoint[2] != 0.0) { + PrintToServer("[PropHunt] Using provided custom spawnpoint at %0.1f, %0.1f, %0.1f", config.spawnpoint[0], config.spawnpoint[1], config.spawnpoint[2]); + config.hasSpawnpoint = true; + } else if (FindSpawnPosition(config.spawnpoint, false)) { + PrintToServer("[PropHunt] Using map spawnpoint at %0.1f, %0.1f, %0.1f", config.spawnpoint[0], config.spawnpoint[1], config.spawnpoint[2]); + config.hasSpawnpoint = true; + } else { + PrintToServer("[PropHunt] Could not find any spawnpoints, using default spawn"); + config.hasSpawnpoint = false; + } + } + + // Use default maptime if exists + if(mapTime == 0) + mapTime = kv.GetNum("maptime", 0); + if(mapTime > 0) { + config.mapTime = mapTime; + PrintToServer("[PropHunt] Map time overwritten to %d seconds", mapTime); + } + + mapConfigs.SetArray(map, config, sizeof(MapConfig)); + // Discard entInputs if unused + if(config.inputs.Length == 0) { + delete config.inputs; + } + mapConfig = config; + return true; + } else { + mapConfig.hasSpawnpoint = false; + PrintToServer("[PropHunt] %s has no config entry", map); + return false; + } +} \ No newline at end of file diff --git a/scripting/include/prophunt/phents.inc b/scripting/include/prophunt/phents.inc new file mode 100644 index 0000000..670c13e --- /dev/null +++ b/scripting/include/prophunt/phents.inc @@ -0,0 +1,128 @@ +#define ENT_PROP_NAME "gwprop" +#define ENT_BLOCKER_NAME "gwblocker" +#define ENT_PORTAL_NAME "gwportal" +#define ENT_ENV_NAME "gwenv" +#include + +stock void CheatCommand(int client, const char[] command, const char[] argument1) { + int userFlags = GetUserFlagBits(client); + SetUserFlagBits(client, ADMFLAG_ROOT); + int flags = GetCommandFlags(command); + SetCommandFlags(command, flags & ~FCVAR_CHEAT); + FakeClientCommand(client, "%s %s", command, argument1); + SetCommandFlags(command, flags); + SetUserFlagBits(client, userFlags); +} + + +stock void EntFire(const char[] name, const char[] input) { + static char targetname[64]; + static char cmd[32]; + #if defined DEBUG_LOG_MAPSTART + PrintToServer("EntFire: %s \"%s\"", name, input); + #endif + int len = SplitString(input, " ", cmd, sizeof(cmd)); + if(len > -1) SetVariantString(input[len]); + + int hammerId = name[0] == '!' ? StringToInt(name[1]) : 0; + for(int i = MaxClients + 1; i <= 4096; i++) { + if(IsValidEntity(i) && (IsValidEdict(i) || EntIndexToEntRef(i) != -1)) { + if(hammerId > 0) { + if(hammerId == Entity_GetHammerId(i)) { + if(len > -1) AcceptEntityInput(i, cmd); + else AcceptEntityInput(i, input); + } + } else { + GetEntPropString(i, Prop_Data, "m_iName", targetname, sizeof(targetname)); + if(StrEqual(targetname, name, false)) { + if(len > -1) AcceptEntityInput(i, cmd); + else AcceptEntityInput(i, input); + + } else { + GetEntityClassname(i, targetname, sizeof(targetname)); + if(StrEqual(targetname, name, false)) { + if(len > -1) AcceptEntityInput(i, cmd); + else AcceptEntityInput(i, input); + } + } + } + } + } +} + + + +void SetupEntities(bool blockers = true, bool props = true, bool portals = true) { + #if defined DEBUG_BLOCKERS + if(mapConfig.hasSpawnpoint) { + PrecacheModel("survivors/survivor_teenangst.mdl", true); + int dummy = CreateDummy("models/survivors/survivor_teenangst.mdl", "idle", mapConfig.spawnpoint, NULL_VECTOR); + SetEntProp(dummy, Prop_Data, "m_nSolidType", 0); + SetEntProp(dummy, Prop_Send, "m_CollisionGroup", 0); + SetEntProp(dummy, Prop_Send, "movetype", MOVETYPE_NONE); + } + EntFire("info_changelevel", "Kill"); + #endif + if(mapConfig.entities != null) { + PrintToServer("[GuessWho] Deploying %d custom entities (Set: %s) (blockers:%b props:%b portals:%b)", mapConfig.entities.Length, g_currentSet, blockers, props, portals); + for(int i = 0; i < mapConfig.entities.Length; i++) { + EntityConfig config; + mapConfig.entities.GetArray(i, config); + + if(config.model[0] != '\0') PrecacheModel(config.model); + + if(StrEqual(config.type, "env_physics_blocker")) { + if(blockers && CreateEnvBlockerScaled(config.type, config.origin, config.scale, isNavBlockersEnabled) == -1) { + Game.Warn("Failed to spawn blocker [type=%s] at (%.1f,%.1f, %.1f)", config.type, config.origin[0], config.origin[1], config.origin[2]); + } + } else if(StrEqual(config.type, "_relportal")) { + if(portals && CreatePortal(Portal_Relative, config.model, config.origin, config.offset, config.scale) == -1) { + Game.Warn("Failed to spawn rel portal at (%.1f,%.1f, %.1f)", config.origin[0], config.origin[1], config.origin[2]); + } + } else if(StrEqual(config.type, "_portal")) { + if(portals && CreatePortal(Portal_Teleport, config.model, config.origin, config.offset, config.scale) == -1) { + Game.Warn("Failed to spawn portal at (%.1f,%.1f, %.1f)", config.origin[0], config.origin[1], config.origin[2]); + } + } else if(StrEqual(config.type, "_lantern")) { + int parent = CreateProp("prop_dynamic", config.model, config.origin, config.rotation); + if(parent == -1) { + Game.Warn("Failed to spawn prop [type=%s] [model=%s] at (%.1f,%.1f, %.1f)", config.type, config.model, config.origin[0], config.origin[1], config.origin[2]); + } else { + float pos[3]; + pos = config.origin; + pos[2] += 15.0; + int child = CreateDynamicLight(pos, config.rotation, GetColorInt(255, 255, 242), 80.0, 11); + if(child == -1) { + Game.Warn("Failed to spawn light source for _lantern"); + } else { + SetParent(child, parent); + TeleportEntity(parent, config.origin, NULL_VECTOR, NULL_VECTOR); + } + } + } else if(StrEqual(config.type, "_dummy")) { + if(CreateDummy(config.model, "hitby_tankpunch", config.origin, config.rotation) == -1) { + Game.Warn("Failed to spawn dummy [model=%s] at (%.1f,%.1f, %.1f)", config.model, config.origin[0], config.origin[1], config.origin[2]); + } + } else if(StrEqual(config.type, "env_fire")) { + if(props && CreateFire(config.origin, config.scale[0], config.scale[1], config.scale[2]) == -1) { + Game.Warn("Failed to spawn env_fire at (%.1f,%.1f, %.1f)", config.origin[0], config.origin[1], config.origin[2]); + } + } else if(props) { + if(CreateProp(config.type, config.model, config.origin, config.rotation) == -1) { + Game.Warn("Failed to spawn prop [type=%s] [model=%s] at (%.1f,%.1f, %.1f)", config.type, config.model, config.origin[0], config.origin[1], config.origin[2]); + } + } + } + + static char key[64]; + static char value[64]; + if(mapConfig.inputs != null) { + for(int i = 0; i < mapConfig.inputs.Length - 1; i += 2) { + mapConfig.inputs.GetString(i, key, sizeof(key)); + mapConfig.inputs.GetString(i + 1, value, sizeof(value)); + EntFire(key, value); + } + } + } +} + diff --git a/scripting/include/prophunt/phgame.inc b/scripting/include/prophunt/phgame.inc new file mode 100644 index 0000000..f5f6d6f --- /dev/null +++ b/scripting/include/prophunt/phgame.inc @@ -0,0 +1,390 @@ +static int mapChangeMsgTicks = 5; + +int GetColorInt(int r, int g, int b) { + int color = r; + color += 256 * g; + color += 65536 * b; + return color; +} + +Action Timer_ChangeMap(Handle h) { + PrintToChatAll("Changing map to %s in %d seconds", nextRoundMap, mapChangeMsgTicks); + if(mapChangeMsgTicks-- == 0) { + ForceChangeLevel(nextRoundMap, "GuessWhoMapSelect"); + nextRoundMap[0] = '\0'; + return Plugin_Stop; + } + return Plugin_Continue; +} + +void ChangeMap(const char map[64], int time = 5) { + strcopy(nextRoundMap, sizeof(nextRoundMap), map); + mapChangeMsgTicks = time; + CreateTimer(1.0, Timer_ChangeMap, _, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE); +} + +bool FindSpawnPosition(float pos[3], bool includePlayers = true) { + if(includePlayers) { + for(int i = 1; i <= MaxClients; i++) { + if(IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i)) { + GetClientAbsOrigin(i, pos); + return true; + } + } + } + int entity = INVALID_ENT_REFERENCE; + while ((entity = FindEntityByClassname(entity, "info_player_start")) != INVALID_ENT_REFERENCE) { + GetEntPropVector(entity, Prop_Send, "m_vecOrigin", pos); + return true; + } + return false; +} + +static char buffer[128]; + +bool isSeeker[MAXPLAYERS+1]; + +methodmap PropHuntGame < BaseGame { + + property int Seekers { + public get() { + int count = 0; + for(int i = 1; i <= MaxClients; i++) { + if(isSeeker[i]) count++; + } + return count; + } + } + + public bool IsSeeker(int client) { + return isSeeker[client]; + } + + public void SetSeeker(int client, bool value) { + isSeeker[client] = value; + } + + public void ClearSeekers() { + for(int i = 1; i <= MaxClients; i++) { + isSeeker[i] = false; + } + } + + property int Tick { + public get() { + if(!isEnabled) return -1; + L4D2_GetVScriptOutput("g_ModeScript.MutationState.Tick", buffer, sizeof(buffer)); + int value = -1; + if(StringToIntEx(buffer, value) > 0) { + return value; + } else { + return -1; + } + } + public set(int tick) { + Format(buffer, sizeof(buffer), "g_ModeScript.MutationState.Tick = %d", tick); + L4D2_ExecVScriptCode(buffer); + } + } + + property GameState State { + public get() { + if(!isEnabled) return State_Unknown; + L4D2_GetVScriptOutput("g_ModeScript.MutationState.State", buffer, sizeof(buffer)); + int stage = 0; + if(StringToIntEx(buffer, stage) > 0) { + return view_as(stage); + } else { + return State_Unknown; + } + } + public set(GameState state) { + if(isEnabled) { + Format(buffer, sizeof(buffer), "g_ModeScript.MutationState.State = %d", view_as(state)); + L4D2_ExecVScriptCode(buffer); + } + } + } + + property int MapTime { + public get() { + L4D2_GetVScriptOutput("g_ModeScript.MutationState.MaxTime", buffer, sizeof(buffer)); + return StringToInt(buffer); + } + public set(int seconds) { + Format(buffer, sizeof(buffer), "g_ModeScript.MutationState.MaxTime = %d", seconds); + L4D2_ExecVScriptCode(buffer); + if(timesUpTimer != null) { + float remaining = float(seconds) - float(this.Tick); + delete timesUpTimer; + timesUpTimer = CreateTimer(remaining, Timer_TimesUp, _, TIMER_FLAG_NO_MAPCHANGE); + } + } + } + + public void Start() { + + } + + public void End(GameState state) { + this.State = state; + CreateTimer(5.0, Timer_ResetAll); + } + + public void Cleanup(bool noClearInv = false) { + DeleteCustomEnts(); + } + + public int _FindSeeker() { + if(!isEnabled) return -1; + L4D2_GetVScriptOutput("g_ModeScript.MutationState.CurrentSeeker && \"GetPlayerUserId\" in g_ModeScript.MutationState.CurrentSeeker ? g_ModeScript.MutationState.CurrentSeeker.GetPlayerUserId() : -1", buffer, sizeof(buffer)); + int uid = StringToInt(buffer); + if(uid > 0) { + return GetClientOfUserId(uid); + } else { + Game.Debug("Mutation has no seeker, manually attempting to find seeker"); + for(int i = 1; i <= MaxClients; i++) { + if(IsClientConnected(i) && IsClientInGame(i)) { + int entity = GetPlayerWeaponSlot(i, 1); + if(entity > -1 && GetEntityClassname(entity, buffer, sizeof(buffer)) && StrEqual(buffer, "melee")) { + GetEntPropString(entity, Prop_Data, "m_strMapSetScriptName", buffer, sizeof(buffer)); + if(StrEqual(buffer, "smg")) { + return i; + } + } + } + } + } + Game.Debug("All attempts to find a seeker failed"); + return -1; + } + + + public void ForceSetSeeker(int client, bool ignoreBalance = false) { + ignoreSeekerBalance = true; + this.Seeker = client; + } + + public bool TeleportToSpawn(int client) { + if(mapConfig.hasSpawnpoint) { + TeleportEntity(client, mapConfig.spawnpoint, NULL_VECTOR, NULL_VECTOR); + return true; + } else { + float pos[3]; + if(FindSpawnPosition(pos)) { + return false; + } + TeleportEntity(client, pos, NULL_VECTOR, NULL_VECTOR); + } + return false; + } + + public void TeleportAllToStart() { + if(mapConfig.hasSpawnpoint) { + PrintToServer("[GuessWho] Teleporting all players to provided spawnpoint (%f %f %f)", mapConfig.spawnpoint[0], mapConfig.spawnpoint[1], mapConfig.spawnpoint[2]); + for(int i = 1; i <= MaxClients; i++) { + if(IsClientConnected(i) && IsClientInGame(i)) { + this.TeleportToSpawn(i); + } + } + } else { + PrintToServer("[GuessWho] Warn: No spawnpoint found (provided or map spawn)"); + } + } + + // Ignores seeker + property int AlivePlayers { + public get() { + int amount = 0; + for(int i = 1; i <= MaxClients; i++) { + if(!this.IsSeeker(i) && IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i) && !IsFakeClient(i)) { + amount++; + } + } + return amount; + } + } + + public void SetupInventory(int client) { + ClearInventory(client); + if(this.IsSeeker(client)) { + CheatCommand(client, "give", "smg"); + } + } + + public void SetupPlayer(int client) { + this.SetupInventory(client); + SDKHook(client, SDKHook_OnTakeDamageAlive, OnTakeDamageAlive); + } + + public void UnsetupPlayer(int client) { + SDKUnhook(client, SDKHook_OnTakeDamageAlive, OnTakeDamageAlive); + } +} + +stock bool ArePlayersJoining() { + for(int i = 1; i <= MaxClients; i++) { + if(IsClientConnected(i) && !IsClientInGame(i)) { + return true; + } + } + return false; +} + +stock void GetHorizontalPositionFromClient(int client, float units, float finalPosition[3]) { + float pos[3], ang[3]; + GetClientEyeAngles(client, ang); + GetClientAbsOrigin(client, pos); + + float theta = DegToRad(ang[1]); + pos[0] += units * Cosine(theta); + pos[1] += units * Sine(theta); + finalPosition = pos; +} + +stock void GetAnglesLookAt(int iClient, int iTarget, float fFinalPos[3]) { + static float fTargetPos[3]; + static float fTargetAngles[3]; + static float fClientPos[3]; + + GetEntPropVector(iClient, Prop_Send, "m_vecOrigin", fClientPos); + GetClientEyePosition(iTarget, fTargetPos); + GetClientEyeAngles(iTarget, fTargetAngles); + + float fVecFinal[3]; + AddInFrontOf(fTargetPos, fTargetAngles, 7.0, fVecFinal); + MakeVectorFromPoints(fClientPos, fVecFinal, fFinalPos); + + GetVectorAngles(fFinalPos, fFinalPos); + + // TeleportEntity(iClient, NULL_VECTOR, fFinalPos, NULL_VECTOR); +} +stock void AddInFrontOf(const float fVecOrigin[3], const float fVecAngle[3], float fUnits, float fOutPut[3]) +{ + float fVecView[3]; GetViewVector(fVecAngle, fVecView); + + fOutPut[0] = fVecView[0] * fUnits + fVecOrigin[0]; + fOutPut[1] = fVecView[1] * fUnits + fVecOrigin[1]; + fOutPut[2] = fVecView[2] * fUnits + fVecOrigin[2]; +} +stock void GetViewVector(const float fVecAngle[3], float fOutPut[3]) +{ + fOutPut[0] = Cosine(fVecAngle[1] / (180 / FLOAT_PI)); + fOutPut[1] = Sine(fVecAngle[1] / (180 / FLOAT_PI)); + fOutPut[2] = -Sine(fVecAngle[0] / (180 / FLOAT_PI)); +} + +stock void LookAtClient(int iClient, int iTarget) { + static float fTargetPos[3]; + static float fTargetAngles[3]; + static float fClientPos[3]; + static float fFinalPos[3]; + + GetClientEyePosition(iClient, fClientPos); + GetClientEyePosition(iTarget, fTargetPos); + GetClientEyeAngles(iTarget, fTargetAngles); + + float fVecFinal[3]; + AddInFrontOf(fTargetPos, fTargetAngles, 7.0, fVecFinal); + MakeVectorFromPoints(fClientPos, fVecFinal, fFinalPos); + + GetVectorAngles(fFinalPos, fFinalPos); + + TeleportEntity(iClient, NULL_VECTOR, fFinalPos, NULL_VECTOR); +} + +stock void LookAtPoint(int client, const float targetPos[3]) { + static float targetAngles[3]; + static float clientPos[3]; + static float fFinalPos[3]; + + GetClientEyePosition(client, clientPos); + GetClientEyeAngles(client, targetAngles); + + float fVecFinal[3]; + AddInFrontOf(targetPos, targetAngles, 7.0, fVecFinal); + MakeVectorFromPoints(clientPos, fVecFinal, fFinalPos); + + GetVectorAngles(fFinalPos, fFinalPos); + + TeleportEntity(client, NULL_VECTOR, fFinalPos, NULL_VECTOR); +} + + +void SetPlayerBlind(int target, int amount) { + int targets[1]; + targets[0] = target; + + int duration = 1536; + int holdtime = 1536; + int flags = (amount == 0) ? (0x0001 | 0x0010) : (0x0002 | 0x0008); + int color[4] = { 0, 0, 0, 0 }; + color[3] = amount; + + Handle message = StartMessageEx(g_FadeUserMsgId, targets, 1); + BfWrite bf = UserMessageToBfWrite(message); + bf.WriteShort(duration); + bf.WriteShort(holdtime); + bf.WriteShort(flags); + bf.WriteByte(color[0]); + bf.WriteByte(color[1]); + bf.WriteByte(color[2]); + bf.WriteByte(color[3]); + EndMessage(); +} + +#define HIDER_DISTANCE_MAX_SIZE 10 + + +#define MAX_AUTO_VOCALIZATIONS 9 +static char AUTO_VOCALIZATIONS[MAX_AUTO_VOCALIZATIONS][] = { + "PlayerLaugh", + "PlayerSpotPill", + "Playerlookout", + "EatPills", + "ReviveMeInterrupted", + "PlayerIncapacitated", + "PlayerNiceShot", + "ResponseSoftDispleasureSwear", + "PlayerAreaClear" +}; + +enum struct HiderDistQueue { + int index; + float list[HIDER_DISTANCE_MAX_SIZE]; + int lastVocalize; + + void AddPos(const float pos[3]) { + this.list[this.index] = GetVectorDistance(seekerPos, pos); + if(++this.index == HIDER_DISTANCE_MAX_SIZE) { + this.index = 0; + } + } + + void Clear() { + for(int i = 0; i < HIDER_DISTANCE_MAX_SIZE; i++) { + this.list[i] = 0.0; + } + } + + float GetAverage() { + float sum = 0.0; + for(int i = 0; i < HIDER_DISTANCE_MAX_SIZE; i++) { + sum += this.list[i]; + } + return sum / float(HIDER_DISTANCE_MAX_SIZE); + } + + void Check(int i) { + if(this.GetAverage() > HIDER_MIN_AVG_DISTANCE_AUTO_VOCALIZE) { + int time = GetTime(); + if(time - this.lastVocalize > HIDER_AUTO_VOCALIZE_GRACE_TIME) { + this.lastVocalize = time; + int index = GetRandomInt(0, MAX_AUTO_VOCALIZATIONS - 1); + PerformScene(i, AUTO_VOCALIZATIONS[index]); + } + } + } +} + +HiderDistQueue distQueue[MAXPLAYERS+1]; \ No newline at end of file diff --git a/scripting/include/prophunt/phtimers.inc b/scripting/include/prophunt/phtimers.inc new file mode 100644 index 0000000..1a37392 --- /dev/null +++ b/scripting/include/prophunt/phtimers.inc @@ -0,0 +1,70 @@ + +Action Timer_RecordPoints(Handle h, int i) { + if(GetEntityFlags(i) & FL_ONGROUND && IsPlayerAlive(i)) { + LocationMeta meta; + GetClientAbsOrigin(i, meta.pos); + GetClientEyeAngles(i, meta.ang); + if(meta.pos[0] != vecLastLocation[i][0] || meta.pos[1] != vecLastLocation[i][1] || meta.pos[2] != vecLastLocation[i][2]) { + if(movePoints.AddPoint(meta)) { + recordTimer = null; + return Plugin_Stop; + } + Effect_DrawBeamBoxRotatableToClient(i, meta.pos, DEBUG_POINT_VIEW_MIN, DEBUG_POINT_VIEW_MAX, NULL_VECTOR, g_iLaserIndex, 0, 0, 0, 150.0, 0.1, 0.1, 0, 0.0, {0, 0, 255, 64}, 0); + vecLastLocation[i] = meta.pos; + } + } + PrintHintText(i, "Points: %d / %d", movePoints.Length, MAX_VALID_LOCATIONS); + return Plugin_Continue; +} + +bool firstCheckDone = false; +Action Timer_WaitForPlayers(Handle h) { + if(!isEnabled) return Plugin_Stop; + if(!ArePlayersJoining()) { + Game.Debug("No players pending, ready to go"); + if(!firstCheckDone) { + // Wait one more iteration + firstCheckDone = true; + } else { + firstCheckDone = false; + InitGamemode(); + return Plugin_Stop; + } + } + Game.Debug("Waiting for players"); + return Plugin_Continue; +} + + +Action Timer_CheckHiders(Handle h) { + static float pos[3]; + static char classname[16]; + for(int i = 1; i <= MaxClients; i++) { + if(IsClientConnected(i) && IsClientInGame(i) && !IsFakeClient(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i)) { + GetClientAbsOrigin(i, pos); + distQueue[i].AddPos(pos); + distQueue[i].Check(i); + + int activeWeapon = GetEntPropEnt(i, Prop_Send, "m_hActiveWeapon"); + if(IsValidEntity(activeWeapon)) { + GetEntityClassname(activeWeapon, classname, sizeof(classname)); + if(i == currentSeeker) { + if(StrEqual(classname, "weapon_melee")) continue; + Game.SetupInventory(i); + } else if(StrEqual(classname, "weapon_gnome")) continue; + } + Game.SetupInventory(i); + } + } + Game.CleanupGnomes(true); + return Plugin_Continue; +} + +Action Timer_ResetAll(Handle h) { + for(int i = 1; i <= MaxClients; i++) { + if(IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2) { + ForcePlayerSuicide(i); + } + } + return Plugin_Handled; +} \ No newline at end of file diff --git a/scripting/l4d2_prophunt.sp b/scripting/l4d2_prophunt.sp new file mode 100644 index 0000000..c8624ca --- /dev/null +++ b/scripting/l4d2_prophunt.sp @@ -0,0 +1,151 @@ +#pragma semicolon 1 +#pragma newdecls required + +//#define DEBUG + +#define PLUGIN_VERSION "1.0" + +#include +#include +#include +#include +#include + +enum GameState { + State_Unknown = 0, + State_Hiding, + State_Active, + State_PropsWin, + State_SeekerWin, +} + +#define MAX_VALID_MODELS 2 +static char VALID_MODELS[MAX_VALID_MODELS][] = { + "models/props_crates/static_crate_40.mdl", + "models/props_junk/gnome.mdl" +}; + +static float EMPTY_ANG[3]; +#define TRANSPARENT "255 255 255 0" +#define WHITE "255 255 255 255" + +enum struct PropData { + int prop; + bool rotationLock; +} + +PropData propData[MAXPLAYERS+1]; + +public Plugin myinfo = +{ + name = "Prophunt", + author = "jackzmc", + description = "", + version = PLUGIN_VERSION, + url = "https://github.com/Jackzmc/sourcemod-plugins" +}; + +public void OnPluginStart() { + EngineVersion g_Game = GetEngineVersion(); + if(g_Game != Engine_Left4Dead2) { + SetFailState("This plugin is for L4D2 only."); + } + RegConsoleCmd("sm_game", Command_Test); +} + +public void OnMapStart() { + for(int i = 0; i < MAX_VALID_MODELS; i++) { + PrecacheModel(VALID_MODELS[i]); + } +} + +void ResetPlayerData(int client) { + if(propData[client].prop > 0) { + AcceptEntityInput(propData[client].prop, "Kill"); + propData[client].prop = 0; + } + propData[client].rotationLock = false; +} + +public void OnMapEnd() { + for(int i = 1; i <= MaxClients; i++) { + ResetPlayerData(i); + if(IsClientConnected(i) && IsClientInGame(i)) { + DispatchKeyValue(i, "rendercolor", WHITE); + } + } +} + +public void OnClientDisconnect(int client) { + ResetPlayerData(client); +} + +public Action Command_Test(int client, int args) { + int prop = CreatePropInternal(VALID_MODELS[0]); + if(prop <= 0) { + ReplyToCommand(client, "Failed to spawn prop"); + return Plugin_Handled; + } + float pos[3]; + propData[client].prop = prop; + DispatchKeyValue(client, "rendercolor", TRANSPARENT); + // SetParent(prop, client); + // SetParentAttachment(prop, "eyes", true); + // TeleportEntity(prop, pos, EMPTY_ANG, NULL_VECTOR); + // SetParentAttachment(prop, "eyes", true); + SDKHook(client, SDKHook_SetTransmit, OnPlayerTransmit); + ReplyToCommand(client, "Game!"); + return Plugin_Handled; +} + + +Action OnPlayerTransmit(int entity, int client) { + return entity == client ? Plugin_Continue : Plugin_Stop; +} + +int CreatePropInternal(const char[] model) { + int entity = CreateEntityByName("prop_dynamic"); + DispatchKeyValue(entity, "model", model); + DispatchKeyValue(entity, "disableshadows", "1"); + DispatchKeyValue(entity, "targetname", "phprop"); + DispatchSpawn(entity); + SetEntProp(entity, Prop_Send, "m_nSolidType", 6); + SetEntProp(entity, Prop_Send, "m_CollisionGroup", 1); + SetEntProp(entity, Prop_Send, "movetype", MOVETYPE_NONE); + return entity; +} + +public Action OnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3], float angles[3], int& weapon, int& subtype, int& cmdnum, int& tickcount, int& seed, int mouse[2]) { + if(propData[client].prop > 0) { + static float pos[3], ang[3]; + GetClientAbsOrigin(client, pos); + TeleportEntity(client, pos, NULL_VECTOR, NULL_VECTOR); + if(propData[client].rotationLock) + TeleportEntity(propData[client].prop, NULL_VECTOR, angles, NULL_VECTOR); + else { + ang[0] = 0.0; + ang[1] = angles[1]; + ang[2] = 0.0; + TeleportEntity(propData[client].prop, pos, ang, NULL_VECTOR); + } + } + return Plugin_Continue; +} + +Action OnTakeDamageAlive(int victim, int& attacker, int& inflictor, float& damage, int& damagetype) { + /*if(attacker == currentSeeker) { + damage = 100.0; + ClearInventory(victim); + if(attacker > 0 && attacker <= MaxClients && IsFakeClient(victim)) { + PrintToChat(attacker, "That was a bot! -%.0f health", cvar_seekerFailDamageAmount.FloatValue); + SDKHooks_TakeDamage(attacker, 0, 0, cvar_seekerFailDamageAmount.FloatValue, DMG_DIRECT); + } + return Plugin_Changed; + } else if(attacker > 0 && attacker <= MaxClients) { + damage = 0.0; + return Plugin_Changed; + } else { + return Plugin_Continue; + }*/ + return Plugin_Continue; +} From 5a5ea13756196a94d2c993a3a231fc2e63e6824a Mon Sep 17 00:00:00 2001 From: Jackz Date: Wed, 24 Aug 2022 11:00:26 -0500 Subject: [PATCH 2/6] Move filter to gamemodes core --- scripting/include/gamemodes/base.inc | 3 +++ scripting/include/guesswho/gwgame.inc | 4 ---- scripting/include/hideandseek/hsgame.inc | 6 ------ 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/scripting/include/gamemodes/base.inc b/scripting/include/gamemodes/base.inc index 3b156c7..db652f7 100644 --- a/scripting/include/gamemodes/base.inc +++ b/scripting/include/gamemodes/base.inc @@ -246,6 +246,9 @@ methodmap PeekCamera { } } +bool Filter_IgnoreAll(int entity, int mask) { + return false; +} enum struct EntityConfig { float origin[3]; diff --git a/scripting/include/guesswho/gwgame.inc b/scripting/include/guesswho/gwgame.inc index 6326229..9911593 100644 --- a/scripting/include/guesswho/gwgame.inc +++ b/scripting/include/guesswho/gwgame.inc @@ -391,10 +391,6 @@ stock void LookAtPoint(int client, const float targetPos[3]) { TeleportEntity(client, NULL_VECTOR, fFinalPos, NULL_VECTOR); } -bool Filter_IgnoreAll(int entity, int mask) { - return false; -} - void SetPlayerBlind(int target, int amount) { int targets[1]; diff --git a/scripting/include/hideandseek/hsgame.inc b/scripting/include/hideandseek/hsgame.inc index 0043a95..d909987 100644 --- a/scripting/include/hideandseek/hsgame.inc +++ b/scripting/include/hideandseek/hsgame.inc @@ -231,9 +231,3 @@ stock void GetViewVector(float fVecAngle[3], float fOutPut[3]) fOutPut[1] = Sine(fVecAngle[1] / (180 / FLOAT_PI)); fOutPut[2] = -Sine(fVecAngle[0] / (180 / FLOAT_PI)); } - - -bool Filter_IgnoreAll(int entity, int mask) { - return false; -} - From 0e7a48b6095c714593ace9161315497e9bb29c2f Mon Sep 17 00:00:00 2001 From: Jackz Date: Wed, 24 Aug 2022 11:00:43 -0500 Subject: [PATCH 3/6] Fix manual target being wrong entity --- plugins/l4d2_turret.smx | Bin 21310 -> 21326 bytes scripting/l4d2_turret.sp | 5 +++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/l4d2_turret.smx b/plugins/l4d2_turret.smx index 765c214bfd24eb4e0a5cc579979e445bdd105e2b..bc4bc54a86f875266f8533905f14b6eb50ff7c57 100644 GIT binary patch literal 21326 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 literal 21310 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 bqm=wvar~;@()2<$vh<>Mlq~%pRBORIPN||c diff --git a/scripting/l4d2_turret.sp b/scripting/l4d2_turret.sp index 24755b6..5d34c1a 100644 --- a/scripting/l4d2_turret.sp +++ b/scripting/l4d2_turret.sp @@ -231,6 +231,7 @@ public Action OnTakeDamageAlive(int victim, int& attacker, int& inflictor, float } public void OnMapEnd() { + manualTarget = -1; ClearTurrets(); } @@ -261,7 +262,7 @@ public void OnEntityDestroyed(int entity) { public Action Command_SpawnTurret(int client, int args) { float pos[3]; GetClientEyePosition(client, pos); - pos[2] += 20.0; + pos[2] += 40.0; int base = CreateParticleNamed(ENT_PORTAL_NAME, PARTICLE_ELMOS, pos, NULL_VECTOR); SetupTurret(base, TURRET_ACTIVATION_TIME); ReplyToCommand(client, "New turret (%d) will activate in %.0f seconds", base, TURRET_ACTIVATION_TIME); @@ -642,7 +643,7 @@ public Action OnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3 // Run a ray trace to find a suitable position // TODO: Possibly run per-turret for more accurate preview... but it's already lag fest TR_TraceRayFilter(orgPos, angles, MASK_SHOT, RayType_Infinite, Filter_ManualTarget); - if(!IsValidEntity(manualTarget)) manualTarget = CreateTarget(aimPos, MANUAL_TARGETNAME); + if(manualTarget <= 0 || !IsValidEntity(manualTarget)) manualTarget = CreateTarget(aimPos, MANUAL_TARGETNAME); // Disable aim snapping if player is holding WALK (which is apparently IN_SPEED) bool aimSnapping = ~buttons & IN_SPEED > 0; From dd2f1b45bda172e1c83a69f41797c3c5f1bf2f8f Mon Sep 17 00:00:00 2001 From: Jackz Date: Wed, 24 Aug 2022 11:00:59 -0500 Subject: [PATCH 4/6] Add heal detection --- plugins/l4d2_detections.smx | Bin 8300 -> 8623 bytes scripting/l4d2_detections.sp | 20 +++++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/plugins/l4d2_detections.smx b/plugins/l4d2_detections.smx index d8f3d746e184c8cc52939a0fcc20ab4904b69469..fa6728c9e64a6794bac6c8e6fd5870c55ce156a5 100644 GIT binary patch delta 8448 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 K$Y(7o>HQCZSMl!v diff --git a/scripting/l4d2_detections.sp b/scripting/l4d2_detections.sp index 0943847..7207eb3 100644 --- a/scripting/l4d2_detections.sp +++ b/scripting/l4d2_detections.sp @@ -35,7 +35,7 @@ Bile Detections: */ stock bool IsPlayerBoomed(int client) { - return GetEntPropFloat(%0, Prop_Send, "m_vomitStart") + 20.1 > GetGameTime(); + return GetEntPropFloat(client, Prop_Send, "m_vomitStart") + 20.1 > GetGameTime(); } stock bool IsAnyPlayerBoomed() { for(int i = 1; i <= MaxClients; i++) { @@ -50,7 +50,7 @@ stock bool AnyRecentBileInPlay(int ignore) { return false; } -stock int GetEntityCountNear(const float[3] srcPos, float radius = 50000.0) { +stock int GetEntityCountNear(const float srcPos[3], float radius = 50000.0) { float pos[3]; int count; int entity = -1; @@ -74,7 +74,7 @@ stock int L4D_SpawnCommonInfected2(const float vPos[3], const float vAng[3] = { return entity; } -PlayerDetections[MAXPLAYERS+1] detections; +PlayerDetections detections[MAXPLAYERS+1]; GlobalForward fwd_PlayerDoubleKit, fwd_NoHordeBileWaste, fwd_DoorFaceCloser, fwd_CheckpointDoorFaceCloser; @@ -100,6 +100,7 @@ public void OnPluginStart() { HookEvent("item_pickup", Event_ItemPickup); HookEvent("door_close", Event_DoorClose); + HookEvent("heal_success", Event_HealSuccess); } // Called on map changes too, we want this: @@ -107,7 +108,7 @@ public void OnClientDisconnect(int client) { detections[client].Reset(); } -public Action Event_ItemPickup(Event event, const char[] name, bool dontBroadcast) { +public void Event_ItemPickup(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(event.GetInt("userid")); if(client && L4D_IsInLastCheckpoint(client)) { static char itmName[32]; @@ -123,7 +124,16 @@ public Action Event_ItemPickup(Event event, const char[] name, bool dontBroadcas } } -public Action Event_DoorClose(Event event, const char[] name, bool dontBroadcast) { +public void Event_HealSuccess(Event event, const char[] name, bool dontBroadcast) { + int client = GetClientOfUserId(event.GetInt("userid")); + if(client) { + int target = GetClientOfUserId(event.GetInt("subject")); + int amount = event.GetInt("health_restored"); + PrintToConsoleAll("[Debug] %N healed %N (+%d health)", client, target, amount); + } +} + +public void Event_DoorClose(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(event.GetInt("userid")); if(fwd_DoorFaceCloser.FunctionCount > 0 && client) { bool isCheckpoint = event.GetBool("checkpoint"); From 86573cf1a611e16de46ff0676568f67db457bbc7 Mon Sep 17 00:00:00 2001 From: Jackz Date: Wed, 24 Aug 2022 11:01:08 -0500 Subject: [PATCH 5/6] Remove debug --- plugins/l4d2_ai_tweaks.smx | Bin 3750 -> 3654 bytes scripting/l4d2_ai_tweaks.sp | 2 -- 2 files changed, 2 deletions(-) diff --git a/plugins/l4d2_ai_tweaks.smx b/plugins/l4d2_ai_tweaks.smx index aa1726267ce6793286c3986bd98aee241ce45844..d85830951a61a5d3db9c0918596f5dd02ca891a4 100644 GIT binary patch delta 3485 zcmZ9LX*^Va!-vmIWQ$TJWlMz6SQ5%sQv3@;Lb6wu?Au^0b(bGo1V^SpRoT<3fJw(t3!7Y8r;Nd(l_H@yvq!Swk6z(yVbj_m>f z&<=wh|4k)+05}Nw)=>Zu=LUd7ke?6*fU{5{Ag(}u1xhi9i2u&ZK>h}D;R67m0Qm=T z0C0yoFG7x#003JkuR}bS0KoqY%%H&>w2%#@9RyYq00f})fJlYh5z0`A4ano6db0EQHh=z2UWqI0*yBRtDW=v!rV#>Hg~hL60e-g6!QXQ;>Z;;Rwm)>z zrt9YGdjonW>JskO*_O->q`!6mHLpsxWDhhSYLVej6QAYRIFjqA;NlwquQj3P9w!&T zgKg<3?g=-nrlPMPd%Q%fpBEf=oJ^#836S}*I#Cq2j6^075#tPacl}F1wYx* z2jDmaIS#Ha?W+RcOsB30lJ(%hMt@uHV(Y=PzTMAT>r(&jf&E|K0eJ8~^mwibF03Zf zSC9=QB{)CE&IrPei~CB#)g^rsxF%p&&9lA+Y>aej&Ji+=jX|U~O8OG+`FTH~26Eb3 z($zR8BB*g(6DX`a_r!z0pToyFp^Md&@NHvbNMSXld|lZYl~k}u=!u^oSqv+DgzSec z<({y|hTWvcb58hS!;I+)oVJ7;nEAhbJM4_pf2(HT!B^;fJkUB+G0(ZaA%kk=`EH7(;Pc*tKcQuS{Sk7i+h`<^Y zXN`ABRdwFfW-KvjoIu){9;4LssQoEZ%hXuI1-)Bccoh1h{=A)ChNsJl_Nb~{J*jG$ z(ZlczR$mV;b7*vV^jpk6KBQTowql=lrvlk>}-kQf?8``SF>wKhLS!)YM ztw9#)t_H0=tTofO0t>YQ@|RR5-*^ai4&Dn77)6r9TDI_O=>GEqn-*{AN==iQUkFM% z<`sr@uL<%WetsJ#+DA|H7{KD1_wAK1m#`s2k&^d)vS!Ws1H8R|~Jm%XK27Hk9SYrJv=M__H zzCD{ZmRxI0ccnKatzV$_e)J-`p+4^$bK1)i@#|&kv{`w~*#b*EMIU)bUAN2gx`|8P zZzu16WtNw!Kd1e2B2B$4aR)ytFS7?;;aiFj`2xH2=0lcL9bdby=*vhAc*b&H)x*Nr z@qpIMx$$qXEhfBLnnHtT# z_@34Jl3!lsro~=gm&>$fPxtCM2o@_`NAE{EFOd!Tb5@J+@$~}z+lN8un09b}&$8JY z*E@t*gK-gx)wSAJ-T7VD(L7@!6vw}VTeu5tuFA9*@n7#Z)%ICP1`4^Wj)8wpP!=1j zvUk04voBQVw;3Vlt|_W5SD$@ioa~)%7G#bpz!61xNU6wsneTJ=8SD7BixmcMC%jX3 zDkf$b2{`FSO8G0$Ooe0B^0=F213cNf>b}8@pLYjvn4EPz|e5vZ>%8+WN)Xm3OA68Xi+oJ%`gT zEf3~94)#_2c)OSMm}copenIf``5bH$>Y#+0w;3tbGMNWCsk9DMU$YFJw&D>npSiK) zT~INNIhB+8dPV*A<0;oO{L|EB8f#I6=O+jD!&%7$rC6qHRIj9nE=KID#84zVV~F$c z?Dw6Rh1}&g`5YV^GWu;bUZRvcUE}JTalAgaj~zQv$R(x}AJTOTxg#0BKy=ppr|@PN z_gqO#Cy@c(tyLKG=$>`qLD(c{bst``v*2DGwM)~kDR!5|?OWjSB8C3S?(Ssbv5nE( zNP<7fDe>~xioUpO+}cjIR%|tQQE#6m`KvYZdx@5g-5dHa$KQ)A&;8`@7;sYJxG3ep z;IU0J=X_piCFetNUZ+TAmJM;I+DGf7{k`uEkIk}yH)j=$R`OFD9C{qtlWXi`zv^D) z5t)-b$N%=FON(v(KOSL*mq^-o3Bxu%R<-EDZ{(AeiI$r-d^JD_kqYytKYRp;)%Lml8#7Y@>QfFG#MJiaPX>+iWtm~`v=}MU z6ln?tlzzxku|I2a+#|#z+cQn~BeO z@z)Be=!~uhTMaoVvDTNZT4`$~TBBV^N1{kwB4v1O9aAAQt(_=uM4l>4_9Kk^s=m}n zs8COP1E*vUJNaaPBdF&SD&zzR%2UJReZt`F#*Qt?!iR>Y8oRBQ=;)HWMv3Mdfm|l8 zn{qC~VZ!yoR_+m>M}^^mK6=7VIY_#2fvlj@`Jt4WTZW@i$!qC&aSOddxvFR7&M8QQ zY(jEWr|G{431rNjd)<$RBEpU7Lc$M}O>hfdsGp}fyqPXgriV-;pGJb1WTf z?n(ZB)06RY-Z(QQZNRoI*;NJSC+b7Y+Ni^-%i5Q%f5apYBug4+U(g+J$&>D=Psu&& z)>72rpDy!xMaymA`X%G+WM#V`;ZrAml#Y`@yuxFW!aj?F(KsFlzE;?Gw+nAlXp$3) zD}JH(s+PH`N3?Mh`K~Q?Cw4zKE;<@Kw$Y56q4aJv3yg=92!&jJ<1eB6A$i6i5g1f z7f5k3jhlk@5OzoaG|tTfzf3*i+!C(jXCj3-#N*nE3ireDqKtK$CWT#5kAwqwo_qMdyU%(RJGobRLxJ1Ankan|-C{XP) zf_t)gv#GVNTfnwIiIlTr0E~svsZB*#E*t)S=yM|nt9~;QBK@Gk0q=+Xd7SVI#MX3*%!fhx9>R#0bK7!-AH`@hm6!)+>#4#K zu4MyN{myhSj*74Xr>?0;FkR^FM^~1w(~;CiR2yt`L@g}gfDcD5?C}u{7lxx;^zf9N z<8h3P?-7ik@4<8!gFOg-7{4xqQUvNFim{Uycn;h-FwPX&1XgVct}Gbc+L{4hJ*dOi z5dDMA)?~$+u&mi&P78oxRJUPFp-_A4jRB2raHOA*aG!;x4g8`JriEsx!tG@dZcX0g z#7?&%!?jqd&0>fRz6}0bMa&96pI-2yEp4&ZI3Vkjd6v#ov4?|g9q4zcwhn_6c^-p? zdpuNconiYARa>rQN;5LNb}t57w=*TbI%LUuMY>F#$Alfs6kn{)oJ?H*ebT<{s&oB3 zm_Ow`^D2KmST5h++Q+0p|JY)2VdIPav(c#pMV4Blt9BJf=TKWCuCg|Vt16fc`i(72 zznv`N*buo&u`^kCu6Uv|CtKs^b-j#6WJy(X`-9LXi)O`!A2NrWU+y9FGEhrA(IZk~ zYlyDEoBkOe8}f}deKp<8I8$yQES+2qBjnEC4n-vPCY22gSqmwa{DIH6WKaDMHD;J< delta 3581 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 Z%y?~Pc~8lx$q Date: Wed, 24 Aug 2022 12:55:04 -0500 Subject: [PATCH 6/6] State health --- plugins/l4d2_detections.smx | Bin 8623 -> 8326 bytes scripting/l4d2_detections.sp | 3 ++- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/l4d2_detections.smx b/plugins/l4d2_detections.smx index fa6728c9e64a6794bac6c8e6fd5870c55ce156a5..6aadb4b5a69de0264dd0ccdb340fa9328e78f0f3 100644 GIT binary patch delta 8149 zcmX|@1yoc|*v5B3Dd~^~K{}Xu~6+~?a0zlT-7slAY&j77f3gOF$gv#7>O0oI!g2vb1p;wk zd(6jv#5T5}!xjWG%%lKc0@gsmbA&12>jDWPd?2u@A^DvHSAay&X>Q4jAi+J>nQh!> zHmgu+($JMv%ooBn3>(gm=G>$*(IKg|NO+l~Ey%}Oj+Yg=?l@6Wt}SR)<5pYp(&mMS zkX(cm|Gk^#ekG1IVy>RsCBnOSB)xIV5Z$k9>F#Y zNDmTU&2GjClr{sBg~Ycb4x-sDTfJI1j?(uG-V%o=F(7G3j^g4Fqd*CsD=>NNh)7lB4f&5Z(VvbPJ|pKuVB|xz&t$PN8JP z;X))w{v^IJakNt?b#Zud9Hs<_Yc%hc{j|zFgG$AYQvxo=fD9q=Rqk%BTCGH0Anp_&wKo`HX>m9w z!?9Fd_TocW_WN<IK711t!<^FRNE|K6R5^aS(%Bqxfzdj;FS*dR7K@6dm zCWpB)p@BB1n=RXVL)J4{-(dEw0xWYMUL)z={b+6dy&wY|iVTrTvV&)a=^^kEFNFyJx79G!;)Pdv!q z+C!f*cwRlL$~pD=EPCj`8S$*jF%Csgxw&L%)3_G0lb|F^@dvrNs>BFx9W*{ZaHJ)M|` zb0ii&pO^b2&bclkB~6xa(Vh!Sxr1~jw?5^*yLpdn6eSR2VH>Wzk*Vid=ML@5LC@14 zSB&@V^^3o#HSMa647puzVRGb)^5JW1K3knQs0JDYcwz{@c4CG_WoB@ebKA@Q)=V^I!FArq&o4 zIZGcN$C-!m-2I600#aUtu1R>@ZdwKJYrO}NjL!Nn-L+$%keIc|jVmTrll?E| zz@hDDBgJL4h!=+P8Xw38{l29Vqdk&gQl!->mhEmotXHFai-j-mJVbny?h>G)lDG%D|bK(9lu^$^W#g{H# zD2!Nxueua6v6*0AW%^K}?#f#|>*EHSGjkhs*kM($s9Tmf(1w+T?3AtMd~ing`_ePU zX2S&EQDN$ZDJyS-HdpW#E#FbkhkCh5g}K{mk)dk(ddEWLt92QV9vR!#YUVJYIpU

>G6*k(5lU8YvlmR#Te#W1Gmb1|kE&suQQGx%}(?>pSP%5g5@Bme-*U z2easxVK=iT5qJ)R5li`&U(NRb)E8fKYNUMh9+U?&VJi^vBd!Q(d|6rnt3wp!bBgNk zqN`*r5mUQzVz1U7kHG&_>o6}^g)aQ~)PSsZ7S@?-xZeoGQU8IwmU|un!@y56e%NAO zp9j9;HQW;2XjZQ%ZPE3!LHvE^+YRKSVlWoDq#eaMG`T`cE;e5`D(?f=gMVadzhSI{ zIWLIPk4q*u-zHBV{2eS4O?`Ev+ib?XkULpXneR~?ka1RIXJhgFTQ`hH#&Ap>!BAN~ z7)Vrqty*~EYd#nT-v}tI#4wLf9J6kO>>chO9`5g2U$`N<)e+S+@@@Q~Euo=GN0Bvq zt9>n@8}&6;p6OwAE53ktyBn20!C~bV7114GYaOydd!t0&8YdvWVJ@=0KxkfBqaafk zI^z1%Oi22Dkap0hka4b8WTkw9*J+B6V1-VQokDR{86?L`xJ}ZTrtQ>^&rX2;R^kP^ zrz{8geAH}vPb@@7P|BLGBG551(gylL=->?P8Q@6&g11A`fCjj_5Da>w6&Y#L{;^(E z{S#^5h;PHUvIS;gy`}WJ1!k>4$kT%$wMidyjuD&m6I&?`yPdf8X2!|Xex04f^GMs@ z=Fq?A zh)8eZ7^^@#E;|IjxZ1L5UNw69^=0U?rBUIi$U;`2o9u+trgoM%BzmgGu;A=pKH3wV z8*VfyAXCYv&1-i$v>*5*H>@{kBqciUpqJOm_b zGo{N3U`UJAfXQzt*i|UJuM{$!fX9|kmg$&^8|awky{byw6qL-`bU$>;Ti`4fs;2HY zAKL$FLF1h<+&*YJ!8Ne|)&9R=ny+fqKz_QWs5`Vp%F^`f{PX@^O1c6sxi(2hY5mc` zmfx$lnBU{C5oyu`%$(Yg`8BA*vMPK@t_Mi#FbYyp=;-FpFR3#R;vM|Q=Pag~0}{qL z1D%0MK?Pos`1hYIpf3bgsq0cv&{w?aC9ZB}KKRqFv`H5)!&|eG$xhE89a6LdCNV-Lu>)_Py^BgX3bBaRA-? zES@H~7aRt<0>3*7=nIMefFC@YM3|oXdDntrBs*B>QUt==x8eNln4}?#xBNZQc|%)Y zK=DIuP%AtmG}j*_h4T*F2d)HdfpfqJupoh9X_RRcSc&op=`7h(;-}!J51I&?=6^}i ze~aR=r?Ce;!J)(7zt4ojgj;}T4cuD<)#+(4kywz#gN>tT!B=1n5I1-WL>09cwMid0 zLAssSH5O}zD~Y`f8{n#gc$L5?c6(O)9B-PFX6$%=w!H#Rz*;pqkDU7Wc9f-G_!(bJ zT1cCJw%jmQ(B!Ysn9I>AdX6(Co{-wIrZ3~TMH%!%d9CGd!gG-$A(nbzGn*44 zoOO#m?b_TcE}I{Ttts}*`dtBX^KLEMAO4!j&@ZP8@rpV*cxYb~MzR_?hs)L(@|t{~ z{N3O5z{1TjJM(*hcJ9k|`wg!dkIx%@khD2zqgOC_S;w!AQO@b3(lb!)HZ@sS&V%4y zzAZ{#D`C;mIWLws96>w?z)Fj+Kx^xRzxI6T&VgFLhZYn2Y2k%e%V~jW4U2)N#?fQ# z;sCjInzR`Ifmb;htNL^oQOdplO7FiVB}}%! z`)IBAxxhcdojn#WIw@o(McJbf1hlHe1&?2@>58Kg8=?- z5NGG-T==_9KKrw!@BBcNcT^5o1MCVi2MPYPUk2G=8z?$$I|)0>Ew5j;lYA%oPV$}1 zkI0XH{0V*}$rBI{_zag6M2bTSCdEw!rQ)Q5Q*re{`Z)SvecVydD9$K&6jul&G`boI zosE?!suLR}Vxh1%m}`KzWafrCYaR~@mo2eNTzEO{p2&9tbYo{S&RS*S~HK@aZFxJh8D^5;f#AAXYd(g@1`xHg(>vGGTkL*YOL3 zV@oliL(%;YARzBW-^+`{FN`s^X}i5pP*yB5ja-vN|72E>RY;`sepjKt+@;GRi6o|wdWfB$C zIVp+EsbhEo3TAkJkNUq23@Xyb8j-a{qEPq^dvgPFdA$#Ihb zkZ6>DCrf8!CtIfxcG2BCr90I+ojWBu^_0+ZO?pby-jg!&gc;&lZuV7-9$s!@B z(n_L<$kuz0Gvn@y7sXftZ25j6ONEEuqC`^v)vA)OhT*-gj?~5Ohy}IRvLq3z77vlM@)4hklUpTSO#qSR+umM*sXM;uQb{X=+ zeLG7}mP#jVU#@o$U-Q;QkfLZh5!e&Ogn`(R>k(0KO>~E61Bkv;CyESA3RVE0(<%j) zIt+v5K*6;3RQAM%cyLw}!%Ak<7^r==e>pbtXS(7;54_z=n|28GeJvX$C7b5rAA1P&EWJxBI4zpHw8Z!e|A^I?A!LB&uBJm3EeEb-huQSST9{yS*{ zp}ZO1Yl~}BtgFSiFjV@)qseKylz)elpyL=_oPcAyjEF5m69`0fp&JU>zj$ax$cT9(Ia7U(sYihI1L zJamqQJ5qlGoLctj^hHG8T5nZnrJcU=DSM}m{Sgj&l_G~fs;)%M_{k!gchhYfZK~;m zvj1V*wi~r)$mP#;{z^{q1oI{p-G7$B5|i?&)`wfWj~^O~R-Zq9O~k@!zRSP)jl-qM zY1Rkap3IU!mJ~KX+qX{GoVDTbcRXLm=dIN0=Qu}TAVa(BbM2QK_rCr$_zC7@PC80aDWpRkB3oujEk*t7 zjW2R7fQdorfaO|e`8GSD`>$+XIT1*GxgGlb<_h^TLWUdGe8p8IPm>{Kt`MD}yN{`m zVzE8iBoX7zxr)PLi;2zh5iF z7zo7v5Umhd7`%LG`VffyC97KPWG?xcSh3+?i5ls%H^x19iW-=cED)xh$gAgX92w|s zU0Yi6pMO&?Sg7MPs1?Tetytg5O=6sbQ?;IV)VZTp!fu#Di$s)Y!sep?rPC7L;Qp7Z!8c<*;ChwL-N&H``Ma2!d&RrMj2qglVKc0ZA*OCwN#TOZsA;1M`SolDg7AA zmgd7{BrAx6A*vqLoTU6@KjC+Z+xcs~x1oy+^E={bVTYRdu~(4n)Uj(^kuaz}ZbTDv z8gFUg`yA*m5fTpO*}?lD?|Ms@b|c0Ay( zL7J*E1-rz@qz1&4Ef30p^F?8)Fol3-p{)%ApY3j>-q?>|a zj2KysUo&QR;h3~o5r5$D@Ur4#teKecy{8c=4w=m^1U`ir3Y@yHo=^ zT8RSXbj1gS)0;lJQ6E7w&Ogq7x_&^(ZIY|Oq3@HeAYT$rdrX?($SUzPyIlSVpdK?8 z&=WaOk6E*-&V2bIF`u_RVsM2H6M@&)>@MB?uATRDFs6?tp##Sf^%^2) zH(Y&lNxG@^%RVQw4TEj{_{!55^PNg%^$o0RxrhteI&)O2x2TUourC8kjV;ZBbZs;5 z+Mi)U^=v&pWiUX?ioTUy^NZ5VqxCZP(9Nt+zng&P==l804ejRTFJ-A(gR(E8dk;%1 zI$%qs?>6M%6b7^$-h;V8kAL*#^==2hMer5ssRV81Q#42kClp?kB_k@Gydv$+6z-z; zxo_+CofXwwIl;H_?c9J!aKuDNQsqu7eWz>B%#BEWQp?@j)8+Lm>lW8Lrov2|>&nw` z!gF+8({%xK$GPPCuE|>latL#~j=IZh zj|JaS9=LNaaK~Vz0vZ-_dU|gJmk{qR!uymz9&{#b1fd11DRi=UuO zSMYws7{b+M@F||+z*}+;9u;P)w1|+(-9HDRY`BVFi_x4j`6UgwLdVfXalEL{>vvJE zAVr1PgRQAfF+JqoYbjLZie+bClxwCwcnsVw7keN82wqFB1g(S(EaQxcg$PfFui*H} zq7+u{cWOi*Jzi={Iym`l6MnX-w-VdwZ8E2i!4bw|$s24b${oCo5JoLTrGXSd;S9mN zsPZZ=gfFNAH(2r^QglUVWrOReFqHi1{Y64JesJtS*q80_F_X?EuA|aja69Ss`+=~k z(C8ds3gXqt7-f#bJ)nV$z4!2>P@x<-5aPE!e|er9P&5-=la=A0z*Ekw(u*1&92SpW zwmZn|$sV)?{ELv;yDHkLIdZM|*)Ckzb$Rm?1yO-xb|0eB>BG6YCg`sZ{_N0S3;xNX zXWFZ4IDwEde`Den@ZRuMjkCIt&Gi1p6j%mCnNNh$hQqVgQawAAYME`VU;}Qv0#P^Pukxd$FY9rJg z`_VeyZ1jV>vramc3>D}^=7L6diglhoIsNN(;o~gXCw&kY%o2C6FKVY&-~i*d9>NB! z63$bxyZ#}!CAH=XBYk_`F}ei&~sAE z_iyj-Dx!oZ;q_>=`DI1cD47EITI3?~X6+BK(#^q*g1xsDUI}&_)2n-4A2Q>3l>Hl8Q)-j3bzF-0)4Opqgl5T ze513zu#)|>G$MtE&K==wgOMRP=VV%BrTfJT4}SoMHvP9DZfsW@Z&oIi&&E#M_%9ZQ z9?ZdPE&C(uBPgz>p=$dEVYIc15#bb9Q`2uu-jER}z~gWB=hXIH#|Ybn&U@L@2CxzP;=p_}c^Wo+M0OrsKG~ zHj|t7HFd^`1Mk$QaF~qE=(tCgSmI&2C`Ko@QA?m%_hsObT++LHW9ew?vu-VJ_H=){f%6=U zSw)3;YA+$66TY$mxXU39rB$f=pT|=szstu}mDw2KKxhkz%BUzGzj%~U%&9o9ga0UE zrH^|tPLxZwOT~E7+pSXB>n2b2O!&Tb%Wv4neX#}qB~4sF$IEztf?Q~9J>ztuLK@eD z*(Clnt45mpH}pfi_*0)f4Bzi5Ta}6G44Yzz4r$!1sDMow5MQUpHW@WunZKz(ZXmGf zD`PMu^?uXy5z9TcmbbpAHtZzKmiX+c{pMMl8ehuD4TiX@Hv66p6QsZG*!<^KuUwY) zR8PjC#k>k#&27A6s}QtWC#C&dl`ZRQZ`}u|#gXwS~uc5^qXEn9ksFOr5M; zhW^>JVyL31jBzo#ospks`*|TAKfwd^+f9VX*yPLcKBds2-*$>N6jgc^YY;m}Tbwnt rBM?u%be;Z~+tux@@YT@!_?(A)G1n9y;L%y>1tS&bci{JIu2%m8t3l{K delta 8448 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 F{{vQ{iNgQ@ diff --git a/scripting/l4d2_detections.sp b/scripting/l4d2_detections.sp index 1840c2b..9d9624f 100644 --- a/scripting/l4d2_detections.sp +++ b/scripting/l4d2_detections.sp @@ -129,7 +129,8 @@ public void Event_HealSuccess(Event event, const char[] name, bool dontBroadcast if(client) { int target = GetClientOfUserId(event.GetInt("subject")); int amount = event.GetInt("health_restored"); - PrintToConsoleAll("[Debug] %N healed %N (+%d health)", client, target, amount); + int orgHealth = GetClientHealth(target) - amount; + PrintToConsoleAll("[Debug] %N healed %N (+%d health, was %d)", client, target, amount, orgHealth); } }