From 2812dbce8c531b627066dc2f160dccc83640d187 Mon Sep 17 00:00:00 2001 From: jenz Date: Tue, 23 Jun 2026 01:16:19 +0200 Subject: [PATCH] only removing hlstats related calls --- .../zh_respawn_stop_no_hlstatsx.sp | 1314 +++++++++++++++++ 1 file changed, 1314 insertions(+) create mode 100755 zombie_hunting_respawn/zh_respawn_stop_no_hlstatsx.sp diff --git a/zombie_hunting_respawn/zh_respawn_stop_no_hlstatsx.sp b/zombie_hunting_respawn/zh_respawn_stop_no_hlstatsx.sp new file mode 100755 index 0000000..ca659e6 --- /dev/null +++ b/zombie_hunting_respawn/zh_respawn_stop_no_hlstatsx.sp @@ -0,0 +1,1314 @@ +#include +#include +#include +#include +#include +#include +#include +#define MAXZONES 66 +#define ZONENAMELENGTH 256 +int g_bBlockRespawn[MAXPLAYERS+1]; +char g_cZones[MAXZONES][ZONENAMELENGTH]; +int g_cZones_CT_count[MAXZONES]; +int g_cZones_ZM_count[MAXZONES]; +int g_client_in_zone[MAXPLAYERS + 1]; +int g_iCT_Damage_in_zone[MAXPLAYERS + 1]; +int g_iZone_fought_or_ct_controlled[MAXZONES]; +int g_iLast_Client_In_Zone[MAXPLAYERS + 1]; +int ping_ents[MAXPLAYERS + 1]; +int g_iAnnounce_zone_controll = 0; +bool g_permit_zone_benefits = false; + +bool g_is_zh_map = false; + +bool round_start_delay; + +bool ran_out_of_time = false; + +//spawning the markers +float ping_coorindates[MAXZONES][3]; +int zone_pings[MAXZONES]; + +static char g_cConfigZones[PLATFORM_MAX_PATH]; +int g_zoneCount = 0; +int client_target[MAXPLAYERS + 1]; +float g_fStartPos[MAXZONES][3]; +float g_fEndPos[MAXZONES][3]; +float g_human_damage_addition; +ConVar g_hRespawnTreshold; +ConVar g_hHealthRegenZM; +ConVar g_hHealthRegenAmount; +Handle hText; +Handle g_hZMZoneTimer = null; +Handle g_hZoneCounter = null; +Handle g_hZoneBenefits = null; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Plugin myinfo = +{ + name = "zombie hunting plugin", + author = "jenz", + description = "Disables respawning on zombie hunting maps after some deaths, adds zoning", + version = "2.0.0", + url = "www.unloze.com" +}; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnPluginStart() +{ + OnMapStart(); + g_hRespawnTreshold = CreateConVar("zh_respawn_count", "5.0", "zombie hunting respawn count", 0, true, 0.0, true, 100.0); + g_hHealthRegenZM = CreateConVar("zh_regenMaxHealth", "2000", "zombie hunting zombie max health for regen", 0, true, 0.0, true, 5000.0); + g_hHealthRegenAmount = CreateConVar("zh_regenAmount", "100", "zombie hunting zombie max health for regen", 0, true, 0.0, true, 5000.0); + for (int client; client < MaxClients; client++) + g_bBlockRespawn[client] = 0; + + ReadZoneFile(); + + HookEvent("round_start", OnRoundStart); + HookEvent("round_end", OnRoundEnd, EventHookMode_Pre); + HookEvent("player_death", OnClientDeath); + hText = CreateHudSynchronizer(); + + round_start_delay = true; + //timer for ZM zone benefits + g_hZMZoneTimer = CreateTimer(5.0, give_zm_zone_boosts, _, TIMER_REPEAT); + g_hZoneCounter = CreateTimer(5.0, announce_zone_controlls, _, TIMER_REPEAT); +} + +public Action announce_zone_controlls(Handle hTimer) +{ + if (g_is_zh_map) + { + float fought_zone = 0.0; + float ct_controlled_zone = 0.0; + float zm_controlled_zone = 0.0; + if (g_zoneCount == 0 || !g_permit_zone_benefits) + { + g_human_damage_addition = 1.0; //indicating no damage buffs + for (int i = 0; i < MaxClients; i++) + { + if (IsValidClient(i) && IsPlayerAlive(i)) + { + SetEntityGravity(i, 1.0); + } + } + return Plugin_Handled; + } + for (int i = 0; i < g_zoneCount; i++) + { + if (g_iZone_fought_or_ct_controlled[i] == 1) //fought over zone + { + fought_zone++; + } + if (g_iZone_fought_or_ct_controlled[i] == 2) //CT zone + { + ct_controlled_zone++; + } + if (g_iZone_fought_or_ct_controlled[i] == 3) //ZM zone + { + zm_controlled_zone++; + } + } + g_iAnnounce_zone_controll++; + int ct_control_percentage = RoundToFloor((ct_controlled_zone/ g_zoneCount) * 100); + int zm_control_percentage = RoundToFloor((zm_controlled_zone/ g_zoneCount) * 100); + int fought_percentage = RoundToFloor((fought_zone/ g_zoneCount) * 100); + if (g_iAnnounce_zone_controll >= 3) + { + PrintToChatAll("CT controll %i%s of zones. ZM controll %i%s of zones. %i%s of zones are fought over", + ct_control_percentage, "%", zm_control_percentage, "%", fought_percentage, "%"); + } + + if (zm_control_percentage > 70) + { + for (int i = 0; i < MaxClients; i++) + { + if (IsValidClient(i) && IsPlayerAlive(i)) + { + if (GetClientTeam(i) == CS_TEAM_T) + { + SetEntityGravity(i, 0.7); + } + else + { + SetEntityGravity(i, 1.0); + } + } + } + if (g_iAnnounce_zone_controll >= 3) + { + PrintToChatAll("ZM controll over 70%s of zones. Applying 30%s low grav", "%", "%"); + } + } + else + { + for (int i = 0; i < MaxClients; i++) + { + if (IsValidClient(i) && IsPlayerAlive(i)) + { + SetEntityGravity(i, 1.0); + } + } + } + + if (ct_control_percentage > 90) + { + g_human_damage_addition = 0.6; + if (g_iAnnounce_zone_controll >= 3) + { + PrintToChatAll("CT controll over 90%s of zones. Applying 60%s extra damage", "%", "%"); + } + } + else if (ct_control_percentage > 70) + { + g_human_damage_addition = 0.40; + if (g_iAnnounce_zone_controll >= 3) + { + PrintToChatAll("CT controll over 70%s of zones. Applying 40%s extra damage", "%", "%"); + } + } + else if (ct_control_percentage > 50) + { + g_human_damage_addition = 0.2; + if (g_iAnnounce_zone_controll >= 3) + { + PrintToChatAll("CT controll over 50%s of zones. Applying 20%s extra damage", "%", "%"); + } + } + else + { + g_human_damage_addition = 1.0; //indicating no damage buffs + } + if (g_iAnnounce_zone_controll >= 3) + { + g_iAnnounce_zone_controll = 0; + } + } + return Plugin_Handled; +} + +public void OnClientPutInServer(int client) +{ + if (g_is_zh_map) + { + SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage); + } +} + +public Action OnTakeDamage(int client, int &attacker, int &inflictor, float &damage, int &damagetype) +{ + if (g_is_zh_map) + { + if (IsValidClient(attacker) && GetClientTeam(attacker) == CS_TEAM_CT && g_human_damage_addition != 1.0) + { + damage += (g_human_damage_addition * damage); + return Plugin_Changed; + } + } + + return Plugin_Continue; +} + +public Action give_zm_zone_boosts(Handle hTimer) +{ + if (!g_is_zh_map) + { + return Plugin_Handled; + } + + for (int client; client < MaxClients; client++) + { + if (IsValidClient(client) && IsPlayerAlive(client) && GetClientTeam(client) == CS_TEAM_T) + { + int index = g_client_in_zone[client]; + //the player is zm, inside a zone and the zone has no humans present, so its a zm zone where he should get extra healed + if (index != -1 && g_cZones_CT_count[index] == 0) + { + //giving zm inside of zm controlled zone extra health regeneration + int client_health = GetEntData(client, FindDataMapInfo(client, "m_iHealth")); + if (client_health < g_hHealthRegenZM.IntValue) + { + SetEntProp(client, Prop_Send, "m_iHealth", client_health + g_hHealthRegenAmount.IntValue, 1); + } + } + } + } + return Plugin_Handled; +} + +public void OnPluginEnd() +{ + CloseHandle(hText); + if (g_hZMZoneTimer != null) + delete g_hZMZoneTimer; + if (g_hZoneCounter != null) + delete g_hZoneCounter; + if (g_hZoneBenefits != null) + { + delete g_hZoneBenefits; + g_hZoneBenefits = INVALID_HANDLE; + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientDisconnect(int client) +{ + if (g_is_zh_map) + { + g_iCT_Damage_in_zone[client] = 0; + client_target[client] = 0; + g_client_in_zone[client] = -1; + adjust_clients(); //calling GetClientTeam inside adjust_clients complaints that client already disconnected. + g_bBlockRespawn[client] = 0; + SDKUnhook(client, SDKHook_OnTakeDamage, OnTakeDamage); + } +} + +public void adjust_clients() +{ + if (!g_is_zh_map) + { + return; + } + for (int i = 0; i < MAXZONES; i++) + { + g_cZones_CT_count[i] = 0; + g_cZones_ZM_count[i] = 0; + } + + for (int i = 0; i <= g_zoneCount; i++) + { + for (int client; client < MaxClients; client++) + { + if (IsValidClient(client) && IsPlayerAlive(client) && g_client_in_zone[client] == i) + { + if (GetClientTeam(client) == CS_TEAM_CT) + { + g_cZones_CT_count[i]++; + } + else + { + g_cZones_ZM_count[i]++; + } + } + } + } + UpdateMarkers(); +} + +public void OnRoundEnd(Event hEvent, const char[] sEvent, bool bDontBroadcast) +{ + if (g_is_zh_map) + { + if(g_hZoneBenefits != INVALID_HANDLE) + { + delete g_hZoneBenefits; + g_hZoneBenefits = INVALID_HANDLE; + } + round_start_delay = true; + bool found_alive_zm = false; + for (int client = 0; client < MaxClients; client++) + { + if (IsValidClient(client) && GetClientTeam(client) == CS_TEAM_T && IsPlayerAlive(client)) + { + found_alive_zm = true; + } + } + + if (found_alive_zm) + { + for (int client = 0; client < MaxClients; client++) + { + if (IsValidClient(client) && GetClientTeam(client) == CS_TEAM_CT) + { + ForcePlayerSuicide(client); + } + } + PrintToChatAll("Humans failed!"); + PrintToChatAll("Humans failed!"); + PrintToChatAll("Humans failed!"); + } + for (int i = 0; i <= g_zoneCount; i++) + { + for (int j = zone_pings[i]; j < zone_pings[i + 1]; j++) + { + RemovePing(j); + } + } + } +} + +public void OnMapEnd() +{ + if (g_is_zh_map) + { + for (int i = 0; i <= g_zoneCount; i++) + { + for (int j = zone_pings[i]; j < zone_pings[i + 1]; j++) + { + RemovePing(j); + /* Should hopefully help prevent these crashes + L 11/26/2024 - 16:59:11: (70.62%) 1447 prop_dynamic + Nov 26 16:59:11 unloze script[1920069]: L 11/26/2024 - 16:59:11: Total edicts: 2049 + Nov 26 16:59:11 unloze script[1920069]: ED_Alloc: no free edicts + Nov 26 16:59:11 unloze script[1920069]: L 11/26/2024 - 16:59:11: Engine error: ED_Alloc: no free edicts + */ + } + } + } +} + +public Action permit_zone_benefits(Handle hTimer) +{ + if (!g_is_zh_map) + { + return Plugin_Handled; + } + g_permit_zone_benefits = true; + return Plugin_Handled; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnRoundStart(Event hEvent, const char[] sEvent, bool bDontBroadcast) +{ + if (g_is_zh_map) + { + g_permit_zone_benefits = false; + g_hZoneBenefits = CreateTimer(35.0, permit_zone_benefits); + g_human_damage_addition = 1.0; + for (int client = 0; client < MaxClients; client++) + { + g_bBlockRespawn[client] = 0; + if (IsValidClient(client)) + { + g_iCT_Damage_in_zone[client] = 0; + } + g_client_in_zone[client] = -1; + } + + for (int i = 0; i < MAXZONES; i++) + { + g_cZones_CT_count[i] = 0; + g_cZones_ZM_count[i] = 0; + g_iZone_fought_or_ct_controlled[i] = -1; + g_iLast_Client_In_Zone[i] = 0; + } + round_start_delay = true; + CreateTimer(5.0, enable_pings); + } +} + +public Action enable_pings(Handle timer, any data) +{ + if (!g_is_zh_map) + { + return Plugin_Handled; + } + round_start_delay = false; + return Plugin_Handled; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientDeath(Event hEvent, const char[] sEvent, bool bDontBroadcast) +{ + if (g_is_zh_map) + { + int victim = GetClientOfUserId(hEvent.GetInt("userid")); + g_client_in_zone[victim] = -1; + adjust_clients(); + SetEntityRenderColor(victim, 255, 255, 255, 255); + if (g_bBlockRespawn[victim] > g_hRespawnTreshold.IntValue) + return; + PrintToChat(victim, "\x04[ZR]\x01 You have %i respawns left for this round.", g_hRespawnTreshold.IntValue - g_bBlockRespawn[victim]); + g_bBlockRespawn[victim]++; + } +} + +public void ZR_OnClientInfected(int client, int attacker, bool motherInfect, bool respawnOverride, bool respawn) +{ + if (g_is_zh_map) + { + int index = g_client_in_zone[client]; + if (index != -1) + { + //client got infected inside a specific zone, reduce human count inside that specific zone by 1 + if (g_cZones_CT_count[index] > 0) + { + g_cZones_CT_count[index]--; + } + g_cZones_ZM_count[index]++; + UpdateMarkers(); + } + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- + +stock bool IsValidClient(int client) +{ + if (client > 0 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client)) + return true; + return false; +} + +public float get_power_distance(int target_player, float pos[3]) +{ + if (!g_is_zh_map) + { + return 0.0; + } + float vec[3]; + GetClientAbsOrigin(target_player, vec); + return GetVectorDistance(vec, pos); +} + +public Action ZR_OnClientRespawn(&client, &ZR_RespawnCondition:condition) +{ + if (g_is_zh_map) + { + if (g_bBlockRespawn[client] > g_hRespawnTreshold.IntValue) + return Plugin_Handled; + find_teleport_target(client); + } + return Plugin_Continue; +} + +public void find_teleport_target(int client) +{ + if (!g_is_zh_map) + { + return; + } + //teleport player to team members with farthest distance to enemy just. + //checking all alive clients to determine which client has highest dist_target to its closest enemy + float total_furthest_distance = -1.0; + int total_nearest = -1; + for (int i = 1; i <= MaxClients; i++) + { + //if player would get stuck being teleported dont teleport them to this player + if (!IsValidClient(i) || !IsPlayerAlive(i)) + { + continue; + } + if (IsPlayerStuck(i) != -1) + { + continue; + } + float nearestdistance = -1.0; + int nearest = -1; + for (int j = 1; j <= MaxClients; j++) + if (IsValidClient(j) && IsPlayerAlive(j) && GetClientTeam(i) != GetClientTeam(j) && GetClientTeam(i) == CS_TEAM_CT) + { + float pos[3]; + GetEntPropVector(i, Prop_Send, "m_vecOrigin", pos); + float dist_target = get_power_distance(j, pos); + if (nearestdistance < 0 || dist_target < nearestdistance) + { + nearest = i; + nearestdistance = dist_target; + } + } + //the closest enemy to this player is further away than previous players closest enemy + if (nearestdistance > total_furthest_distance) + { + total_furthest_distance = nearestdistance; + total_nearest = nearest; + } + } + if (IsValidClient(total_nearest)) + { + client_target[client] = total_nearest; + CreateTimer(0.0, tp_client, client); + } +} + +stock int IsPlayerStuck(int client) { + float vecMin[3]; + float vecMax[3]; + float vecOrigin[3]; + + GetClientMins(client, vecMin); + GetClientMaxs(client, vecMax); + vecMax[2] = 63.0; + vecMin[2] += 1.0; + GetClientAbsOrigin(client, vecOrigin); + + TR_TraceHullFilter(vecOrigin, vecOrigin, vecMin, vecMax, MASK_PLAYERSOLID, TraceRayDontHitPlayerAndWorld); + return TR_GetEntityIndex(); +} + +public bool TraceRayDontHitPlayerAndWorld(int entityhit, int mask) { + return entityhit>MaxClients +} +public bool TraceRayHitOnlyEnt(int entityhit, int mask, any data) { + return entityhit==data; +} + +public void OnClientPostAdminCheck(int client) +{ + if (g_is_zh_map) + { + g_iCT_Damage_in_zone[client] = 0; + client_target[client] = 0; + g_client_in_zone[client] = -1; + } +} + +public Action tp_client(Handle timer, int client) +{ + if (!g_is_zh_map) + { + return Plugin_Handled; + } + if (IsValidClient(client) && IsValidClient(client_target[client])) + { + float posd[3]; + GetEntPropVector(client_target[client], Prop_Send, "m_vecOrigin", posd); + TeleportEntity(client, posd, NULL_VECTOR, NULL_VECTOR); + PrintToChat(client, "Respawned you at player: %N", client_target[client]); + client_target[client] = 0; + } + return Plugin_Handled; +} + +public void unloze_zoneLeave(int client, char[] zone) +{ + if (g_is_zh_map) + { + int index = g_client_in_zone[client]; + if (index < 0) + { + return; + } + + g_client_in_zone[client] = -1; + g_iCT_Damage_in_zone[client] = 0; + if (GetClientTeam(client) == CS_TEAM_CT) + { + if (g_cZones_CT_count[index] > 0) + { + g_cZones_CT_count[index]--; + } + } + else + { + if (g_cZones_ZM_count[index] > 0) + { + g_cZones_ZM_count[index]--; + } + } + SetEntityRenderColor(client, 255, 255, 255, 255); + UpdateMarkers(); + } +} + +public void unloze_zoneCreated() +{ + if (g_is_zh_map) + { + ReadZoneFile(); + } +} + +public Action retry_zoneEntry(Handle timer, DataPack data) +{ + if (!g_is_zh_map) + { + return Plugin_Handled; + } + ResetPack(data); + char zone[256]; + data.ReadString(zone, sizeof(zone)); + int client_serial = data.ReadCell(); + delete data; + + int client; + if ((client = GetClientFromSerial(client_serial)) != 0) + { + //by the time its recalled should the player have left the previous zone already + unloze_zoneEntry(client, zone); + } + return Plugin_Handled; +} + +public void unloze_zoneEntry(int client, char[] zone) +{ + if (g_is_zh_map) + { + int index = -1; + //unfortunately it can happen that a zone is entered before the current one is left, which can lead to -1 index + //when leaving the zone again. + //example: Enter new zone before old is left -> leave old zone -> index is -1 -> leave current zone -> leave forward is called before entering new zone is called -> + //tries to do -- on a array index where the index is -1 + if (g_client_in_zone[client] != -1) + { + //the previous zone has to be left before we recognize the client entering the new zone + //only special cases are roundstart/respawning + DataPack hDataPack = new DataPack(); + hDataPack.WriteString(zone); + hDataPack.WriteCell(GetClientSerial(client)); + CreateTimer(0.2, retry_zoneEntry, hDataPack); + return; + } + for (int i = 0; i < g_zoneCount; i++) + { + if (StrEqual(g_cZones[i], zone)) + { + index = i; + break; + } + } + g_client_in_zone[client] = index; + + g_iCT_Damage_in_zone[client] = PlayerRankings_GetClientDamage(client); + if (GetClientTeam(client) == CS_TEAM_CT) + { + g_cZones_CT_count[index]++; + } + else + { + g_cZones_ZM_count[index]++; + } + g_iLast_Client_In_Zone[index] = client; + display_hud_text(index, client); + UpdateMarkers(); + } +} + + + +public void handle_pings(int i, int pingtype) +{ + if (!g_is_zh_map) + { + return; + } + if (round_start_delay) + { + return; //preventing pings from spawning exactly on roundStart as it might cause too many entities + } + for (int j = zone_pings[i]; j < zone_pings[i + 1]; j++) + { + //the ping is atm not the skull, will be changed to skull. + RemovePing(j); + if (!ran_out_of_time) + { + int timeleft = 0; + GetMapTimeLeft(timeleft); + if (timeleft <= 0) + { + ran_out_of_time = true; + } + } + //these jewish tricks should stop the crashing when switching map because the prop_dynamics are not around anymore. + //its not the last round because timeleft is not 0 + //there is also atm no nextmap set for the server through mapchooser. This confirms that the mapvote did not set it and an + //admin also did not set it yet. + //just checking GetNextmap will not suffice because we always have a nextmap set. + if (!HasEndOfMapVoteFinished() && !ran_out_of_time) + { + SpawnPing(pingtype, ping_coorindates[j], j); + for (int client = 0; client < MaxClients; client++) + { + if (IsValidClient(client) && g_client_in_zone[client] == i) + { + display_hud_text(i, client); + } + } + } + } +} + +public void display_hud_text(int index, int client) +{ + if (!g_is_zh_map) + { + return; + } + if (hText != INVALID_HANDLE) + { + char msg[256]; + if (g_cZones_CT_count[index] > 0 && g_cZones_ZM_count[index] > 0) + { + Format(msg, sizeof(msg), "Contested zone"); + SetHudTextParams(0.35, 0.85, 2.5, 255, 255, 255, 85); + ShowSyncHudText(client, hText, msg); + } + else if (g_cZones_CT_count[index] > 0) + { + Format(msg, sizeof(msg), "Human controlled zone"); + SetHudTextParams(0.35, 0.85, 2.5, 0, 0, 255, 85); + ShowSyncHudText(client, hText, msg); + SetEntityRenderColor(client, 0, 0, 255, 255); + } + else + { + Format(msg, sizeof(msg), "Zombie controlled zone"); + SetHudTextParams(0.35, 0.85, 2.5, 255, 0, 0, 85); + ShowSyncHudText(client, hText, msg); + SetEntityRenderColor(client, 255, 0, 0, 255); + } + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: Reads from file +//---------------------------------------------------------------------------------------------------- +public Action ReadZoneFile() +{ + if (g_is_zh_map) + { + int i_zoneTemp; + char l_cMapName[MAXZONES]; + GetCurrentMap(l_cMapName, sizeof(l_cMapName)); + Handle l_hZoneFile = INVALID_HANDLE; + char l_cLine[ZONENAMELENGTH]; + char sPart[4][32]; + BuildPath(Path_SM, g_cConfigZones, sizeof(g_cConfigZones), "configs/unloze_zones/%s.zones.txt", l_cMapName); + l_hZoneFile = OpenFile(g_cConfigZones, "r"); + if (l_hZoneFile == INVALID_HANDLE) + { + Handle kv = CreateKeyValues("Zones"); + KeyValuesToFile(kv, g_cConfigZones); + CloseHandle(kv); + delete l_hZoneFile; + return Plugin_Handled; + } + while (!IsEndOfFile(l_hZoneFile) && ReadFileLine(l_hZoneFile, l_cLine, sizeof(l_cLine))) + { + if (StrContains(l_cLine, "name", false) > -1) + { + ReplaceStrings(l_cLine, "name"); + Format(g_cZones[i_zoneTemp], sizeof(g_cZones), l_cLine); + } + if (StrContains(l_cLine, "cordinate_a", false) >= 0) + { + ReplaceString(l_cLine, sizeof(l_cLine), "\"", "", true); + ReplaceString(l_cLine, sizeof(l_cLine), "cordinate_a", "", true); + ExplodeString(l_cLine, " ", sPart, 4, 32); + g_fStartPos[i_zoneTemp][0] = StringToFloat(sPart[0]);//reading first vector + g_fStartPos[i_zoneTemp][1] = StringToFloat(sPart[1]);//reading second vector + g_fStartPos[i_zoneTemp][2] = StringToFloat(sPart[2]);//reading third vector + } + if (StrContains(l_cLine, "cordinate_b", false) >= 0) + { + ReplaceString(l_cLine, sizeof(l_cLine), "\"", "", true); + ReplaceString(l_cLine, sizeof(l_cLine), "cordinate_b", "", true); + ExplodeString(l_cLine, " ", sPart, 4, 32); + g_fEndPos[i_zoneTemp][0] = StringToFloat(sPart[0]); + g_fEndPos[i_zoneTemp][1] = StringToFloat(sPart[1]); + g_fEndPos[i_zoneTemp][2] = StringToFloat(sPart[2]); + i_zoneTemp++; + } + } + g_zoneCount = i_zoneTemp; + delete l_hZoneFile; + } + return Plugin_Handled; +} + +public void OnMapStart() +{ + ran_out_of_time = false; + g_is_zh_map = false; + char sConfigFile[PLATFORM_MAX_PATH]; + BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/zh_maps.cfg"); + if(!FileExists(sConfigFile)) + { + LogMessage("Could not find config: \"%s\"", sConfigFile); + return; + } + char map[PLATFORM_MAX_PATH]; + GetCurrentMap(map, PLATFORM_MAX_PATH); + + new Handle:fileHandle = OpenFile(sConfigFile, "r" ); + char lineBuffer[256]; + while( !IsEndOfFile( fileHandle ) && ReadFileLine( fileHandle, lineBuffer, sizeof( lineBuffer ) ) ) + { + TrimString( lineBuffer ); + if (StrEqual(lineBuffer, map, false)) + { + g_is_zh_map = true; + break; + } + } + CloseHandle( fileHandle ); + + if (!g_is_zh_map) + { + return; + } + ReadZoneFile(); + + + g_human_damage_addition = 1.0; + //resetting coordinates and setup. + for (int i = 0; i < MAXZONES; i++) + { + ping_coorindates[i][0] = 0.0; + ping_coorindates[i][1] = 0.0; + ping_coorindates[i][2] = 0.0; + zone_pings[i] = 0; + } + + char g_cMapname[ZONENAMELENGTH]; + GetCurrentMap(g_cMapname, sizeof(g_cMapname)); + if (StrEqual(g_cMapname, "zm_cbble_b3", false)) + { + ping_coorindates[0][0] = -1321.18; + ping_coorindates[0][1] = 635.93; + ping_coorindates[0][2] = 15.00; + ping_coorindates[1][0] = -1228.51; + ping_coorindates[1][1] = 1097.70; + ping_coorindates[1][2] = 15.00; + zone_pings[1] = 2; //first zone thats iterated. + + ping_coorindates[2][0] = -1313.29; + ping_coorindates[2][1] = 481.83; + ping_coorindates[2][2] = 15.00; + ping_coorindates[3][0] = -1026.88; + ping_coorindates[3][1] = -543.23; + ping_coorindates[3][2] = 15.00 + 48.0; //higher terrain. + zone_pings[2] = 4; //second zone thats iterated, and so on and so on. + + ping_coorindates[4][0] = -857.17; + ping_coorindates[4][1] = -549.33; + ping_coorindates[4][2] = 15.00 + 48.0; + ping_coorindates[5][0] = -319.23; + ping_coorindates[5][1] = -1091.23; + ping_coorindates[5][2] = 15.00 + 48.0; //higher terrain. + zone_pings[3] = 6; + + ping_coorindates[6][0] = -178.41; + ping_coorindates[6][1] = -1096.69; + ping_coorindates[6][2] = 15.00 + 48.0; + ping_coorindates[7][0] = 135.89; + ping_coorindates[7][1] = 262.61; + ping_coorindates[7][2] = 15.00 + 48.0; //higher terrain. + zone_pings[4] = 8; + + ping_coorindates[8][0] = 149.52; + ping_coorindates[8][1] = 477.08; + ping_coorindates[8][2] = 15.00 + 48.0; + ping_coorindates[9][0] = 144.99; + ping_coorindates[9][1] = 927.54; + ping_coorindates[9][2] = 15.00 + 48.0; //higher terrain. + zone_pings[5] = 10; + + ping_coorindates[10][0] = 146.94; + ping_coorindates[10][1] = 1083.88; + ping_coorindates[10][2] = 15.00 + 48.0; + ping_coorindates[11][0] = -1074.73; + ping_coorindates[11][1] = 1087.19; + ping_coorindates[11][2] = 15.00; + zone_pings[6] = 12; + } + else if (StrEqual(g_cMapname, "cs_office", false)) + { + //not the actual values atm + ping_coorindates[0][0] = 1454.83; + ping_coorindates[0][1] = 585.43; + ping_coorindates[0][2] = -160.96; //-95.00 + zone_pings[1] = 1; + + ping_coorindates[1][0] = 1405.29; + ping_coorindates[1][1] = 927.91; + ping_coorindates[1][2] = -160.96; //-95.00 + ping_coorindates[2][0] = 890.47; + ping_coorindates[2][1] = 953.11; + ping_coorindates[2][2] = -160.96; //-95.00 + zone_pings[2] = 3; + + ping_coorindates[3][0] = 710.38; + ping_coorindates[3][1] = 958.05; + ping_coorindates[3][2] = -160.96; //-95.00 + ping_coorindates[4][0] = 661.59; + ping_coorindates[4][1] = 117.65; + ping_coorindates[4][2] = -160.96; //-95.00 + zone_pings[3] = 5; + + ping_coorindates[5][0] = 108.23; + ping_coorindates[5][1] = 92.75; + ping_coorindates[5][2] = -160.96; //-95.00 + ping_coorindates[6][0] = 96.99; + ping_coorindates[6][1] = -330.89; + ping_coorindates[6][2] = -160.96; //-95.00 + zone_pings[4] = 7; + + ping_coorindates[7][0] = -224.44; + ping_coorindates[7][1] = -499.20; + ping_coorindates[7][2] = -160.96; //-95.00 + ping_coorindates[8][0] = 96.99; + ping_coorindates[8][1] = -501.89; + ping_coorindates[8][2] = -160.96; //-95.00 + ping_coorindates[9][0] = 670.37; + ping_coorindates[9][1] = -512.63; + ping_coorindates[9][2] = -160.96; //-95.00 + ping_coorindates[10][0] = 957.84; + ping_coorindates[10][1] = -506.23; + ping_coorindates[10][2] = -160.96; //-95.00 + zone_pings[5] = 11; + + ping_coorindates[11][0] = 673.70; + ping_coorindates[11][1] = -212.05; + ping_coorindates[11][2] = -160.96; //-95.00 + zone_pings[6] = 12; + + ping_coorindates[12][0] = 972.64; + ping_coorindates[12][1] = -151.94; + ping_coorindates[12][2] = -160.96; //-95.00 + ping_coorindates[13][0] = 972.64; + ping_coorindates[13][1] = 98.05; + ping_coorindates[13][2] = -160.96; //-95.00 + zone_pings[7] = 14; + + ping_coorindates[14][0] = 1215.49; + ping_coorindates[14][1] = 526.93; + ping_coorindates[14][2] = -160.96; //-95.00 + zone_pings[8] = 15; + + ping_coorindates[15][0] = 1374.12; + ping_coorindates[15][1] = 171.48; + ping_coorindates[15][2] = -160.96; //-95.00 + zone_pings[9] = 16; + + ping_coorindates[16][0] = 1775.58; + ping_coorindates[16][1] = 151.76; + ping_coorindates[16][2] = -160.96; //-95.00 + ping_coorindates[17][0] = 1769.61; + ping_coorindates[17][1] = -462.40; + ping_coorindates[17][2] = -160.96; //-95.00 + zone_pings[10] = 18; + + ping_coorindates[18][0] = 1461.20; + ping_coorindates[18][1] = -480.59; + ping_coorindates[18][2] = -160.96; //-95.00 + zone_pings[11] = 19; + + ping_coorindates[19][0] = 1388.60; + ping_coorindates[19][1] = -178.14; + ping_coorindates[19][2] = -160.96; //-95.00 + zone_pings[12] = 20; + + ping_coorindates[20][0] = 966.46; + ping_coorindates[20][1] = -893.44; + ping_coorindates[20][2] = -160.96; //-95.00 + zone_pings[13] = 21; + + ping_coorindates[21][0] = 945.39; + ping_coorindates[21][1] = -1136.16; + ping_coorindates[21][2] = -190.96; //-95.00 + ping_coorindates[22][0] = 716.53; + ping_coorindates[22][1] = -1882.94; + ping_coorindates[22][2] = -325.00; //-95.00 + ping_coorindates[23][0] = 645.86; + ping_coorindates[23][1] = -1426.71; + ping_coorindates[23][2] = -280.00; //-95.00 + zone_pings[14] = 24; + + ping_coorindates[24][0] = 426.91; + ping_coorindates[24][1] = -891.43; + ping_coorindates[24][2] = -225.00; //-95.00 + zone_pings[15] = 25; + + ping_coorindates[25][0] = 421.71; + ping_coorindates[25][1] = -1408.24; + ping_coorindates[25][2] = -280.00; //-95.00 + zone_pings[16] = 26; + + ping_coorindates[26][0] = -1211.93; + ping_coorindates[26][1] = -1842.44; + ping_coorindates[26][2] = -335.00; //-95.00 + ping_coorindates[27][0] = 401.20; + ping_coorindates[27][1] = -1872.70; + ping_coorindates[27][2] = -335.00; //-95.00 + zone_pings[17] = 28; + + ping_coorindates[28][0] = -1197.14; + ping_coorindates[28][1] = -1292.59; + ping_coorindates[28][2] = -335.00; //-95.00 + zone_pings[18] = 29; + + ping_coorindates[29][0] = -1603.39; + ping_coorindates[29][1] = -1383.98; + ping_coorindates[29][2] = -325.00; //-95.00 + zone_pings[19] = 30; + + ping_coorindates[30][0] = -1565.33; + ping_coorindates[30][1] = -648.76; + ping_coorindates[30][2] = -240.00; //-95.00 + ping_coorindates[31][0] = -1578.84; + ping_coorindates[31][1] = -234.01; + ping_coorindates[31][2] = -240.00; //-95.00 + zone_pings[20] = 32; + + ping_coorindates[32][0] = -896.58; + ping_coorindates[32][1] = -1404.99; + ping_coorindates[32][2] = -325.00; //-95.00 + zone_pings[21] = 33; + + ping_coorindates[33][0] = -974.14; + ping_coorindates[33][1] = 249.19; + ping_coorindates[33][2] = -175.00; //-95.00 + ping_coorindates[34][0] = -1061.58; + ping_coorindates[34][1] = -30.77; + ping_coorindates[34][2] = -335.00; //-95.00 + ping_coorindates[35][0] = -1174.68; + ping_coorindates[35][1] = -738.16; + ping_coorindates[35][2] = -325.00; //-95.00 + zone_pings[22] = 36; + + ping_coorindates[36][0] = -319.48; + ping_coorindates[36][1] = -790.84; + ping_coorindates[36][2] = -280.00; //-95.00 + ping_coorindates[37][0] = 91.64; + ping_coorindates[37][1] = -843.01; + ping_coorindates[37][2] = -225.00; //-95.00 + zone_pings[23] = 38; + + ping_coorindates[38][0] = -561.65; + ping_coorindates[38][1] = -267.70; + ping_coorindates[38][2] = -160.00; //-95.00 + ping_coorindates[39][0] = -184.50; + ping_coorindates[39][1] = 100.97; + ping_coorindates[39][2] = -160.00; //-95.00 + ping_coorindates[40][0] = -855.69; + ping_coorindates[40][1] = 250.49; + ping_coorindates[40][2] = -160.00; //-95.00 + zone_pings[24] = 41; + + ping_coorindates[41][0] = -589.94; + ping_coorindates[41][1] = 614.19; + ping_coorindates[41][2] = -160.00; //-95.00 + zone_pings[25] = 42; + + ping_coorindates[42][0] = -1131.05; + ping_coorindates[42][1] = 533.00; + ping_coorindates[42][2] = -325.00; //-95.00 + ping_coorindates[43][0] = -960.03; + ping_coorindates[43][1] = 555.42; + ping_coorindates[43][2] = -175.00; //-95.00 + zone_pings[26] = 44; + + ping_coorindates[44][0] = -728.83; + ping_coorindates[44][1] = 535.22; + ping_coorindates[44][2] = -360.00; //-95.00 + ping_coorindates[45][0] = -728.83; + ping_coorindates[45][1] = -32.00; + ping_coorindates[45][2] = -360.00; //-95.00 + zone_pings[27] = 46; + } +} + +stock void ReplaceStrings(char[] str, char[] strReplace) +{ + char l_cstrFix[MAXZONES]; + Format(l_cstrFix, sizeof(l_cstrFix), str); + ReplaceString(l_cstrFix, sizeof(l_cstrFix), "\"", ""); + ReplaceString(l_cstrFix, sizeof(l_cstrFix), strReplace, ""); + TrimString(l_cstrFix); + Format(str, sizeof(l_cstrFix), l_cstrFix); +} + +public void SpawnPing(int skin, float pos[3], int index) +{ + if (!g_is_zh_map) + { + return; + } + int Ent = CreateEntityByName("prop_dynamic"); + SetEntityModel(Ent, "models/unloze/unloze_ping.mdl"); + DispatchKeyValue(Ent, "modelscale", "1.5"); + + if (skin == 1) //fought over (skull) + SetVariantString("1"); + else if (skin == 2) //CT controlled (moon) + SetVariantString("2"); + else if (skin == 3) //ZM controlled (cross) + SetVariantString("3"); + + AcceptEntityInput(Ent, "Skin"); + DispatchSpawn(Ent); + TeleportEntity(Ent, pos, NULL_VECTOR, NULL_VECTOR); + ping_ents[index] = Ent; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void RemovePing(int index) +{ + if (!g_is_zh_map) + { + return; + } + if (ping_ents[index] != -1 && IsValidEdict(ping_ents[index])) + { + char m_szClassname[64]; + GetEdictClassname(ping_ents[index], m_szClassname, sizeof(m_szClassname)); + if (strcmp("prop_dynamic", m_szClassname)==0) + { + AcceptEntityInput(ping_ents[index], "Kill"); + } + } + ping_ents[index] = -1; +} + +public void UpdateMarkers() +{ + if (!g_is_zh_map) + { + return; + } + //this only works because of knowing that order of ping coordinates match with zone order. + for (int i = 0; i <= g_zoneCount; i++) + { + //PrintToChatAll("g_cZones_CT_count[i]: %i", g_cZones_CT_count[i]); + //PrintToChatAll("g_cZones_ZM_count[i]: %i", g_cZones_ZM_count[i]); + if (g_cZones_CT_count[i] > 0 && g_cZones_ZM_count[i] > 0) + { + //both humans and ZM in zone. + if (g_iZone_fought_or_ct_controlled[i] != 1) + { + handle_pings(i, 1); + g_iZone_fought_or_ct_controlled[i] = 1; //indicating zone is fought over + } + } + else if (g_cZones_CT_count[i] > 0) + { + //only humans in zone + //the zone just went from white (humans and zm in zone) to blue (only humans now in zone) + if (g_iZone_fought_or_ct_controlled[i] != 2) + { + g_iZone_fought_or_ct_controlled[i] = 2; + reward_ct_zone_points(i); + handle_pings(i, 2); + } + } + else if (g_cZones_ZM_count[i] > 0) + { + if (g_iZone_fought_or_ct_controlled[i] != 3) + { + g_iZone_fought_or_ct_controlled[i] = 3; + //zm controlled zone + reward_zm_zone_points(i); + handle_pings(i, 3); + } + } + else + { + if (g_iLast_Client_In_Zone[i] != 0) + { + int last_client_in_zone = g_iLast_Client_In_Zone[i]; + if (IsValidClient(last_client_in_zone) && IsPlayerAlive(last_client_in_zone) && GetClientTeam(last_client_in_zone) == CS_TEAM_CT) + { + //last guy was a CT + g_iZone_fought_or_ct_controlled[i] = 2; + handle_pings(i, 2); + } + else if (IsValidClient(last_client_in_zone) && IsPlayerAlive(last_client_in_zone) && GetClientTeam(last_client_in_zone) == CS_TEAM_T) + { + //last guy was a ZM + g_iZone_fought_or_ct_controlled[i] = 3; + handle_pings(i, 3); + } + else + { + //the client who was last here might have left or went spectate. + handle_pings(i, 1); + g_iZone_fought_or_ct_controlled[i] = 1; //indicating zone is fought over + } + } + else + { + //no client was in the zone in this round yet. setting it to the skull ping. + handle_pings(i, 1); + g_iZone_fought_or_ct_controlled[i] = 1; //indicating zone is fought over + } + } + } +} + +public void reward_zm_zone_points(int i) +{ + if (!g_is_zh_map) + { + return; + } + for (int j = 0; j < MaxClients; j++) + { + //is validclient, is ct, is alive, is inside the zone that just changed from fought to T controlled + if (IsValidClient(j) && GetClientTeam(j) == CS_TEAM_T && IsPlayerAlive(j) && g_client_in_zone[j] == i) + { + //rewarding empty zone take over with at least 1 frag + int frags = GetClientFrags(j); + SetEntProp(j, Prop_Data, "m_iFrags", frags + 1); + } + } +} + +public void reward_ct_zone_points(int i) +{ + if (!g_is_zh_map) + { + return; + } + for (int j = 0; j < MaxClients; j++) + { + //is validclient, is ct, is alive, is inside the zone that just changed from fought to CT controlled + if (IsValidClient(j) && GetClientTeam(j) == CS_TEAM_CT && IsPlayerAlive(j) && g_client_in_zone[j] == i) + { + int damage_done_inside_fought_zone = PlayerRankings_GetClientDamage(j) - g_iCT_Damage_in_zone[j]; + g_iCT_Damage_in_zone[j] = PlayerRankings_GetClientDamage(j); + //so uh, lets say the zone becomes CT, then fought over again, then CT again without the guy ever leaving it. + //this should ensure it only counts for what the guy did in damage since the takeover + if (damage_done_inside_fought_zone > 0) + { + int frags = GetClientFrags(j); + // Damage 0-1000 inside Zone + if (damage_done_inside_fought_zone < 200) + { + SetEntProp(j, Prop_Data, "m_iFrags", frags + 5); + } + else if (damage_done_inside_fought_zone < 400) + { + SetEntProp(j, Prop_Data, "m_iFrags", frags + 10); + } + else if (damage_done_inside_fought_zone < 800) + { + SetEntProp(j, Prop_Data, "m_iFrags", frags + 15); + } + else if (damage_done_inside_fought_zone < 1200) + { + SetEntProp(j, Prop_Data, "m_iFrags", frags + 20); + } + else if (damage_done_inside_fought_zone < 1500) + { + SetEntProp(j, Prop_Data, "m_iFrags", frags + 25); + } + else + { + SetEntProp(j, Prop_Data, "m_iFrags", frags + 30); + } + } + //this change might be very bad. it might overspam people with points if a zone constantly switches from controlled by CT + //to instead be fought over back and forth. but at least it makes it worth it to take over zones. + //rewarding empty zone take over with at least 1 frag + int frags = GetClientFrags(j); + SetEntProp(j, Prop_Data, "m_iFrags", frags + 1); + } + } +}