From c5be0ce2ab2e9500a020005fb42381b18a35cf5f Mon Sep 17 00:00:00 2001 From: newby Date: Tue, 25 Apr 2023 13:36:30 -0700 Subject: [PATCH 01/22] experimental: bound view bob Put a bound on view bob beyond it just being a reduced function of amplitude so that scout is a little more controllable / less nauseating. --- csqc/main.qc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/csqc/main.qc b/csqc/main.qc index 32effac6..fcd1511f 100644 --- a/csqc/main.qc +++ b/csqc/main.qc @@ -565,20 +565,20 @@ static vector FO_Conc_Offset() { } float amp = Blend(table[i+1].amp_end, cur->amp_end, rem, cur->duration); - amp *= pstate_pred.conc_amp; float a = (cur->duration - rem) / cur->duration * cur->cycles * 2 * M_PI; a += cur->offset * 2 * M_PI; - return [amp * sin(a), amp * sin(a) * cos(a), 0]; + return [sin(a), sin(a) * cos(a), amp * pstate_pred.conc_amp]; } static void FO_UpdateConcAim() { makevectors(input_angles); vector o = FO_Conc_Offset(); - cuss_state.c_forward = normalize(v_forward * 200 + o.x * v_right + o.y * v_up); + cuss_state.c_forward = normalize(v_forward * 200 + o.x * o.z * v_right + o.y * o.z * v_up); - cuss_state.c_view = vectoangles(v_forward * 200 + o.x/4 * v_right + o.y/4 * v_up); + vector vv = o * min(o.z / 4, 20); + cuss_state.c_view = vectoangles(v_forward * 200 + vv.x * v_right + vv.y * v_up); cuss_state.c_view[0] *= -1; } From 9d68949f8e91f06b5da943f60391b78ddf010f19 Mon Sep 17 00:00:00 2001 From: newby Date: Mon, 1 May 2023 01:31:13 -0700 Subject: [PATCH 02/22] weapons: fix heavy cell consumption + minor tweaks - AC was costing -7 cells to fire, fix this and move it to a def. - Make weapon prediction account for usable cells in predicting spin-up - Add some helpers and cleanup around conditional firing of hwguy (and more generally ammo interactions). - Fix weapon prediction predicting out of ammo when there was exactly ammo_per_shot ammo left (> vs >=) --- csqc/weapon_predict.qc | 18 +++++++++++++++--- share/defs.h | 1 + share/weapons.qc | 17 +++-------------- ssqc/hwguy.qc | 20 ++++++++++++++++++++ ssqc/weapons.qc | 39 +++++++++++++++++++++++++++------------ 5 files changed, 66 insertions(+), 29 deletions(-) diff --git a/csqc/weapon_predict.qc b/csqc/weapon_predict.qc index 7889c29d..f46570d9 100644 --- a/csqc/weapon_predict.qc +++ b/csqc/weapon_predict.qc @@ -631,7 +631,7 @@ float WP_CheckAmmo(FO_WeapInfo* wi) { return FALSE; int ammo = WP_GetAmmo(wi->ammo_type); - return ammo > wi->ammo_per_shot; + return ammo >= wi->ammo_per_shot; } void WP_ChangeWeapon(Slot slot) { @@ -988,6 +988,14 @@ float WP_ConsumeAmmo(Slot slot) { return TRUE; } +float W_ConsumeAmmoIfPossible(float ammo_type, float amount) { + if (WP_GetAmmo(ammo_type) < amount) + return FALSE; + + pstate_pred.ammo_used[ammo_type] += amount; + return TRUE; +} + var void() melee_anim = player_axeN; void WP_AnimateModel() { @@ -1553,8 +1561,12 @@ void WP_Attack() { // Start the AC state machine when necessary. if (wi->weapon == WEAP_ASSAULT_CANNON && - (pstate_pred.tfstate & TFSTATE_AC_MASK) == 0) - pstate_pred.tfstate |= TFSTATE_AC_SPINUP; + (pstate_pred.tfstate & TFSTATE_AC_MASK) == 0) { + if (W_ConsumeAmmoIfPossible(AMMO_CELLS, PC_HVYWEAP_CELL_FIRE)) + pstate_pred.tfstate |= TFSTATE_AC_SPINUP; + else + pstate_pred.client_thinkindex = 0; // Just kidding, no cells. + } #if 0 // If our latency is higher than forward projection, synchronize animation // with when it will actually start/finish. The projectile internally diff --git a/share/defs.h b/share/defs.h index 51d1b1b8..e30d08bd 100644 --- a/share/defs.h +++ b/share/defs.h @@ -1065,6 +1065,7 @@ enumflags { #define PC_HVYWEAP_GRENADE_MAX_1 4 #define PC_HVYWEAP_GRENADE_MAX_2 1 #define PC_HVYWEAP_TF_ITEMS 0 +#define PC_HVYWEAP_CELL_FIRE 7 // Class Details for PYRO diff --git a/share/weapons.qc b/share/weapons.qc index e357900d..f62e431e 100644 --- a/share/weapons.qc +++ b/share/weapons.qc @@ -335,19 +335,6 @@ static FO_WeapModels weapon_models[] = { // REQUIRES: Order must match above. static string AMMO_to_s[] = {"none", "shells", "nails", "cells", "rockets"}; -static float* AMMO_to_p(entity player, AmmoType ammo_type) { - switch (ammo_type) { - case AMMO_SHELLS: return &player.ammo_shells; - case AMMO_CELLS: return &player.ammo_cells; - case AMMO_NAILS: return &player.ammo_nails; - case AMMO_ROCKETS: return &player.ammo_rockets; - default: - case AMMO_NONE: - return __NULL__; - } - return __NULL__; -} - Slot WEAP_to_slot(float playerclass, float weapon) { for (float i = 0; i < TF_NUM_SLOTS; i++) { if (class_weapons[playerclass].slots[i] == weapon) @@ -466,6 +453,8 @@ struct FO_WeapState { }; +float* W_ammo_to_p(entity player, AmmoType ammo_type); + void FO_FillWeapState(entity player, Slot slot, FO_WeapState* result) { FO_WeapInfo* wi = FO_SlotWeapInfo(player.playerclass, slot); @@ -473,7 +462,7 @@ void FO_FillWeapState(entity player, Slot slot, FO_WeapState* result) { result->slot = slot; result->wi = wi; - result->ammo_remaining = AMMO_to_p(player, wi->ammo_type); + result->ammo_remaining = W_ammo_to_p(player, wi->ammo_type); if (!IsSlotNull(slot)) result->clip_fired = &player.clip_fired[SlotIndex(slot)]; diff --git a/ssqc/hwguy.qc b/ssqc/hwguy.qc index ae6caade..daac67e2 100644 --- a/ssqc/hwguy.qc +++ b/ssqc/hwguy.qc @@ -98,3 +98,23 @@ void FO_LockToggle () { /* this shouldn't be here, I think we just need to allow this impulse while shooting */ /* worth checking detpipes for this too */ } + +float AssCanTryBeginFire() { + if (get_shells() < 1) + return FALSE; + + if (FO_CheckForReload()) + return FALSE; + + if (!W_ConsumeAmmoIfPossible(AMMO_CELLS, PC_HVYWEAP_CELL_FIRE)) { + // Not worth optimizing w/ client side. + if (time >= self.antispam_assault_cannon) { + sprint(self, PRINT_MEDIUM, "Not enough cells to power up the Assault Cannon\n"); + self.antispam_assault_cannon = time + 3; + } + return FALSE; + } + + player_asscan_up1(); + return TRUE; +} diff --git a/ssqc/weapons.qc b/ssqc/weapons.qc index dfca2c2f..99380711 100644 --- a/ssqc/weapons.qc +++ b/ssqc/weapons.qc @@ -190,6 +190,29 @@ void (float att_delay) Attack_Finished = { self.attack_finished = self.client_time + att_delay; }; +float* W_ammo_to_p(entity player, AmmoType ammo_type) { + switch (ammo_type) { + case AMMO_SHELLS: return &player.ammo_shells; + case AMMO_CELLS: return &player.ammo_cells; + case AMMO_NAILS: return &player.ammo_nails; + case AMMO_ROCKETS: return &player.ammo_rockets; + default: + case AMMO_NONE: + return __NULL__; + } + return __NULL__; +} + +float W_ConsumeAmmoIfPossible(float ammo_type, float amount) { + float *ammo = W_ammo_to_p(self, ammo_type); + + if (*ammo < amount) + return FALSE; + *ammo -= amount; + return TRUE; +} + + int () W_FireAxe = { local vector source; local vector org; @@ -1621,6 +1644,8 @@ void () player_asscan_up1; void () player_medikit1; void () player_medikitb1; +float AssCanTryBeginFire(); + void () W_Attack = { FO_WeapState ws; FO_FillCurrentWeapState(&ws); @@ -1705,19 +1730,9 @@ void () W_Attack = { player_autorifle1(); W_FireAutoRifle(); } else if (ws.weapon == WEAP_ASSAULT_CANNON) { - if (self.ammo_cells < 7) { - if (time >= self.antispam_assault_cannon) { - sprint(self, PRINT_MEDIUM, "Not enough cells to power up the Assault Cannon\n"); - self.antispam_assault_cannon = time + 3; - } + self.immune_to_check = time + 5; + if (!AssCanTryBeginFire()) W_ChangeToBestWeapon(); - } else { - self.ammo_cells -= - 7; - self.count = 0; - self.immune_to_check = time + 5; - self.tfstate |= TFSTATE_AIMING; - player_asscan_up1(); - } } else if (ws.weapon == WEAP_FLAMETHROWER) { player_flamethrower1(); W_FireFlame(); From d2857492a5786810eb3a29da51b02c1e7bcc546c Mon Sep 17 00:00:00 2001 From: newby Date: Mon, 1 May 2023 01:31:21 -0700 Subject: [PATCH 03/22] hud: unify lmp lookup and render partial clips - slightly unify the awful char->wad lookup used by a few of the hud functions - add a hacky way to emit red text with markup - use said hack to render clips constrained by available ammo rather than loaded clip in red - add `fo_hud_noclipicon` for just clip text with no icon (off by default) --- csqc/hud_helpers.qc | 88 +++++++++++++++++------------------------- csqc/status.qc | 5 ++- csqc/weapon_predict.qc | 10 ++++- 3 files changed, 48 insertions(+), 55 deletions(-) diff --git a/csqc/hud_helpers.qc b/csqc/hud_helpers.qc index 16345ca8..094b0e13 100644 --- a/csqc/hud_helpers.qc +++ b/csqc/hud_helpers.qc @@ -113,6 +113,26 @@ float(PanelID id, vector pos, vector size, float alpha, float enabled) hud_panel return sui_is_clicked(id); }; +static string lmp_lookup(float c, float use_red) { + string lmp = ""; + switch (c) { + case ' ': return ""; + case '*': return "use_red"; // Caller must handle + case '-': lmp = "num_minus"; break; + case '/': lmp = "num_slash"; break; + case ':': lmp = "num_colon"; break; + default: { + if (c >= '0' && c <= '9') + lmp = sprintf("num_%g", c-'0'); + else + return "sb_quad"; // Unrecognized. + } + } + if (use_red) + lmp = strcat("a", lmp); + return lmp; +} + // this draws backwards, haven't bothered to change as we don't use it void Hud_DrawLargeValue(vector pos, float value, float threshhold, float size) { @@ -143,39 +163,31 @@ void Hud_DrawLargeValue(vector pos, float value, float threshhold, float size) void Hud_DrawStringLMP(vector pos, string value, float size) { - float c; - float len, i; + float len, i, j; string s; if (!size) size = 24; vector vsize = [size, size, 0]; s = value; len = strlen(s); - i = 0; + float use_red = FALSE; - while(iclip_size); + float rem = WP_GetAmmo(wi->ammo_type); + + // It's possible for the amount in clip to exceed remaining ammo (this + // occurs because we load before we drop for example). Render a clipped + // clip when this occurs, with a visual indicator. + if (clip > rem) + return sprintf("*%d*/%d", rem, wi->clip_size); + else + return sprintf("%d/%d", clip, wi->clip_size); } float WP_CanReload(Slot slot, string* msg = __NULL__) { From 365808b77800630c9a8d60eab24f249610ffc8cf Mon Sep 17 00:00:00 2001 From: newby Date: Mon, 1 May 2023 13:15:20 -0700 Subject: [PATCH 04/22] hud: fix spacing on updated text rendering funcs - effective pre-increment was inserting a space on rendered elements - also just update the threshold equivalent to support use_red markup, even though it's not currently used --- csqc/hud_helpers.qc | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/csqc/hud_helpers.qc b/csqc/hud_helpers.qc index 094b0e13..352a3b17 100644 --- a/csqc/hud_helpers.qc +++ b/csqc/hud_helpers.qc @@ -178,28 +178,32 @@ void Hud_DrawStringLMP(vector pos, string value, float size) continue; } - j++; if (lmp != "") HRC_drawpic(pos + [j * size, 0, 0], lmp, vsize, '1 1 1', 1, 0); + j++; } } void Hud_DrawStringLMPThreshold(vector pos, string value, float size, float threshold) { - float len, i, intval; + float len, i, j, intval, use_red = FALSE; string s, lmp; if (!size) size = 24; vector vsize = [size, size, 0]; s = value; intval = stof(value); len = strlen(s); - i = 0; - while(i Date: Mon, 1 May 2023 14:28:01 -0700 Subject: [PATCH 05/22] hud: improve scoreboard precision Clipping scoreboard units to kilos hides a lot of information. Impove behavior by more densely filling up to 4 digits: - <10000 now prints precisely - <100 % 1000 now prints with an additional decimal and unit - >100 % 1000 now prints as before --- csqc/status.qc | 40 ++++++++++++++-------------------------- 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/csqc/status.qc b/csqc/status.qc index 32ae043d..f060842f 100644 --- a/csqc/status.qc +++ b/csqc/status.qc @@ -621,37 +621,25 @@ void(PanelID panelid, string text) drawReadyPanel = { } } -float (float val) AbbreviateNumber = { - val = val / 1000; - val = rint(val); - return val; -}; - string (float val) AbbreviateNumberToString = { - string abbr = ""; + val = rint(val); + if (val < 10000) + return ftos(rint(val)); - int count = 0; - while (val >= 1000) - { - val = AbbreviateNumber(val); + float count = 0; + while (val >= 1000) { + val /= 1000; count++; } - switch (count) - { - case 1: - abbr = "k"; - break; - case 2: - abbr = "m"; - break; - case 3: - abbr = "b"; - break; - } - - string s = strcat(ftos(val), abbr); - return s; + // Try to (with max density) use up to 4 characters. + const string abbr = "kmb"; + if (count == 0) + return ftos(val); + else if (val < 100) + return sprintf("%0.1f%c", val, abbr[min(count - 1, 2)]); + else + return sprintf("%d%c", val, abbr[min(count - 1, 2)]); }; void (vector position, vector size, string val, vector textcolour, float alpha From 6b5ae6be98d3a81688c9a936146a8f0a9254b5c6 Mon Sep 17 00:00:00 2001 From: newby Date: Mon, 1 May 2023 14:29:16 -0700 Subject: [PATCH 06/22] spy: set frl to something sane 0 just allows instant spam --- ssqc/client.qc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ssqc/client.qc b/ssqc/client.qc index a60d9dde..b4dd98d1 100644 --- a/ssqc/client.qc +++ b/ssqc/client.qc @@ -526,7 +526,7 @@ void () DecodeLevelParms = { feign_msg = CF_GetSetting("fm", "feign_msg", "on"); // rate limit on feign - feign_rate_limit = CF_GetSetting("frl", "feign_rate_limit", "0"); + feign_rate_limit = CF_GetSetting("frl", "feign_rate_limit", "0.5"); // turn off spy [off] spy_off = CF_GetSetting("spy", "spy", "off"); From 625325fc5c2107e8df8e0cf8febe966b9dadd87e Mon Sep 17 00:00:00 2001 From: newby Date: Mon, 1 May 2023 17:12:24 -0700 Subject: [PATCH 07/22] hud: render at right position DrawStringLMPThreshold was maintaining the offset in rendered space but still using the offset in strong. Doesn't affect anything in practice since use_red markup is not being used currently with this function. --- csqc/hud_helpers.qc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csqc/hud_helpers.qc b/csqc/hud_helpers.qc index 352a3b17..7f7afc23 100644 --- a/csqc/hud_helpers.qc +++ b/csqc/hud_helpers.qc @@ -202,7 +202,7 @@ void Hud_DrawStringLMPThreshold(vector pos, string value, float size, float thre } if (lmp != "") - HRC_drawpic(pos + [i * size, 0, 0], lmp, vsize, '1 1 1', 1, 0); + HRC_drawpic(pos + [j * size, 0, 0], lmp, vsize, '1 1 1', 1, 0); j++; } } From 98ff9e30bf0b07c53d585e030cdaa8fa8d170258 Mon Sep 17 00:00:00 2001 From: newby Date: Mon, 1 May 2023 17:15:19 -0700 Subject: [PATCH 08/22] cleanup: remove deprecated project_weapons_* settings TODO: update documentation --- ssqc/client.qc | 7 ------- ssqc/qw.qc | 3 --- 2 files changed, 10 deletions(-) diff --git a/ssqc/client.qc b/ssqc/client.qc index b4dd98d1..72049bc4 100644 --- a/ssqc/client.qc +++ b/ssqc/client.qc @@ -608,12 +608,6 @@ void () DecodeLevelParms = { // CSQC projectiles fo_projectiles = CF_GetSetting("focp", "fo_csqc_projectiles", "on"); - // project projectile weapons by player ping - project_weapons = CF_GetSetting("pw", "project_weapons", "off"); - - // max projectile projection latency (default 100ms) - project_weapons_max_latency = CF_GetSetting("pwml", "project_weapons_max_latency", ftos(0.1)); - // delay respawning by this many seconds [0] Role_None.respawn_delay_time = CF_GetSetting("rd", "respawn_delay", "0"); if (Role_None.respawn_delay_time) { @@ -1002,7 +996,6 @@ void () DecodeLevelParms = { detpipe_limit_world = 7; medicaura = FALSE; medicnocuss = FALSE; - project_weapons = FALSE; distance_based_cuss_duration = FALSE; drop_grenades = FALSE; drop_grenpack = FALSE; diff --git a/ssqc/qw.qc b/ssqc/qw.qc index fc101edd..95c5bfdf 100644 --- a/ssqc/qw.qc +++ b/ssqc/qw.qc @@ -600,9 +600,6 @@ float old_dispenser; float old_hp_armor; float max_armor_hwguy; -float project_weapons; -float project_weapons_max_latency; - float ng_damage; float sng_damage; float superaxe; From f6aa9bf4bb00710eb3aec7d2f16806998ef3fdc9 Mon Sep 17 00:00:00 2001 From: newby Date: Wed, 3 May 2023 11:33:02 -0700 Subject: [PATCH 09/22] hud: fix built-in pad bug strpad of negative length (for right align) on strings that are already the right length, sends them to the moon. Avoid this. Spacing on scoreboard generally needs a little bit of attention, but at least show a squished number rather than blank.. --- csqc/status.qc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/csqc/status.qc b/csqc/status.qc index f060842f..16e09dd0 100644 --- a/csqc/status.qc +++ b/csqc/status.qc @@ -644,7 +644,8 @@ string (float val) AbbreviateNumberToString = { void (vector position, vector size, string val, vector textcolour, float alpha , float flags, string colname) drawShowScoresColumnVal = { - val = strpad(strlen(colname) * -1, val); + if (strlen(val) < strlen(colname)) + val = strpad(strlen(colname) * -1, val); sui_text(position, size, val, textcolour, 1, 0); }; From a03cab88a8872f4dfb2700532a54d3241bfb9467 Mon Sep 17 00:00:00 2001 From: newby Date: Fri, 5 May 2023 01:12:57 -0700 Subject: [PATCH 10/22] login: fix file-handle leaks and refactor The current login code is leaking file handles in two places which leads to login failures when we run out of handles and it's unable to read the token. Fix this but also just refactor so we're not duplicating the read/send path between client and server initiated. Add instructions for people who dont have a token to visit the FO website to get one. --- csqc/events.qc | 8 ++------ csqc/main.qc | 34 ++++++++++++++++++++++------------ 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/csqc/events.qc b/csqc/events.qc index d19d5965..55f2a73a 100644 --- a/csqc/events.qc +++ b/csqc/events.qc @@ -2,6 +2,7 @@ void ParseSBAR(); void ParseGrenPrimed(float grentype, float primed_at, float explodes_at); void ParseHitFlag(vector targpos, float mitdmg, float rawdmg, float hitflag); float StartGrenTimer(float primed_at, float expires_at, float grentype, float play_sound); +float FoLogin(string token, float print_error); void() CSQC_Parse_Event = { float msgtype = readbyte(); @@ -342,13 +343,8 @@ void() CSQC_Parse_Event = { RemoveVoteMap(readstring(), FALSE); break; case MSG_LOGIN: - local float filehandle = fopen(FO_TOKEN_PATH, FILE_READ); - if (filehandle != -1) { - localcmd("setinfo _fo_token ", fgets(filehandle), "\n"); - localcmd("cmd fo-login-silent\n"); - } else { + if (!FoLogin("", FALSE)) print("You are not logged in\n"); - } break; case MSG_PAUSE: CsGrenTimer::SyncPause(); diff --git a/csqc/main.qc b/csqc/main.qc index d3ba3082..bdabaa02 100644 --- a/csqc/main.qc +++ b/csqc/main.qc @@ -10,7 +10,7 @@ void AddGrenTimer(float grentype, float offset); void StopGrenTimers(); float IsValidToUseGrenades(); void Sync_GameState(); -void FoLogin(string token); +float FoLogin(string token, float print_error); void Perf_Status(); void FO_Hud_Init(); float InFluid(vector point); @@ -238,7 +238,7 @@ noref float(string cmd) CSQC_ConsoleCommand = { Slot_Keyup(stof(argv(1))); break; case "login": - FoLogin(argv(1)); + FoLogin(argv(1), TRUE); break; case "fo_hud_editor": FO_Hud_Editor(); @@ -720,25 +720,35 @@ void Sync_GameState() { PM_PredictJump(); } -void FoLogin(string token) { - local float filehandle; +static string FoLogin_GetToken() { + float filehandle = fopen(FO_TOKEN_PATH, FILE_READ); + if (filehandle == -1) + return ""; + string token = fgets(filehandle); + fclose(filehandle); + return token; +} + +// Doesn't actually return success, just whether it sent a token. +float FoLogin(string token, float print_error) { if (token != "") { - filehandle = fopen(FO_TOKEN_PATH, FILE_WRITE); + float filehandle = fopen(FO_TOKEN_PATH, FILE_WRITE); fputs(filehandle, token); fclose(filehandle); } else { - filehandle = fopen(FO_TOKEN_PATH, FILE_READ); - if (filehandle == -1) { - print("Can't login without valid token\n"); - return; - } else { - token = fgets(filehandle); - } + token = FoLogin_GetToken(); + } + + if (token == "") { + if (print_error) + print("Token required: Please sign-up at FortressOne.org and follow the instructions to generate your login token.\n"); + return FALSE; } localcmd("setinfo _fo_token ", token, "\n"); localcmd("cmd fo-login-silent\n"); + return TRUE; } static string to_precision(float f, float p) { From 69dccc621c89dc6da1d7a9461c9ac74e2cecbd81 Mon Sep 17 00:00:00 2001 From: Sheldon Johnson Date: Wed, 10 May 2023 01:46:49 +1000 Subject: [PATCH 11/22] Remove pointless type from function fixing compile warning --- csqc/main.qc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/csqc/main.qc b/csqc/main.qc index ee2bc23a..c3319ff2 100644 --- a/csqc/main.qc +++ b/csqc/main.qc @@ -32,10 +32,10 @@ void PushToSlotHistory(float value) { slot_history[slot_history_top] = value; } -float RemoveFromSlotHistory(float slot) { +void RemoveFromSlotHistory(float slot) { if (slot_history_top == -1) { // Stack is empty - return -1; + return; } for (float i = slot_history_top; i >= 0; i--) { @@ -214,6 +214,7 @@ void Slot_Keydown(float slot) { void Slot_Keyup(float slot) { RemoveFromSlotHistory(slot); + if (slot_history_top >= 0) { // still holding another +slot bind localcmd(sprintf("impulse %f\n", slot_history[slot_history_top])); } else { From ab3baeea841cbaec84b5b9063ecd86bd63500b9e Mon Sep 17 00:00:00 2001 From: Sheldon Johnson Date: Tue, 16 May 2023 20:11:13 +1000 Subject: [PATCH 12/22] Don't attempt to send match results if login isn't required --- ssqc/quadmode.qc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ssqc/quadmode.qc b/ssqc/quadmode.qc index f90e6663..bb079624 100644 --- a/ssqc/quadmode.qc +++ b/ssqc/quadmode.qc @@ -478,7 +478,7 @@ void () QuadRoundBegin = { bprint(2, "QUAD ROUND BEGINS NOW\n"); - if (rounds == 1) + if (rounds == 1 && fo_login_required) PostFOQuadFinalRoundStarted(); te = find(world, classname, "player"); @@ -626,7 +626,8 @@ void () StartQuadRound = p = find (world, classname, "player"); // send result to server - PostFOQuadFinished(quad_winner); + if (fo_login_required) + PostFOQuadFinished(quad_winner); while (p != world) { if (p.netname != "" && p.team_no && p.playerclass) { @@ -678,7 +679,7 @@ void () StartQuadRound = p = find(p, classname, "player"); } - if (rounds == 2 && legit_players > 1) + if (rounds == 2 && legit_players > 1 && fo_login_required) PostFOQuadStarted(); if (rounds == 1 /* final round */) { From 35826c1b029925c22d94c33823a5f6e235b7e888 Mon Sep 17 00:00:00 2001 From: Sheldon Johnson Date: Mon, 22 May 2023 20:06:16 +1000 Subject: [PATCH 13/22] Don't send match results if teams uneven, don't allow forcestart when logins enabled --- ssqc/clan.qc | 2 +- ssqc/commands.qc | 5 +++++ ssqc/quadmode.qc | 22 ++++++++++++++++++---- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/ssqc/clan.qc b/ssqc/clan.qc index de247a11..d3448929 100644 --- a/ssqc/clan.qc +++ b/ssqc/clan.qc @@ -1095,7 +1095,7 @@ float () CheckAllPlayersReady = { void () PlayerReady = { if (fo_login_required && self.fo_login == string_null) { - sprint(self, PRINT_HIGH, "You need to log in to ready up. See fortressone.org\n"); + sprint(self, PRINT_HIGH, "You need to sign in first. Get your login token at www.fortressone.org\n"); return; } diff --git a/ssqc/commands.qc b/ssqc/commands.qc index 629de952..5e6f58e3 100644 --- a/ssqc/commands.qc +++ b/ssqc/commands.qc @@ -27,6 +27,11 @@ void () RestartMap = { } void () ForceStartMatch = { + if (fo_login_required) { + bprint(PRINT_HIGH, "Can't forcestart while logins enabled.\n"); + return; + } + if (clanbattle == 1 && cb_prematch == 1) { bprint(PRINT_HIGH, self.netname); bprint(PRINT_HIGH, " has forced the match start.\n"); diff --git a/ssqc/quadmode.qc b/ssqc/quadmode.qc index bb079624..04c8912e 100644 --- a/ssqc/quadmode.qc +++ b/ssqc/quadmode.qc @@ -1,6 +1,15 @@ void () info_player_teamspawn; void () PostFOQuadStarted = { + if (!fo_login_required) + return; + + if !(TeamFortress_TeamGetNoPlayersExcludingAllTime(1) == TeamFortress_TeamGetNoPlayersExcludingAllTime(2)) { + bprint(PRINT_HIGH, "Uneven teams, match can't be recorded\n"); + fo_login_required = FALSE; + return; + } + local string data = ""; data = strcat(data, "{\n"); @@ -69,6 +78,9 @@ void () PostFOQuadStarted = { }; void () PostFOQuadFinalRoundStarted = { + if (!fo_login_required) + return; + local string data = ""; data = strcat(data, "{\n"); @@ -126,6 +138,9 @@ void () PostFOQuadFinalRoundStarted = { }; void (float winner) PostFOQuadFinished = { + if (!fo_login_required) + return; + if (!match_id) return; @@ -478,7 +493,7 @@ void () QuadRoundBegin = { bprint(2, "QUAD ROUND BEGINS NOW\n"); - if (rounds == 1 && fo_login_required) + if (rounds == 1) PostFOQuadFinalRoundStarted(); te = find(world, classname, "player"); @@ -626,8 +641,7 @@ void () StartQuadRound = p = find (world, classname, "player"); // send result to server - if (fo_login_required) - PostFOQuadFinished(quad_winner); + PostFOQuadFinished(quad_winner); while (p != world) { if (p.netname != "" && p.team_no && p.playerclass) { @@ -679,7 +693,7 @@ void () StartQuadRound = p = find(p, classname, "player"); } - if (rounds == 2 && legit_players > 1 && fo_login_required) + if (rounds == 2 && legit_players > 1) PostFOQuadStarted(); if (rounds == 1 /* final round */) { From feb2c7aead9421374ef5b52655e3df3367866154 Mon Sep 17 00:00:00 2001 From: newby Date: Tue, 25 Jul 2023 12:08:33 -0700 Subject: [PATCH 14/22] client: work-around for missing models issue flush post world-load to resolve race conditions where models appended into the map package do not resolve correctly. --- csqc/main.qc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/csqc/main.qc b/csqc/main.qc index b4efe67f..b489c7d7 100644 --- a/csqc/main.qc +++ b/csqc/main.qc @@ -165,6 +165,9 @@ noref void() CSQC_WorldLoaded = { print("CSQC World Loaded\n"); ClientSettings_Check(); localcmd("menu_restart\n"); + // Resolve race condition where models packed into map package sometimes do + // not resolve correctly. + localcmd("flush\n"); } void FO_CussView(); From 301b252f6b0e94a4e8809425fb878f6f3c5317e0 Mon Sep 17 00:00:00 2001 From: newby Date: Tue, 25 Jul 2023 12:28:36 -0700 Subject: [PATCH 15/22] medic: activate aura by default when changing class to medic and off The most common reason for this being off is.. forgetting to turn it on. Flip this to be on by default when you change class to medic. If you turn it off, it will stay off (unless you again change classes), but the default is now on. --- ssqc/client.qc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ssqc/client.qc b/ssqc/client.qc index e11872d5..2666d040 100644 --- a/ssqc/client.qc +++ b/ssqc/client.qc @@ -2113,6 +2113,8 @@ void () PutClientInServer = { TeamFortress_ChangeClass(11); } + int prev_playerclass = self.playerclass; + if (deathmatch == 3) { if(self.nextpc != self.playerclass) { if (self.playerclass != 0) { @@ -2293,6 +2295,11 @@ void () PutClientInServer = { self.tf_items_flags = self.tf_items_flags | NIT_SCANNER_ENEMY; } + // Activate medic aura by default when changing to class and off + if (self.playerclass == PC_MEDIC && prev_playerclass != PC_MEDIC && + !self.aura_active) + CF_Medic_AuraToggle(); + UpdateReadyStatus(); }; From a9be1465a5f426e51924c53d116a3078fe1314a5 Mon Sep 17 00:00:00 2001 From: Sheldon Johnson Date: Mon, 31 Jul 2023 03:07:56 +1000 Subject: [PATCH 16/22] Auto update server when stale --- ssqc/world.qc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ssqc/world.qc b/ssqc/world.qc index c7cc99f1..a4483e47 100644 --- a/ssqc/world.qc +++ b/ssqc/world.qc @@ -515,6 +515,8 @@ void () TerminateStaleServer = { return; //someone is around } + Admin_UpdateServer(); + dprint(sprintf("Terminating empty server with more than %d hours uptime\n", STALE_TIME_HOURS)); localcmd("quit\n"); From 3f2c294daebf0e93ebc337766084c1b9cb75f41a Mon Sep 17 00:00:00 2001 From: newby Date: Mon, 31 Jul 2023 16:31:56 -0700 Subject: [PATCH 17/22] hwguy: fix locked weaponframe selection CSQC side was filling in wrong field --- share/animate.qc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/animate.qc b/share/animate.qc index ab40bbe5..6d0db327 100644 --- a/share/animate.qc +++ b/share/animate.qc @@ -154,7 +154,7 @@ static inline float is_attacking() { return input_buttons & BUTTON0; } static inline float is_intermission() { return intermission; } static void SuperDamageSound() {} // TODO static inline vector get_velocity() { return pmove_vel; } -static inline void set_weapon_frame(int f) { self.frame = f; } +static inline void set_weapon_frame(float f) { pstate_pred.weaponframe = f; } static inline void muzzleflash() {} float WP_CurrentClipFired(); static inline float get_clip_fired() { return WP_CurrentClipFired(); } From 65566b778dd7c7219fecc42ed16bbf1dc9c0b111 Mon Sep 17 00:00:00 2001 From: newby Date: Fri, 11 Aug 2023 15:20:58 -0700 Subject: [PATCH 18/22] client: add slot_a for alternating slot selection pecan was dependent using bugs in the old +slot implementation so that he could switch between reds/yellows while using a +slot bind. Add a new client command to do what he really wants: to be able to swap between reds/yellows, swapping to reds if neither active We implement a more generic form of this, "slot_a ". This lets you bind it with 2 passed slots, when activated, it will switch to slot_a if neither is selected, otherwise it will alternate between them. pecan's use case becomes: bind key slot_a 1 2 --- csqc/main.qc | 8 ++++++++ csqc/weapon_predict.qc | 17 +++++++++++++++++ share/weapons.qc | 3 ++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/csqc/main.qc b/csqc/main.qc index b489c7d7..a3a770f3 100644 --- a/csqc/main.qc +++ b/csqc/main.qc @@ -118,6 +118,9 @@ noref void(float apiver, string enginename, float enginever) CSQC_Init = { registercommand("-dropflag"); registercommand("+rj"); registercommand("-rj"); + + registercommand("slot_a"); + // registercommand("+quick1"); // registercommand("-quick1"); // registercommand("+quick2"); @@ -228,6 +231,8 @@ void Slot_Keyup(float slot) { } } +void W_ChangeToSlotAlternate(string opt1, string opt2); + noref float(string cmd) CSQC_ConsoleCommand = { tokenize_console(cmd); float val; @@ -477,6 +482,9 @@ noref float(string cmd) CSQC_ConsoleCommand = { case "vote_removemap": RemoveVoteMap(argv(1), TRUE); break; + case "slot_a": // Alternate between passed options + W_ChangeToSlotAlternate(argv(1), argv(2)); + break; } return FALSE; diff --git a/csqc/weapon_predict.qc b/csqc/weapon_predict.qc index 1e4046ab..1cec49c7 100644 --- a/csqc/weapon_predict.qc +++ b/csqc/weapon_predict.qc @@ -644,6 +644,23 @@ void WP_ChangeWeapon(Slot slot) { // UpdateViewModel will propagate. } +// Alternate between opt1/opt2, activating opt1 if neither is active. +// Useful for demoman to have red/yellows bound to 1 key. +void W_ChangeToSlotAlternate(string opt1, string opt2) { + float v1 = strlen(opt1) > 0 ? stof(opt1) : 0; + float v2 = strlen(opt2) > 0 ? stof(opt2) : v1; + + if ((v1 < 1 || v1 > TF_NUM_SLOTS) || (v2 < 1 || v2 > TF_NUM_SLOTS)) + return; + + // The OWI/slot mess rears its head again here. We convert to a slot for + // comparison but use the naked input value which will then be converted per + // OWI if active. + Slot slot = FO_SlotByInput(pstate_pred.playerclass, v1); + float imp = IsSameSlot(pstate_pred.current_slot, slot) ? v2 : v1; + localcmd(sprintf("impulse %d\n", imp)); +} + Slot WP_BestWeaponSlot() { for (float i = 1; i <= TF_NUM_SLOTS; i++) { Slot slot = MakeSlot(i); diff --git a/share/weapons.qc b/share/weapons.qc index f62e431e..a0ed2d8b 100644 --- a/share/weapons.qc +++ b/share/weapons.qc @@ -34,7 +34,8 @@ float SlotIndex(Slot slot) { printf("ERROR: OOB slot id (%d) found. Continuing.\n", (float)slot.id); return TF_NUM_SLOTS - 1; } - return slot.id - 1; } + return slot.id - 1; +} // Convert a weapon-bit to a linear index. static float WEAP_to_index(float weapon) { From 92176ad0b3f74f175520bf097062c0fb4a1182c6 Mon Sep 17 00:00:00 2001 From: newby Date: Sun, 13 Aug 2023 16:11:36 -0700 Subject: [PATCH 19/22] init: no more stuff If you've ever noticed that first connect seems to take a long time compared to subsequent ones it turns out that hundreds of mod aliases (many of which we no longer really use) are being stuffed (with a rate limit) for binding. Eliminate this by performing client binds directly in CSQC, with no server-side stuffs. --- csqc/main.qc | 23 +++- share/defs.h | 158 ++++++++++++++++++++++++- ssqc/client.qc | 5 +- ssqc/qw.qc | 1 - ssqc/spect.qc | 5 - ssqc/tforthlp.qc | 296 +++++++---------------------------------------- ssqc/weapons.qc | 5 - 7 files changed, 226 insertions(+), 267 deletions(-) diff --git a/csqc/main.qc b/csqc/main.qc index a3a770f3..01877e6b 100644 --- a/csqc/main.qc +++ b/csqc/main.qc @@ -52,6 +52,23 @@ void RemoveFromSlotHistory(float slot) { } +static void BindAlias(TFAlias* tfa) { + if (tfa->impulse == 0 && tfa->cmd == "") // Some aliases are !csqc-only + return; + + if (tfa->impulse) + localcmd(sprintf("alias %s impulse %d\n", tfa->alias, tfa->impulse)); + else + localcmd(strcat("alias ", tfa->alias, " \"", tfa->cmd, "\"\n")); +} + +static void SetupAliases() { + for (float i = 0; i < client_aliases.length; i++) + BindAlias(&client_aliases[i]); + + print("Aliases set\n"); +} + DECLARE_PERF_SAMPLER(frame_timing, 60, 0.1); DECLARE_PERF_SAMPLER(hud_timing, 60, 0.1); DECLARE_PERF_SAMPLER(hud_partial_timing, 60, 0.1); @@ -162,11 +179,13 @@ noref void(float apiver, string enginename, float enginever) CSQC_Init = { vote_list_filter = ""; TF_Init(); + + ClientSettings_Check(); + SetupAliases(); + print("CSQC initialization finished\n"); }; noref void() CSQC_WorldLoaded = { - print("CSQC World Loaded\n"); - ClientSettings_Check(); localcmd("menu_restart\n"); // Resolve race condition where models packed into map package sometimes do // not resolve correctly. diff --git a/share/defs.h b/share/defs.h index e30d08bd..3a1a5ae9 100644 --- a/share/defs.h +++ b/share/defs.h @@ -509,7 +509,7 @@ struct Slot { int id; }; #define TF_SHOWTF 107 // Displays server settings and mod version #define TF_SHOWLEGALCLASSES 108 // Show what classes are allowed by current map #define TF_SHOW_IDS 109 // Show ids of connected players -#define TF_ALIAS_CHECK 110 // Check if client has gotten all the aliases +// unused 110 #define TF_CHANGECLASS 111 // Bring up class selection menu #define TF_CHANGEPC_SCOUT 112 // Change class to Scout #define TF_CHANGEPC_SNIPER 113 // Change class to Sniper @@ -1537,3 +1537,159 @@ enumflags { #define FO_QUAD_STARTED_REQUEST 2 #define FO_QUAD_FINISHED_REQUEST 3 #define FO_LOGIN_REQUEST 4 + +struct TFAlias { + string alias; + float impulse; + string cmd; + float nocsqc_impulse; + string nocsqc_cmd; +}; + +TFAlias client_aliases[] = { + {"slot1", TF_IMPULSE_SLOT1}, + {"slot2", TF_IMPULSE_SLOT2}, + {"slot3", TF_IMPULSE_SLOT3}, + {"slot4", TF_IMPULSE_SLOT4}, + {"+slot1", 0, "impulse 20;+attack"}, + {"-slot1", 0, "-attack;impulse 24"}, + {"+slot2", 0, "impulse 21;+attack"}, + {"-slot2", 0, "-attack;impulse 24"}, + {"+slot3", 0, "impulse 22;+attack"}, + {"-slot3", 0, "-attack;impulse 24"}, + {"+slot4", 0, "impulse 23;+attack"}, + {"-slot4", 0, "-attack;impulse 24"}, + {"+quick1", 0, "impulse 1;+attack"}, + {"-quick1", 0, "-attack"}, + {"+quick2", 0, "impulse 2;+attack"}, + {"-quick2", 0, "-attack"}, + {"+quick3", 0, "impulse 3;+attack"}, + {"-quick3", 0, "-attack"}, + {"+quick4", 0, "impulse 4;+attack"}, + {"-quick4", 0, "-attack"}, + {"menu", 0, "fo_menu_special", 0, "cmd menu"}, + {"changeteam", 0, "fo_menu_team", TF_CHANGETEAM}, + {"teamblue", 0, "cmd changeteam 1", TF_TEAM_1}, + {"teamred", 0, "cmd changeteam 2", TF_TEAM_2}, + {"teamyellow", 0, "cmd changeteam 3", TF_TEAM_3}, + {"teamgreen", 0, "cmd changeteam 4", TF_TEAM_4}, + {"changeclass", 0, "fo_menu_class", TF_CHANGECLASS}, + {"scout", 0, "cmd changeclass 1", TF_CHANGEPC_SCOUT}, + {"sniper", 0, "cmd changeclass 2", TF_CHANGEPC_SNIPER}, + {"soldier", 0, "cmd changeclass 3", TF_CHANGEPC_SOLDIER}, + {"demoman", 0, "cmd changeclass 4", TF_CHANGEPC_DEMOMAN}, + {"medic", 0, "cmd changeclass 5", TF_CHANGEPC_MEDIC}, + {"hwguy", 0, "cmd changeclass 6", TF_CHANGEPC_HVYWEAP}, + {"pyro", 0, "cmd changeclass 7", TF_CHANGEPC_PYRO}, + {"spy", 0, "cmd changeclass 8", TF_CHANGEPC_SPY}, + {"engineer", 0, "cmd changeclass 9", TF_CHANGEPC_ENGINEER}, + {"randompc", 0, "cmd changeclass 10", TF_CHANGEPC_RANDOM}, + {"showclasses", TF_TEAM_CLASSES}, + {"legalclasses", TF_SHOWLEGALCLASSES}, + {"classhelp", TF_CLASSHELP}, + {"query", TF_STATUS_QUERY}, + {"inv", TF_INVENTORY}, + {"showtf", TF_SHOWTF}, + {"showscores", TF_TEAM_SCORES}, + {"flaginfo", FLAG_INFO}, + {"maphelp", TF_HELP_MAP}, + {"showids", TF_SHOW_IDS}, + {"id", TF_ID}, + {"idteam", TF_ID_TEAM}, + {"idenemy", TF_ID_ENEMY}, + {"nexttip", TF_NEXTTIP}, + {"votenext", TF_VOTENEXT}, + {"votetrick", TF_VOTETRICK}, + {"voterace", TF_VOTERACE}, + {"forcenext", TF_FORCENEXT}, + {"togglevote", TF_TOGGLEVOTE}, + {"dropkey", TF_DROPKEY}, + {"dropammo", 0, "fo_menu_dropammo", TF_DROP_AMMO}, + {"dropflag", TF_DROPFLAG}, + {"dropitems", TF_DROPFLAG}, + {"showloc", TF_DISPLAYLOCATION}, + {"special", TF_SPECIAL_SKILL}, + {"special2", TF_SPECIAL_SKILL_2}, + {"saveme", TF_MEDIC_HELPME}, + {"discard", TF_DISCARD}, + {"discard_drop_ammo", TF_DISCARD_DROP_AMMO}, + {"weapnext", TF_WEAPNEXT}, + {"weapprev", TF_WEAPPREV}, + {"weaplast", TF_WEAPLAST}, + {"reload", TF_RELOAD}, + {"reload1", TF_RELOAD_SLOT1}, + {"reload2", TF_RELOAD_SLOT2}, + {"reload3", TF_RELOAD_SLOT3}, + {"reloadnext", TF_RELOAD_NEXT}, + {"grenswitch", TF_GRENADE_SWITCH}, + {"throwgren", TF_GRENADE_T}, + {"primeone", TF_GRENADE_1}, + {"primetwo", TF_GRENADE_2}, + {"+gren1", TF_GRENADE_1}, + {"-gren1", TF_GRENADE_T}, + {"+gren2", TF_GRENADE_2}, + {"-gren2", TF_GRENADE_T}, + {"gren1", TF_GRENADE_PT_1}, + {"gren2", TF_GRENADE_PT_2}, + {"dash", TF_DASH}, + {"autoscan", TF_SCAN}, + {"scansound", TF_SCAN_SOUND}, + {"scanf", TF_SCAN_FRIENDLY}, + {"scane", TF_SCAN_ENEMY}, + {"zoomtoggle", TF_ZOOMTOGGLE}, + {"zoomin", TF_ZOOMIN}, + {"zoomout", TF_ZOOMOUT}, + {"detpipe", TF_PB_DETONATE}, + {"+det5", TF_DETPACK_5}, + {"-det5", TF_DETPACK_STOP}, + {"+det20", TF_DETPACK_20}, + {"-det20", TF_DETPACK_STOP}, + {"+det50", TF_DETPACK_50}, + {"-det50", TF_DETPACK_STOP}, + {"+det255", TF_DETPACK}, + {"-det255", TF_DETPACK_STOP}, + {"aura", TF_MEDIC_AURA_TOGGLE}, + {"locktoggle", TF_HVYWEAP_LOCK_TOGGLE}, + {"lock", TF_LOCKON}, + {"unlock", TF_LOCKOFF}, + {"+lock", TF_LOCKON}, + {"-lock", TF_LOCKOFF}, + {"airblast", TF_AIRBLAST}, + {"disguise", 0, "fo_menu_disguise", TF_SPY_SPY}, + {"+feign", TF_SPY_DIE_ON}, + {"-feign", TF_SPY_DIE_OFF}, + {"feign", TF_SPY_DIE}, + {"sfeign", TF_SPY_SILENT_DIE}, + {"dreset", TF_DISGUISE_RESET}, + {"dscout", TF_DISGUISE_SCOUT}, + {"dsniper", TF_DISGUISE_SNIPER}, + {"dsoldier", TF_DISGUISE_SOLDIER}, + {"ddemoman", TF_DISGUISE_DEMOMAN}, + {"dmedic", TF_DISGUISE_MEDIC}, + {"dhwguy", TF_DISGUISE_HWGUY}, + {"dpyro", TF_DISGUISE_PYRO}, + {"dengineer", TF_DISGUISE_ENGINEER}, + {"dblue", TF_DISGUISE_BLUE}, + {"dred", TF_DISGUISE_RED}, + {"dyellow", TF_DISGUISE_YELLOW}, + {"dgreen", TF_DISGUISE_GREEN}, + {"denemy", TF_DISGUISE_ENEMY}, + {"dlast", TF_DISGUISE_LAST}, + {"dlastspawn", TF_DISGUISE_LAST_SPAWNED}, + {"build", 0, "fo_menu_build", TF_ENGINEER_BUILD}, + {"detsentry", TF_ENGINEER_DETSENTRY}, + {"detdispenser", TF_ENGINEER_DETDISP}, + {"toggledispenser", TF_ENGINEER_TOGGLEDISPENSER}, + {"togglesentry", TF_ENGINEER_TOGGLESENTRY}, + {"ready", TF_PLAYER_READY}, + {"notready", TF_PLAYER_NOT_READY}, + {"nginfo", TF_NAILGREN_INFO}, + {"break", 0, "cmd break"}, + {"voteyes", 0, "cmd voteyes"}, + {"yes", 0, "cmd voteyes"}, + {"fo_settings_status", 0, "cmd fo_settings_status"}, + {"placepracspawn", TF_PRACSPAWN_PLACE}, + {"removepracspawn", TF_PRACSPAWN_REMOVE}, + {"tracktarget", 0, "", 0, "cmd track target"}, +}; + diff --git a/ssqc/client.qc b/ssqc/client.qc index 2666d040..11b0e972 100644 --- a/ssqc/client.qc +++ b/ssqc/client.qc @@ -2942,6 +2942,8 @@ void FO_HandleTFStateUpdate() { self.last_tfstate = self.tfstate; } +void TeamFortress_MOTD(); + void () PlayerPostThink = { FO_CheckClientThink(); UpdateScoreboardInfo(self); @@ -3005,7 +3007,7 @@ void () PlayerPostThink = { FO_ReloadFrame(); ButtonFrame(); W_WeaponFrame(); - if (self.motd <= 400) { + if (self.motd >= 0) { TeamFortress_MOTD(); } else { if (self.cheat_check == 0) { @@ -3049,7 +3051,6 @@ void () ClientConnect = { bprint(PRINT_HIGH, self.netname, " entered the game\n"); self.motd = 0; - self.got_aliases = 0; if (self.netname == string_null) KickCheater(self); diff --git a/ssqc/qw.qc b/ssqc/qw.qc index 10109581..c8450756 100644 --- a/ssqc/qw.qc +++ b/ssqc/qw.qc @@ -49,7 +49,6 @@ float remote_client_time(); .float tp_grenades_2; // 2nd type of grenades being carried .float tp_grenade_switch; // Set to 1 if +gren1 and +gren2 switch places .float hook_out; // Dummy field for hook to silence error messages -.float got_aliases; // TRUE if the player has TeamFortress aliases .float cheat_check; // Time when we'll next check for team cheats .float is_removed; // TRUE if the entity has been removed .float is_undercover; // TRUE for a SPY if they're undercover diff --git a/ssqc/spect.qc b/ssqc/spect.qc index 2b045ce2..24367707 100644 --- a/ssqc/spect.qc +++ b/ssqc/spect.qc @@ -12,7 +12,6 @@ void () SpectatorDisconnect; void () SpectatorImpulseCommand; void () SpectatorThink; -void () Quick_Aliases; void () Admin_Aliases; void () SpectatorConnect = { @@ -29,8 +28,6 @@ void () SpectatorConnect = { if (infokey(self,"*admin")) self.is_admin = stof(infokey(self, "*admin")); - Quick_Aliases(); - st = infokey(self, "apw"); if (st == string_null) st = infokey(self, "adminpwd"); @@ -160,8 +157,6 @@ void () SpectatorThink = { if (self.impulse) SpectatorImpulseCommand(); - //if (self.motd <= 400) - // TeamFortress_MOTD(); if (time >= self.StatusRefreshTime) { RefreshStatusBar(self); } diff --git a/ssqc/tforthlp.qc b/ssqc/tforthlp.qc index a869d546..ab35927d 100644 --- a/ssqc/tforthlp.qc +++ b/ssqc/tforthlp.qc @@ -8,272 +8,66 @@ void (float inp) MOTD_Input = { Menu_Team_Input(inp); }; -void () Quick_Aliases = -{ - TeamFortress_AliasString("+quick1", "impulse 1;+attack"); - TeamFortress_AliasString("-quick1", "-attack"); - TeamFortress_AliasString("+quick2", "impulse 2;+attack"); - TeamFortress_AliasString("-quick2", "-attack"); - TeamFortress_AliasString("+quick3", "impulse 3;+attack"); - TeamFortress_AliasString("-quick3", "-attack"); - TeamFortress_AliasString("+quick4", "impulse 4;+attack"); - TeamFortress_AliasString("-quick4", "-attack"); -}; - -void () TeamFortress_MOTD = { - if (votemode) { +void TeamFortress_MOTD() { + if (votemode) return; - } - local float csqcactive = infokeyf(self, INFOKEY_P_CSQCACTIVE); - if (self.classname == "observer") { - if(!csqcactive) { - TeamFortress_AliasString("tracktarget", "cmd tracktarget"); - } + + if (loginRequired && !self.login) + Menu_Login(); + else + Menu_Team(0); + + float csqcactive = infokeyf(self, INFOKEY_P_CSQCACTIVE); + if (csqcactive) { + self.motd = -1; return; } + // Below is not really tested, it's an attempt at preserving for posterity. + // Expect potential bugs if we ever reintroduce !CSQC support. + const float ALIAS_OFFSET = 100; - local string st1; - local string st2; - local string ya; - - if (self.motd == 5) { - if(csqcactive) { - if(self.team_no == 0 && !intermission_running ) { - if (loginRequired && !self.login) - Menu_Login(); - else - Menu_Team(0); - } - } else { - sprint(self, PRINT_HIGH, "\nFortressOne ", VER, "\n\n"); + if (self.motd == 0) { + if ((teamplay != 0) && (self.team_no == 0)) + stuffcmd(self, "color 0\n"); - st1 = infokey(world, "motd1"); - if (st1 != string_null) { - st2 = infokey(world, "motd2"); - if (st2 != string_null) { - st1 = strcat(strcat(st1, "\n"), st2); - } - } else { - st1 = "Welcome to FortressOne\n==================================\nwww.github.com/FortressOne"; - } + sprint(self, PRINT_HIGH, "\nFortressOne ", VER, "\n\n"); - sprint(self, PRINT_HIGH, st1); - sprint(self, PRINT_HIGH, "\n\n\n"); - if(self.team_no == 0 && !intermission_running) { - Status_Menu(self, MOTD_Input, st1); + string st1, st2; + st1 = infokey(world, "motd1"); + if (st1 != string_null) { + st2 = infokey(world, "motd2"); + if (st2 != string_null) { + st1 = strcat(strcat(st1, "\n"), st2); } - } - } - - if (self.motd == 20) { - if ((teamplay != 0) && (self.team_no == 0)) { - stuffcmd(self, "color "); - ya = ftos(0); - stuffcmd(self, ya); - stuffcmd(self, "\n"); + } else { + st1 = "Welcome to FortressOne\n==================================\nwww.github.com/FortressOne"; } - // will also skip motd - if (self.got_aliases == TRUE) { - self.motd = 400; - return; - } + sprint(self, PRINT_HIGH, strcat(st1, "\n\n\n")); + if(self.team_no == 0 && !intermission_running) + Status_Menu(self, MOTD_Input, st1); - if (csqcactive) { - TeamFortress_AliasString("menu", "fo_menu_special"); - } else { - TeamFortress_AliasString("menu", "cmd menu"); - } + self.motd = ALIAS_OFFSET; + } - TeamFortress_Alias("slot1", TF_IMPULSE_SLOT1, 0); - TeamFortress_Alias("slot2", TF_IMPULSE_SLOT2, 0); - TeamFortress_Alias("slot3", TF_IMPULSE_SLOT3, 0); - TeamFortress_Alias("slot4", TF_IMPULSE_SLOT4, 0); + float idx = self.motd - ALIAS_OFFSET; + if (idx >= 0 && idx < client_aliases.length) { + TFAlias* alias = &client_aliases[idx]; - TeamFortress_AliasString("+slot1", "impulse 20;+attack"); - TeamFortress_AliasString("-slot1", "-attack;impulse 24"); - TeamFortress_AliasString("+slot2", "impulse 21;+attack"); - TeamFortress_AliasString("-slot2", "-attack;impulse 24"); - TeamFortress_AliasString("+slot3", "impulse 22;+attack"); - TeamFortress_AliasString("-slot3", "-attack;impulse 24"); - TeamFortress_AliasString("+slot4", "impulse 23;+attack"); - TeamFortress_AliasString("-slot4", "-attack;impulse 24"); - } else if (self.motd == 30) { - if(csqcactive) { - TeamFortress_AliasString("changeteam", "fo_menu_team"); - TeamFortress_AliasString("teamblue", "cmd changeteam 1"); - TeamFortress_AliasString("teamred", "cmd changeteam 2"); - TeamFortress_AliasString("teamyellow", "cmd changeteam 3"); - TeamFortress_AliasString("teamgreen", "cmd changeteam 4"); - TeamFortress_AliasString("changeclass", "fo_menu_class"); - TeamFortress_AliasString("scout", "cmd changeclass 1"); - TeamFortress_AliasString("sniper", "cmd changeclass 2"); - TeamFortress_AliasString("soldier", "cmd changeclass 3"); - TeamFortress_AliasString("demoman", "cmd changeclass 4"); - TeamFortress_AliasString("medic", "cmd changeclass 5"); - TeamFortress_AliasString("hwguy", "cmd changeclass 6"); - TeamFortress_AliasString("pyro", "cmd changeclass 7"); - TeamFortress_AliasString("spy", "cmd changeclass 8"); - TeamFortress_AliasString("engineer", "cmd changeclass 9"); - TeamFortress_AliasString("randompc", "cmd changeclass 10"); - } else { - TeamFortress_Alias("changeteam", TF_CHANGETEAM, 0); - TeamFortress_Alias("teamblue", TF_TEAM_1, 0); - TeamFortress_Alias("teamred", TF_TEAM_2, 0); - TeamFortress_Alias("teamyellow", TF_TEAM_3, 0); - TeamFortress_Alias("teamgreen", TF_TEAM_4, 0); - TeamFortress_Alias("changeclass", TF_CHANGECLASS, 0); - TeamFortress_Alias("scout", TF_CHANGEPC_SCOUT, 0); - TeamFortress_Alias("sniper", TF_CHANGEPC_SNIPER, 0); - TeamFortress_Alias("soldier", TF_CHANGEPC_SOLDIER, 0); - TeamFortress_Alias("demoman", TF_CHANGEPC_DEMOMAN, 0); - TeamFortress_Alias("medic", TF_CHANGEPC_MEDIC, 0); - TeamFortress_Alias("hwguy", TF_CHANGEPC_HVYWEAP, 0); - TeamFortress_Alias("pyro", TF_CHANGEPC_PYRO, 0); - TeamFortress_Alias("spy", TF_CHANGEPC_SPY, 0); - TeamFortress_Alias("engineer", TF_CHANGEPC_ENGINEER, 0); - TeamFortress_Alias("randompc", TF_CHANGEPC_RANDOM, 0); - } - TeamFortress_Alias("showclasses", TF_TEAM_CLASSES, 0); - TeamFortress_Alias("legalclasses", TF_SHOWLEGALCLASSES, 0); - TeamFortress_Alias("classhelp", TF_CLASSHELP, 0); - } else if (self.motd == 40) { - TeamFortress_Alias("query", TF_STATUS_QUERY, 0); - TeamFortress_Alias("inv", TF_INVENTORY, 0); - TeamFortress_Alias("showtf", TF_SHOWTF, 0); - TeamFortress_Alias("showscores", TF_TEAM_SCORES, 0); - TeamFortress_Alias("flaginfo", FLAG_INFO, 0); - TeamFortress_Alias("maphelp", TF_HELP_MAP, 0); - TeamFortress_Alias("showids", TF_SHOW_IDS, 0); - TeamFortress_Alias("id", TF_ID, 0); - TeamFortress_Alias("idteam", TF_ID_TEAM, 0); - TeamFortress_Alias("idenemy", TF_ID_ENEMY, 0); - TeamFortress_Alias("is_aliased", TF_ALIAS_CHECK, 0); - } else if (self.motd == 50) { - TeamFortress_Alias("nexttip", TF_NEXTTIP, 0); - TeamFortress_Alias("votenext", TF_VOTENEXT, 0); - TeamFortress_Alias("votetrick", TF_VOTETRICK, 0); - TeamFortress_Alias("voterace", TF_VOTERACE, 0); - TeamFortress_Alias("forcenext", TF_FORCENEXT, 0); - TeamFortress_Alias("togglevote", TF_TOGGLEVOTE, 0); - TeamFortress_Alias("dropkey", TF_DROPKEY, 0); - if(csqcactive) { - TeamFortress_AliasString("dropammo", "fo_menu_dropammo"); - } else { - TeamFortress_Alias("dropammo", TF_DROP_AMMO, 0); - } - TeamFortress_Alias("dropflag", TF_DROPFLAG, 0); - TeamFortress_Alias("dropitems", TF_DROPFLAG, 0); - TeamFortress_Alias("showloc", TF_DISPLAYLOCATION, 0); - TeamFortress_Alias("special", TF_SPECIAL_SKILL, 0); - TeamFortress_Alias("special2", TF_SPECIAL_SKILL_2, 0); - TeamFortress_Alias("saveme", TF_MEDIC_HELPME, 0); - TeamFortress_Alias("discard", TF_DISCARD, 0); - TeamFortress_Alias("discard_drop_ammo", TF_DISCARD_DROP_AMMO, 0); - } else if (self.motd == 60) { - TeamFortress_Alias("weapnext", TF_WEAPNEXT, 0); - TeamFortress_Alias("weapprev", TF_WEAPPREV, 0); - TeamFortress_Alias("weaplast", TF_WEAPLAST, 0); - TeamFortress_Alias("reload", TF_RELOAD, 0); - TeamFortress_Alias("reload1", TF_RELOAD_SLOT1, 0); - TeamFortress_Alias("reload2", TF_RELOAD_SLOT2, 0); - TeamFortress_Alias("reload3", TF_RELOAD_SLOT3, 0); - TeamFortress_Alias("reloadnext", TF_RELOAD_NEXT, 0); - } else if (self.motd == 70) { - TeamFortress_Alias("grenswitch", TF_GRENADE_SWITCH, 0); - TeamFortress_Alias("-gren1", TF_GRENADE_T, 0); - TeamFortress_Alias("-gren2", TF_GRENADE_T, 0); - TeamFortress_Alias("throwgren", TF_GRENADE_T, 0); - TeamFortress_Alias("primeone", TF_GRENADE_1, 0); - TeamFortress_Alias("primetwo", TF_GRENADE_2, 0); - TeamFortress_Alias("+gren1", TF_GRENADE_1, 0); - TeamFortress_Alias("+gren2", TF_GRENADE_2, 0); - TeamFortress_Alias("gren1", TF_GRENADE_PT_1, 0); - TeamFortress_Alias("gren2", TF_GRENADE_PT_2, 0); - } else if (self.motd == 80) { - TeamFortress_Alias("dash", TF_DASH, 0); - TeamFortress_Alias("autoscan", TF_SCAN, 0); - TeamFortress_Alias("scansound", TF_SCAN_SOUND, 0); - TeamFortress_Alias("scanf", TF_SCAN_FRIENDLY, 0); - TeamFortress_Alias("scane", TF_SCAN_ENEMY, 0); - TeamFortress_Alias("zoomtoggle", TF_ZOOMTOGGLE, 0); - TeamFortress_Alias("zoomin", TF_ZOOMIN, 0); - TeamFortress_Alias("zoomout", TF_ZOOMOUT, 0); - } else if (self.motd == 90) { - TeamFortress_Alias("detpipe", TF_PB_DETONATE, 0); - TeamFortress_Alias("+det5", TF_DETPACK_5, 0); - TeamFortress_Alias("-det5", TF_DETPACK_STOP, 0); - TeamFortress_Alias("+det20", TF_DETPACK_20, 0); - TeamFortress_Alias("-det20", TF_DETPACK_STOP, 0); - TeamFortress_Alias("+det50", TF_DETPACK_50, 0); - TeamFortress_Alias("-det50", TF_DETPACK_STOP, 0); - TeamFortress_Alias("+det255", TF_DETPACK, 255); - TeamFortress_Alias("-det255", TF_DETPACK_STOP, 0); - } else if (self.motd == 100) { - TeamFortress_Alias("aura", TF_MEDIC_AURA_TOGGLE, 0); - TeamFortress_Alias("locktoggle", TF_HVYWEAP_LOCK_TOGGLE, 0); - TeamFortress_Alias("lock", TF_LOCKON, 0); - TeamFortress_Alias("unlock", TF_LOCKOFF, 0); - TeamFortress_Alias("+lock", TF_LOCKON, 0); - TeamFortress_Alias("-lock", TF_LOCKOFF, 0); - TeamFortress_Alias("airblast", TF_AIRBLAST, 0); - if(csqcactive) { - TeamFortress_AliasString("disguise", "fo_menu_disguise"); - } else { - TeamFortress_Alias("disguise", TF_SPY_SPY, 0); - } - TeamFortress_Alias("+feign", TF_SPY_DIE_ON, 0); - TeamFortress_Alias("-feign", TF_SPY_DIE_OFF, 0); - TeamFortress_Alias("feign", TF_SPY_DIE, 0); - TeamFortress_Alias("sfeign", TF_SPY_SILENT_DIE, 0); - } else if (self.motd == 110) { - TeamFortress_Alias("dreset", TF_DISGUISE_RESET, 0); - TeamFortress_Alias("dscout", TF_DISGUISE_SCOUT, 0); - TeamFortress_Alias("dsniper", TF_DISGUISE_SNIPER, 0); - TeamFortress_Alias("dsoldier", TF_DISGUISE_SOLDIER, 0); - TeamFortress_Alias("ddemoman", TF_DISGUISE_DEMOMAN, 0); - TeamFortress_Alias("dmedic", TF_DISGUISE_MEDIC, 0); - TeamFortress_Alias("dhwguy", TF_DISGUISE_HWGUY, 0); - TeamFortress_Alias("dpyro", TF_DISGUISE_PYRO, 0); - } else if (self.motd == 120) { - TeamFortress_Alias("dengineer", TF_DISGUISE_ENGINEER, 0); - TeamFortress_Alias("dblue", TF_DISGUISE_BLUE, 0); - TeamFortress_Alias("dred", TF_DISGUISE_RED, 0); - TeamFortress_Alias("dyellow", TF_DISGUISE_YELLOW, 0); - TeamFortress_Alias("dgreen", TF_DISGUISE_GREEN, 0); - TeamFortress_Alias("denemy", TF_DISGUISE_ENEMY, 0); - TeamFortress_Alias("dlast", TF_DISGUISE_LAST, 0); - TeamFortress_Alias("dlastspawn", TF_DISGUISE_LAST_SPAWNED, 0); - if(csqcactive) { - TeamFortress_AliasString("build", "fo_menu_build"); - } else { - TeamFortress_Alias("build", TF_ENGINEER_BUILD, 0); - } - TeamFortress_Alias("detsentry", TF_ENGINEER_DETSENTRY, 0); - TeamFortress_Alias("detdispenser", TF_ENGINEER_DETDISP, 0); - TeamFortress_Alias("toggledispenser", TF_ENGINEER_TOGGLEDISPENSER, 0); - TeamFortress_Alias("togglesentry", TF_ENGINEER_TOGGLESENTRY, 0); - } else if (self.motd == 130) { - stuffcmd(self, "is_aliased\n"); - TeamFortress_Alias ("ready", TF_PLAYER_READY, 0); - TeamFortress_Alias ("notready", TF_PLAYER_NOT_READY, 0); - TeamFortress_Alias ("nginfo", TF_NAILGREN_INFO, 0); //nailgreninfo - TeamFortress_AliasString("break", "cmd break"); - TeamFortress_AliasString("voteyes", "cmd voteyes"); - TeamFortress_AliasString("yes", "cmd voteyes"); - TeamFortress_AliasString("fo_settings_status", "cmd fo_settings_status"); - TeamFortress_Alias("placepracspawn", TF_PRACSPAWN_PLACE, 0); - TeamFortress_Alias("removepracspawn", TF_PRACSPAWN_REMOVE, 0); - } else if (self.motd == 140) { - Quick_Aliases(); - } else if (self.motd == 400 && self.team_no == 0 && !csqcactive) { - if (loginRequired && !self.login) - Menu_Login(); + if (alias->nocsqc_cmd) + TeamFortress_AliasString(alias->alias, alias->nocsqc_cmd); + else if (alias->nocsqc_impulse) + TeamFortress_Alias(alias->alias, alias->nocsqc_impulse, 0); + else if (alias->impulse) + TeamFortress_Alias(alias->alias, alias->impulse, 0); else - Menu_Team(1); + TeamFortress_AliasString(alias->alias, alias->cmd); } - self.motd = self.motd + 1; + if (idx < client_aliases.length) + self.motd += 1; + else + self.motd = -1; }; void () TeamFortress_HelpMap = { diff --git a/ssqc/weapons.qc b/ssqc/weapons.qc index 99380711..b5e199e3 100644 --- a/ssqc/weapons.qc +++ b/ssqc/weapons.qc @@ -88,7 +88,6 @@ void () fadefromwhite; void (entity disp) Engineer_UseDispenser; void (entity gun) Engineer_UseSentryGun; -void () TeamFortress_MOTD; void () TeamFortress_HelpMap; void () TeamFortress_NailGrenInfo; @@ -2294,10 +2293,6 @@ void () DeadImpulses = { } } Status_Refresh(self); - } else if (self.impulse == TF_ALIAS_CHECK) { - sprint(self, PRINT_HIGH, "Aliases checked\n"); - self.got_aliases = 1; - self.impulse = 0; } if (self.impulse == TF_PLAYER_READY) { if (clanbattle == 1) { From 18ba2c0405afd5397a7c7d20260e3c47a7a858fa Mon Sep 17 00:00:00 2001 From: Sheldon Johnson Date: Mon, 14 Aug 2023 18:41:16 +1000 Subject: [PATCH 20/22] Use fo_login for stats --- ssqc/events.qc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ssqc/events.qc b/ssqc/events.qc index 404470ec..4090fec9 100644 --- a/ssqc/events.qc +++ b/ssqc/events.qc @@ -29,6 +29,8 @@ string () ISOTimemillis = { string (entity pl) getEntityNameOrLogin = { if (loginRequired) return pl.login; + else if (fo_login_required) + return pl.fo_login; else return clearString(pl.netname); } From efa6ee3078b85bbc61f227f82819e7992591bdf1 Mon Sep 17 00:00:00 2001 From: newby Date: Mon, 14 Aug 2023 20:05:34 -0700 Subject: [PATCH 21/22] client: bind csqc buttons directly Currently we interpose on a variety of alias-like commands (e.g. +grenade1) only to directly translate them back to a command. Just replace these with a direct bind and save the round-trips into CSQC. --- csqc/main.qc | 83 ++++------------------------------------------------ share/defs.h | 14 ++++++++- 2 files changed, 19 insertions(+), 78 deletions(-) diff --git a/csqc/main.qc b/csqc/main.qc index 01877e6b..f0568585 100644 --- a/csqc/main.qc +++ b/csqc/main.qc @@ -63,9 +63,14 @@ static void BindAlias(TFAlias* tfa) { } static void SetupAliases() { - for (float i = 0; i < client_aliases.length; i++) + float i; + + for (i = 0; i < client_aliases.length; i++) BindAlias(&client_aliases[i]); + for (i = 0; i < csqc_aliases.length; i++) + BindAlias(&csqc_aliases[i]); + print("Aliases set\n"); } @@ -123,30 +128,11 @@ noref void(float apiver, string enginename, float enginever) CSQC_Init = { registercommand("+aux_jump"); registercommand("-aux_jump"); - registercommand("+special"); - registercommand("-special"); - registercommand("+special2"); - registercommand("-special2"); - registercommand("+grenade1"); - registercommand("-grenade1"); - registercommand("+grenade2"); - registercommand("-grenade2"); - registercommand("+dropflag"); - registercommand("-dropflag"); registercommand("+rj"); registercommand("-rj"); registercommand("slot_a"); - // registercommand("+quick1"); - // registercommand("-quick1"); - // registercommand("+quick2"); - // registercommand("-quick2"); - // registercommand("+quick3"); - // registercommand("-quick3"); - // registercommand("+quick4"); - // registercommand("-quick4"); - registercommand("tracktarget"); registercommand("+fo_showscores"); registercommand("-fo_showscores"); registercommand("fo_settings_check"); @@ -406,9 +392,6 @@ noref float(string cmd) CSQC_ConsoleCommand = { FO_Show_Scores(FALSE); } break; - case "tracktarget": - localcmd("cmd tracktarget\n"); - break; case "+aux_jump": jump_counter++; localcmd("+jump\n"); @@ -425,60 +408,6 @@ noref float(string cmd) CSQC_ConsoleCommand = { } break; - case "+special": - localcmd("+button3\n"); - break; - case "-special": - localcmd("-button3\n"); - break; - case "+special2": - localcmd("+button4\n"); - break; - case "-special2": - localcmd("-button4\n"); - break; - case "+grenade1": - localcmd("+button5\n"); - break; - case "-grenade1": - localcmd("-button5\n"); - break; - case "+grenade2": - localcmd("+button6\n"); - break; - case "-grenade2": - localcmd("-button6\n"); - break; - case "+dropflag": - localcmd("+button7\n"); - break; - case "-dropflag": - localcmd("-button7\n"); - break; - // case "+quick1": - // localcmd("+button8\n"); - // break; - // case "-quick1": - // localcmd("-button8\n"); - // break; - // case "+quick2": - // localcmd("+button9\n"); - // break; - // case "-quick2": - // localcmd("-button9\n"); - // break; - // case "+quick3": - // localcmd("+button10\n"); - // break; - // case "-quick3": - // localcmd("-button10\n"); - // break; - // case "+quick4": - // localcmd("+button11\n"); - // break; - // case "-quick4": - // localcmd("-button11\n"); - // break; case "+rj": if (player_class == PC_SOLDIER || player_class == PC_PYRO) { localcmd("+button4\n"); diff --git a/share/defs.h b/share/defs.h index 3a1a5ae9..d2d45042 100644 --- a/share/defs.h +++ b/share/defs.h @@ -1690,6 +1690,18 @@ TFAlias client_aliases[] = { {"fo_settings_status", 0, "cmd fo_settings_status"}, {"placepracspawn", TF_PRACSPAWN_PLACE}, {"removepracspawn", TF_PRACSPAWN_REMOVE}, - {"tracktarget", 0, "", 0, "cmd track target"}, + {"tracktarget", 0, "cmd tracktarget", 0, "cmd track target"}, }; +TFAlias csqc_aliases[] = { + {"+special", 0, "+button3"}, + {"-special", 0, "-button3"}, + {"+special2", 0, "+button4"}, + {"-special2", 0, "-button4"}, + {"+grenade1", 0, "+button5"}, + {"-grenade1", 0, "-button5"}, + {"+grenade2", 0, "+button6"}, + {"-grenade2", 0, "-button6"}, + {"+dropflag", 0, "+button7"}, + {"-dropflag", 0, "-button7"}, +}; From 3aece0b70dc26d9c56e6f6d034f7d03c4c045b71 Mon Sep 17 00:00:00 2001 From: newby Date: Tue, 15 Aug 2023 21:22:55 -0700 Subject: [PATCH 22/22] init: fix missing new line The first client_alias bind was being swallowed because there was an partially constructed command in the buffer it was being appended to. --- csqc/main.qc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csqc/main.qc b/csqc/main.qc index f0568585..3df8cadc 100644 --- a/csqc/main.qc +++ b/csqc/main.qc @@ -769,7 +769,7 @@ void Perf_Status() { } void ClientSettings_Check() { - localcmd("cl_movespeedkey 1"); + localcmd("cl_movespeedkey 1\n"); if (cvar("worker_count") == 0) printf("ERROR: Please set `worker_count 4` to reduce stuttering!\n"); if (cvar("r_temporalscenecache") == 0)