keeping movement speed intact throughout the game, keep track of ammo properly

This commit is contained in:
2026-05-07 05:15:10 +02:00
parent 1611bff8a6
commit 9b08664f6a
2 changed files with 43 additions and 14 deletions

View File

@@ -208,7 +208,9 @@ launchGame()
{ {
player enableWeapons(); player enableWeapons();
player visionSetNakedForPlayer(getDvar("mapname"), 2); player visionSetNakedForPlayer(getDvar("mapname"), 2);
player setMoveSpeedScale(1.25); // Use the mode-configured speed dvar, not a hardcoded value.
// Fungame = 1.5, Classic = 1.2, etc. — 1.25 was always wrong for Fungame.
player setMoveSpeedScale(getDvarFloat("speed"));
} }
setDvar("jump_height", 60); setDvar("jump_height", 60);
@@ -395,15 +397,22 @@ updateWeapon()
self giveWeapon("onemanarmy_mp"); self giveWeapon("onemanarmy_mp");
self takeWeapon(self getCurrentWeapon()); self takeWeapon(self getCurrentWeapon());
self giveMaxAmmo(level.gungameList[self.current]); self giveMaxAmmo(level.gungameList[self.current]);
self setWeaponAmmoClip(level.gungameList[self.current], 9999); // force full clip — giveMaxAmmo only fills stock/reserve
waitFrame(); waitFrame();
self switchtoweaponimmediate(level.gungameList[self.current]); self switchtoweaponimmediate(level.gungameList[self.current]);
waitFrame(); waitFrame();
self setWeaponAmmoClip(level.gungameList[self.current], 9999); // re-apply after switch to prevent forced reload
if(level.state == "prematch" || level.state == "ingame") if(level.state == "prematch" || level.state == "ingame")
self show(); self show();
if(self.isJugger) // Always restore the correct speed, clamped to the mode's configured base floor.
self setMoveSpeedScale(1); // getBaseSpeed() ensures no path can silently drop below the dvar-configured minimum.
else if(self.speed) if(level.state != "prematch")
self setMoveSpeedScale(1.6); {
if(self.speed)
self setMoveSpeedScale(1.6); // Speed streak: above base, always fine
else
self setMoveSpeedScale(getBaseSpeed()); // Juggernaut and normal: always >= base speed
}
if(level.state == "prematch") if(level.state == "prematch")
{ {
self setMoveSpeedScale(0); self setMoveSpeedScale(0);
@@ -822,13 +831,21 @@ floatToString(float)
string = getSubStr(string, 0, 5); string = getSubStr(string, 0, 5);
return StringToFloat(string); return StringToFloat(string);
} }
// Returns the mode-configured base speed, clamped so nothing can go below it.
// All setMoveSpeedScale calls for non-prematch state should go through this
// (or compare against it) to honour the 1.5 Fungame / 1.2 Classic floor contract.
getBaseSpeed()
{
base = getDvarFloat("speed");
return base;
}
takeInvalidWeapon() takeInvalidWeapon()
{ {
self endon("disconnect"); self endon("disconnect");
self endon("death"); self endon("death");
level endon("nuke"); level endon("nuke");
counter = 0; counter = 0;
wait 3; waitFrame(); // was: wait 3 — removed so mid-game joiners get their weapon immediately
while(1) while(1)
{ {
wait 0.1; // was waitFrame() (~60/s) — 10/s is ample for a safety-net poller wait 0.1; // was waitFrame() (~60/s) — 10/s is ample for a safety-net poller
@@ -1320,11 +1337,22 @@ watchBotRiotShield()
if(dot > 0.25) // 0.25 ~= 75 degree half-angle if(dot > 0.25) // 0.25 ~= 75 degree half-angle
{ {
// Apply riot shield bash damage (100 = standard MW2 shield bash) // The mod pins engine health at 1000 and tracks real HP in actual_health.
player thread maps\mp\gametypes\_damage::finishPlayerDamageWrapper( // finishPlayerDamageWrapper only hits engine health (which never changes),
self, self, 100, 0, "MOD_MELEE", "riotshield_mp", // so we apply damage directly to the scripted HP instead.
player getOrigin(), player getOrigin(), "none", 0, 0 bashDamage = 100;
); player.actual_health -= bashDamage;
player notify("takeDamage"); // reset regen timer
if(player.actual_health <= 0)
{
player.actual_health = 0;
// Drive a lethal hit through the engine so the kill is attributed correctly.
player thread maps\mp\gametypes\_damage::finishPlayerDamageWrapper(
self, self, 1000, 0, "MOD_MELEE", "riotshield_mp",
player getOrigin(), player getOrigin(), "none", 0, 0
);
}
break; // one target per swing break; // one target per swing
} }
} }

View File

@@ -236,7 +236,7 @@ giveStreak(streak)
wait 1; wait 1;
self maps\mp\perks\_perks::givePerk("specialty_lightweight"); self maps\mp\perks\_perks::givePerk("specialty_lightweight");
self setMoveSpeedScale(1.6); self setMoveSpeedScale(1.6);
self.setMoveSpeedScale = 1.6; self.moveSpeedScaler = 1.6; // keep cached baseline in sync (was: self.setMoveSpeedScale = 1.6 — typo, set entity field not call function)
break; break;
case "Riotshield": case "Riotshield":
self AttachShieldModel( "weapon_riot_shield_mp", "tag_shield_back" ); self AttachShieldModel( "weapon_riot_shield_mp", "tag_shield_back" );
@@ -648,10 +648,11 @@ Juggernaut()
self.isJugger = true; self.isJugger = true;
// FIX: Use the custom health system (actual_maxhealth/actual_health) instead of // FIX: Use the custom health system (actual_maxhealth/actual_health) instead of
// the raw engine maxhealth. Setting engine maxhealth directly broke the HUD display // the raw engine maxhealth. Setting engine maxhealth directly broke the HUD display
// and regen logic. We double the effective HP pool through the custom system. // and regen logic. We multiply the effective HP pool through the custom system.
self.actual_maxhealth = self.maxhp * 5; // 5× base HP (e.g. 300 in Fungame vs normal 60) self.actual_maxhealth = self.maxhp * 5; // 5× base HP (e.g. 300 in Fungame vs normal 60)
self.actual_health = self.actual_maxhealth; self.actual_health = self.actual_maxhealth;
self setMoveSpeedScale(.7); // Speed floor is the mode base (1.5 in Fungame) — no slowdown penalty.
// Juggernaut's balance trade-off is the 5× HP pool only.
juggIcon = newHudElem(); juggIcon = newHudElem();
juggIcon.x = self.origin[0]; juggIcon.x = self.origin[0];