From bff8c7cfa69b197bee07f5379a6e520afb5b9eb2 Mon Sep 17 00:00:00 2001 From: Kibi Kelburton Date: Sat, 9 May 2026 17:16:32 +0200 Subject: [PATCH] fix this fucking configstringindex overflow --- mod/main.gsc | 26 +++++++++++++++++--------- mod/streaks.gsc | 5 +++-- mod/vote.gsc | 30 +++++++++++++----------------- 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/mod/main.gsc b/mod/main.gsc index 458b1c9..63c77c6 100755 --- a/mod/main.gsc +++ b/mod/main.gsc @@ -330,7 +330,7 @@ loadSetup() self.actual_health = self.actual_maxhealth; self.maxhealth = 1000; self.health = 1000; - self thread watchHealthHUD(); + // watchHealthHUD removed — HP display not wanted self thread watchRegen(); self thread watchDeagleGL(); self thread watchM40A3(); @@ -385,7 +385,9 @@ upgradeOnTeamKills() enemyTeam = self getEnemyTeam(); self.current = level.teamKills[self.team + "_weapon"]; self thread updateWeapon(); - self.weaponhud setText("Gun: " + self.current + "/" + (level.gungameList.size) + "/^3" + level.teamKills[enemyTeam + "_weapon"]); + // setText() is safe here: bounded to ~N unique strings where N = weapon count. + // Configstrings are deduplicated, so all players sharing the same weapon# reuse one slot. + self.weaponhud setText("Gun: " + self.current + " / " + (level.gungameList.size) + " / ^3" + level.teamKills[enemyTeam + "_weapon"]); } } getEnemyTeam() @@ -660,7 +662,10 @@ scorepopup(amount) self.scoretext_amount.color = color; self.scoretext_amount.glowColor = glowColor; self.scoretext_amount SetPulseFX( 40, 2000, 600 ); - self.scoretext_amount setText("+" + self.amount); + // FIX: Use .label + setValue() instead of setText("+" + amount). + // Each unique amount string burned a permanent configstring slot. + self.scoretext_amount.label = &"+"; + self.scoretext_amount setValue(self.amount); if(self.multiplier > 1) { self.multitext[self.multiplier].alpha = 1; @@ -679,11 +684,13 @@ scorepopup(amount) self.multitext[self.multiplier] setText("Multi Kill!"); else if(self.multiplier > 4) { - color = []; - for(i = 0;i < 13;i++) - color[i] = randomInt(9); difference = self.multiplier - 4; - self.multitext[5] setText("^3x" + difference + " ^" + color[0] + "K^" + color[1] + "i^" + color[2] + "l^" + color[3] + "l^" + color[4] + "i^" + color[5] + "n^" + color[6] + "g ^" + color[7] + "S^" + color[8] + "p^" + color[9] + "r^" + color[10] + "e^" + color[11] + "e^" + color[12] + "!"); + // FIX: Use a fixed string instead of randomized color codes. + // The old rainbow text generated a unique configstring for every kill spree + // (random colors = unique string every time = configstring leak). + // FIX: Use .label + setValue() to avoid configstring leak per spree level. + self.multitext[5].label = &"^1K^2i^3l^4l^5i^6n^7g ^1S^2p^3r^4e^5e ^3x"; + self.multitext[5] setValue(difference); } self thread lowerMultiplier(); } @@ -741,7 +748,7 @@ tryNuke() } if(getDvar("g_gametype") != "gungame_team") - self.weaponhud setText("Gun: " + (level.gungameList.size-1)); + self.weaponhud setText("Gun: " + (level.gungameList.size - 1)); } createUI() { @@ -759,9 +766,10 @@ createWeaponHud() self.weaponhud.color = (1,1,0); self.weaponhud.hideWhenInMenu = true; self.weaponhud.glowcolor = (1,0,0); + // setText() is safe here: max ~162 unique strings, configstrings are deduplicated. self.weaponhud setText("Gun: " + self.current + " / " + (level.gungameList.size - 1)); - // weapontotalhud kept defined but hidden — total is now inline in weaponhud text + // weapontotalhud kept defined but hidden — total is inline in weaponhud text self.weapontotalhud = self createFontString("hudsmall", 1.2); self.weapontotalhud.alpha = 0; } diff --git a/mod/streaks.gsc b/mod/streaks.gsc index b4b3316..31c7a8e 100755 --- a/mod/streaks.gsc +++ b/mod/streaks.gsc @@ -471,8 +471,9 @@ BombThem(ims) Boom(player, expos) { player playsound ("claymore_activated"); - level._effect["bombexplosion"] = loadfx("explosions/tanker_explosion"); - PlayFx( level._effect["bombexplosion"], expos ); + // FIX: loadfx() must NEVER be called at runtime — only at level init. + // Reuse the pre-cached explosion handle from Init(). + PlayFx( level._effect["claymore_explode"], expos ); //RadiusDamage(self.origin,350,500,100,level); MagicBullet("ac130_105mm_mp", expos, expos+(0,-100,-1000), self); MagicBullet("ac130_105mm_mp", expos, expos+(100,0, -10), self); diff --git a/mod/vote.gsc b/mod/vote.gsc index 6e9e13b..a4d35c6 100755 --- a/mod/vote.gsc +++ b/mod/vote.gsc @@ -337,22 +337,12 @@ createPlayerRectangle(shader,align, relative, x, y, width, height) doCountdown(timer,timer2) { secs = 20; - milisecs = 10; - while(secs > 0) + timer.label = &"Time left: "; + timer2.alpha = 0; // subsecond display removed + for(secs = 20; secs > 0; secs--) { - milisecs--; - if(milisecs == 0) - { - milisecs = 10; - secs--; - } - if(secs == 9) - { - timer2 setPoint("LEFT", "CENTER", 20,90); - } - timer setText("Time left: " + secs); - timer2 setValue(milisecs); - wait .1; + timer setValue(secs); + wait 1; } level notify("finishVote"); } @@ -399,7 +389,7 @@ startVote() //background3 = createRectangle("black","CENTER", "CENTER", 225,0,180,75); //background3.alpha = .7; timer = level createServerFontString("default", 1.8); - timer setPoint("CENTER", "CENTER", -20,90); + timer setPoint("CENTER", "CENTER", 0,90); timer.hideWhenInMenu = true; timer2 = level createServerFontString("default", 1.8); @@ -539,12 +529,18 @@ doControls() voted = true; level.votes[self.position]++; //level.elems[self.position] setText(getDisplayName(level.options[self.position]) + " [" + level.votes[self.position] + "]"); + // FIX: Rebuild vote text only if it actually changed, and cap total rebuilds. + // Each unique setText() string permanently burns a configstring slot (512 limit). text = ""; for(i = 0;i < level.maxOptions;i++) { text += getDisplayName(level.options[i].map) + " [^3" + level.options[i].gamemode + "^7][" + level.votes[i] + "]\n"; } - level.elems setText(text); + if(!isDefined(level._lastVoteText) || level._lastVoteText != text) + { + level.elems setText(text); + level._lastVoteText = text; + } } } onForward()