Files
tws-zombies-scripts/t5/tws_t5_common.gsc
T

276 lines
6.7 KiB
Plaintext

/* tws_t5_common.gsc — shared config, HUD helpers, connect/spawn/help registries. */
#include maps\_utility;
#include common_scripts\utility;
init()
{
if (GetDvar(#"zombiemode") != "1")
return;
common_config();
register_help_command(".help", "List available commands");
level thread help_chat_listener();
level thread on_player_connect_dispatch();
}
common_config()
{
if (isDefined(level.hud_x))
return;
// anchor: move the whole cluster with these two
level.hud_x = 10;
level.hud_y = 10;
level.hud_row_match = level.hud_y;
level.hud_row_round = level.hud_y + 15;
level.hud_row_name = level.hud_y + 32;
level.hud_row_count = level.hud_y + 54;
level.hud_row_bar = level.hud_y + 84;
level.hud_font_small = 1.4;
level.hud_font_large = 2.0;
level.hud_font_mid = 1.6;
level.hud_bar_width = 120;
level.hud_bar_height = 8;
level.hud_col_count = level.hud_x + 90;
level.hud_col_name = level.hud_x + 60;
level.hud_col_health = level.hud_x + level.hud_bar_width + 12;
level.hud_rate = 0.1;
// green/amber/red ramp is health-only
level.hud_c_label = (0.85, 0.85, 0.85);
level.hud_c_dim = (0.55, 0.55, 0.55);
level.hud_c_count = (1, 1, 1);
level.hud_c_name = (0.4, 0.9, 0.5);
level.hud_c_high = (0.2, 1, 0.4);
level.hud_c_mid = (1, 0.8, 0);
level.hud_c_low = (1, 0.2, 0.2);
level.hud_c_afk = (1, 0.8, 0.2);
// numbers fade in below this fraction of max hp
level.hud_health_threshold = 1.0;
if (!isDefined(level.tws_spawn_handlers))
level.tws_spawn_handlers = [];
}
ensure_config()
{
if (!isDefined(level.hud_x))
common_config();
}
register_spawn_handler(fn)
{
if (!isDefined(level.tws_spawn_handlers))
level.tws_spawn_handlers = [];
level.tws_spawn_handlers[level.tws_spawn_handlers.size] = fn;
}
// Connection handlers also serve newcomers still waiting in spectator mode.
register_connect_handler(fn)
{
if (!isDefined(level.tws_connect_handlers))
level.tws_connect_handlers = [];
level.tws_connect_handlers[level.tws_connect_handlers.size] = fn;
}
// Modules register their own entries so help only lists installed commands.
register_help_command(command, description)
{
if (!isDefined(level.tws_help_commands))
level.tws_help_commands = [];
entry = spawnStruct();
entry.command = command;
entry.description = description;
level.tws_help_commands[level.tws_help_commands.size] = entry;
}
// Listen at level scope so newcomers can ask for help before their first spawn.
help_chat_listener()
{
for (;;)
{
level waittill("say", message, player);
if (!isDefined(player) || !isDefined(message))
continue;
command = toLower(message);
if (command == ".help" || command == ".commands")
player show_help();
}
}
show_help()
{
// Cache the text per connection; repeated SetText calls consume config strings.
if (!isDefined(self.tws_help_elems))
{
elems = [];
// Use the same anchors as the HUD, with room below the health numbers.
y = level.hud_row_bar + level.hud_bar_height + 20;
title = make_text_elem(self, level.hud_x, y,
"left", level.hud_font_mid, level.hud_c_afk);
title SetText("Commands");
elems[elems.size] = title;
for (i = 0; i < level.tws_help_commands.size; i++)
{
entry = level.tws_help_commands[i];
elem = make_text_elem(self, level.hud_x, y + 22 + i * 18,
"left", level.hud_font_small, level.hud_c_count);
elem SetText("^3" + entry.command + "^7 - " + entry.description);
elems[elems.size] = elem;
}
self.tws_help_elems = elems;
self thread destroy_on_disconnect(elems);
}
for (i = 0; i < self.tws_help_elems.size; i++)
{
elem = self.tws_help_elems[i];
elem.alpha = 1;
}
// Only the expiry timer is replaced; the say listener and cleanup stay alive.
self notify("tws_help_refresh");
self thread hide_help_after_delay();
}
hide_help_after_delay()
{
self endon("disconnect");
self endon("tws_help_refresh");
wait 12;
for (i = 0; i < self.tws_help_elems.size; i++)
{
elem = self.tws_help_elems[i];
elem.alpha = 0;
}
}
// only connect listener in the fleet; a second one crashes the T5 SP handshake
on_player_connect_dispatch()
{
for (;;)
{
level waittill("connected", player);
player thread on_player_spawned_dispatch();
player thread on_player_connected_dispatch();
}
}
on_player_connected_dispatch()
{
self endon("disconnect");
// Leave the connection handshake before invoking optional modules.
wait 0.05;
if (!isDefined(level.tws_connect_handlers))
return;
for (i = 0; i < level.tws_connect_handlers.size; i++)
self thread [[ level.tws_connect_handlers[i] ]]();
}
// handlers own their own self endon("disconnect")
on_player_spawned_dispatch()
{
self endon("disconnect");
self waittill("spawned_player");
if (!isDefined(level.tws_spawn_handlers))
return;
for (i = 0; i < level.tws_spawn_handlers.size; i++)
self thread [[ level.tws_spawn_handlers[i] ]]();
}
make_text_elem(player, x, y, align_x, scale, colour)
{
elem = NewClientHudElem(player);
elem.horzAlign = "left";
elem.vertAlign = "top";
elem.alignX = align_x;
elem.alignY = "top";
elem.x = x;
elem.y = y;
elem.foreground = 1;
elem.fontScale = scale;
elem.alpha = 1;
elem.color = colour;
// black glow reads as an outline against bright geometry
elem.glowColor = (0, 0, 0);
elem.glowAlpha = 0.6;
return elem;
}
make_shader_elem(player, x, y)
{
elem = NewClientHudElem(player);
elem.horzAlign = "left";
elem.vertAlign = "top";
elem.alignX = "left";
elem.alignY = "top";
elem.x = x;
elem.y = y;
elem.foreground = 1;
elem.alpha = 1;
return elem;
}
destroy_on_disconnect(elems)
{
self waittill("disconnect");
for (i = 0; i < elems.size; i++)
{
if (isDefined(elems[i]))
elems[i] Destroy();
}
}
int_dvar_or(name, fallback)
{
raw = GetDvar(name);
if (raw == "")
return fallback;
return int(raw);
}
format_mmss(elapsed_ms)
{
total_secs = int(elapsed_ms / 1000);
if (total_secs < 0)
total_secs = 0;
mins = int(total_secs / 60);
secs = total_secs - (mins * 60);
sec_str = "" + secs;
if (secs < 10)
sec_str = "0" + secs;
return "" + mins + ":" + sec_str;
}