From 82ef472b348440786ecbff9bb0750cb7f4ae6877 Mon Sep 17 00:00:00 2001 From: Sergey Shorokhov Date: Tue, 16 Apr 2024 15:58:34 +0300 Subject: [PATCH] new ConVars: `redm_tickets`, `redm_tickets_hud_update_freq`, `redm_tickets_hud_blink_percent`, `redm_tickets_hud_type` --- .../addons/amxmodx/scripting/ReDeathmatch.sma | 1 + .../ReDeathmatch/Features/Tickets.inc | 199 ++++++++++++++++++ .../scripting/ReDeathmatch/ReDM_features.inc | 2 + 3 files changed, 202 insertions(+) create mode 100644 cstrike/addons/amxmodx/scripting/ReDeathmatch/Features/Tickets.inc diff --git a/cstrike/addons/amxmodx/scripting/ReDeathmatch.sma b/cstrike/addons/amxmodx/scripting/ReDeathmatch.sma index f07001f..13b5cf2 100644 --- a/cstrike/addons/amxmodx/scripting/ReDeathmatch.sma +++ b/cstrike/addons/amxmodx/scripting/ReDeathmatch.sma @@ -137,6 +137,7 @@ public CSGameRules_RestartRound() { return RoundModes_RestartRound() + Tickets_RestartRound() } public CSGameRules_PlayerKilled_Post(const victim, const killer, const inflictor) { diff --git a/cstrike/addons/amxmodx/scripting/ReDeathmatch/Features/Tickets.inc b/cstrike/addons/amxmodx/scripting/ReDeathmatch/Features/Tickets.inc new file mode 100644 index 0000000..1d5e001 --- /dev/null +++ b/cstrike/addons/amxmodx/scripting/ReDeathmatch/Features/Tickets.inc @@ -0,0 +1,199 @@ +static g_respawnsCount[any: TeamName] + +static redm_tickets +static Float: redm_tickets_hud_update_freq +static Float: redm_tickets_hud_blink_percent +static redm_tickets_hud_type + +Tickets_Init() { + RegisterHookChain(RG_CBasePlayer_Killed, "CBasePlayer_Killed", .post = true) + RegisterHookChain(RG_CSGameRules_FPlayerCanRespawn, "CSGameRules_FPlayerCanRespawn", .post = true) + + bind_pcvar_num( + create_cvar( + "redm_tickets", "150", + .has_min = true, .min_val = 0.0, + .flags = _FCVAR_INTEGER, + .description = "Number of times a team can ^n\ + have players respawn before they stop ^n\ + being able to respawn. ^n\ + `0` - disabled" + ), + redm_tickets + ) + hook_cvar_change(get_cvar_pointer("redm_tickets"), "CvarChange_redm_tickets") + + bind_pcvar_float( + create_cvar( + "redm_tickets_hud_update_freq", "1.0", + .has_min = true, .min_val = 0.0, + .flags = _FCVAR_FLOAT, + .description = "Tickets HUD update frequency." + ), + redm_tickets_hud_update_freq + ) + bind_pcvar_float( + create_cvar( + "redm_tickets_hud_blink_percent", "10.0", + .has_min = true, .min_val = 0.0, + .has_max = true, .max_val = 100.0, + .flags = _FCVAR_FLOAT, + .description = "Minimum percentage of tickets to start blinking." + ), + redm_tickets_hud_blink_percent + ) + bind_pcvar_num( + create_cvar( + "redm_tickets_hud_type", "1", + .has_min = true, .min_val = 0.0, + .has_max = true, .max_val = 1.0, + .flags = _FCVAR_INTEGER, + .description = "Ticket HUD display type. ^n\ + 0 - without colors and effects; ^n\ + 1 - color, with effects." + ), + redm_tickets_hud_type + ) + + CTickets_UpdateHUD() +} + +public CvarChange_redm_tickets(const cvar, const oldValue[], const value[]) { + CTickets_UpdateHUD() + for (new player = 1; player <= MaxClients; player++) { + if (!is_user_connected(player)) + continue + + new TeamName: team = get_member(player, m_iTeam) + if (CTickets_TeamTicketsLeft(team) == 0) + continue + + CTickets_PreventPlayerSpawning(player, .isSpawnAvailable = true) + } +} + +Tickets_RestartRound() { + arrayset(g_respawnsCount, 0, sizeof(g_respawnsCount)) + + CTickets_UpdateHUD() +} + +public CBasePlayer_Killed(const player, const killer, const gib) { + if (!IsActive()) + return + + if (redm_tickets <= 0) + return + + new TeamName: team = get_member(player, m_iTeam) + g_respawnsCount[team]++ + + if (CTickets_TeamTicketsLeft(team) != 0) + return + + CTickets_PreventPlayerSpawning(player) +} + +public CSGameRules_FPlayerCanRespawn(const player) { + if (!IsActive()) + return HC_CONTINUE + + if (redm_tickets <= 0) + return HC_CONTINUE + + new TeamName: team = get_member(player, m_iTeam) + + SetHookChainReturn(ATYPE_INTEGER, CTickets_TeamTicketsLeft(team) != 0) + return HC_SUPERCEDE +} + +public CTickets_UpdateHUD() { + if (!IsActive()) + return + + if (redm_tickets <= 0) + return + + CTickets_ShowPlayerTicketsHUD(.player = 0) + + const taskId = 9999 + remove_task(taskId) + set_task_ex(redm_tickets_hud_update_freq, "CTickets_UpdateHUD", .id = taskId) +} + +static CTickets_ShowPlayerTicketsHUD(const player = 0) { + new ticketsT = CTickets_TeamTicketsLeft(TEAM_TERRORIST) + new ticketsCT = CTickets_TeamTicketsLeft(TEAM_CT) + + static buffer[256] + formatex(buffer, charsmax(buffer), "%03d %03d", + ticketsT, + ticketsCT + ) + + if (redm_tickets_hud_type == 0) { + set_dhudmessage( + .red = 200, + .green = 200, + .blue = 200, + .y = 0.14, + .effects = 0, + .fadeouttime = 0.0, + .holdtime = (redm_tickets_hud_update_freq + 0.05) + ) + show_dhudmessage(player, "%s", buffer) + + return + } + + new TeamName: looserTeam + if (ticketsCT < ticketsT) + looserTeam = TEAM_CT + else if (ticketsCT > ticketsT) + looserTeam = TEAM_TERRORIST + else looserTeam = TEAM_UNASSIGNED + + new bool: shouldBlink = CTickets_TeamTicketsLeft(looserTeam) <= (redm_tickets * (redm_tickets_hud_blink_percent / 100)) + if (!shouldBlink) + looserTeam = TEAM_UNASSIGNED + + new Float: fadeoutTime = (redm_tickets_hud_update_freq * 0.5) + new Float: holdTimeBlink = (redm_tickets_hud_update_freq - fadeoutTime) + + // T tickets + set_dhudmessage( + .red = 255, + .green = 100, + .blue = 0, + .y = 0.14, + .effects = 0, + .fadeouttime = (looserTeam == TEAM_TERRORIST) ? fadeoutTime : 0.0, + .holdtime = (looserTeam == TEAM_TERRORIST) ? holdTimeBlink : (redm_tickets_hud_update_freq + 0.05) + ) + show_dhudmessage(player, "%-16.4s", buffer) + + // CT tickets + set_dhudmessage( + .red = 0, + .green = 100, + .blue = 255, + .y = 0.14, + .effects = 0, + .fadeintime = 0.0, + .fadeouttime = (looserTeam == TEAM_CT) ? fadeoutTime : 0.0, + .holdtime = (looserTeam == TEAM_CT) ? holdTimeBlink : (redm_tickets_hud_update_freq + 0.05) + ) + + // TODO: fkin amxx don't support left-padding... + show_dhudmessage(player, " %s", buffer[4]) +} + +static Float: CTickets_PreventPlayerSpawning(const player, const bool: isSpawnAvailable = false) { + set_member(player, m_flRespawnPending, isSpawnAvailable ? get_gametime() : 9999999.0) + + return get_member(player, m_flRespawnPending) +} + +static CTickets_TeamTicketsLeft(const TeamName: team) { + return max(0, redm_tickets - g_respawnsCount[team]) +} diff --git a/cstrike/addons/amxmodx/scripting/ReDeathmatch/ReDM_features.inc b/cstrike/addons/amxmodx/scripting/ReDeathmatch/ReDM_features.inc index df8136c..f09b996 100644 --- a/cstrike/addons/amxmodx/scripting/ReDeathmatch/ReDM_features.inc +++ b/cstrike/addons/amxmodx/scripting/ReDeathmatch/ReDM_features.inc @@ -1,4 +1,5 @@ #include "ReDeathmatch/Features/AimBarriers.inc" +#include "ReDeathmatch/Features/Tickets.inc" static g_fwdPrecacheEvent = -1 static g_gunsEventsId @@ -51,6 +52,7 @@ Features_Init() { RegisterHookChain(RG_HandleMenu_ChooseTeam, "HandleMenu_ChooseTeam", .post = true) AimBarriers_Init() + Tickets_Init() bind_pcvar_num( create_cvar(