#include #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) { LH_LogPlayerEvent(j, "triggered", "zh_h_zone_take_over_simple", false); //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) { LH_LogPlayerEvent(j, "triggered", "zh_h_zone_take_over_1", false); SetEntProp(j, Prop_Data, "m_iFrags", frags + 5); } else if (damage_done_inside_fought_zone < 400) { LH_LogPlayerEvent(j, "triggered", "zh_h_zone_take_over_2", false); SetEntProp(j, Prop_Data, "m_iFrags", frags + 10); } else if (damage_done_inside_fought_zone < 800) { LH_LogPlayerEvent(j, "triggered", "zh_h_zone_take_over_3", false); SetEntProp(j, Prop_Data, "m_iFrags", frags + 15); } else if (damage_done_inside_fought_zone < 1200) { LH_LogPlayerEvent(j, "triggered", "zh_h_zone_take_over_4", false); SetEntProp(j, Prop_Data, "m_iFrags", frags + 20); } else if (damage_done_inside_fought_zone < 1500) { LH_LogPlayerEvent(j, "triggered", "zh_h_zone_take_over_5", false); SetEntProp(j, Prop_Data, "m_iFrags", frags + 25); } else { LH_LogPlayerEvent(j, "triggered", "zh_h_zone_take_over_6", false); 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. LH_LogPlayerEvent(j, "triggered", "zh_h_zone_take_over_simple", false); //rewarding empty zone take over with at least 1 frag int frags = GetClientFrags(j); SetEntProp(j, Prop_Data, "m_iFrags", frags + 1); } } }