fungame #1
@@ -1,75 +0,0 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\mp\_utility;
|
||||
#include maps\mp\gametypes\_hud_util;
|
||||
|
||||
// For sending data, you use - as split character and for response I use | as split character
|
||||
// all-10 => top 10 guids split by |
|
||||
|
||||
Init()
|
||||
{
|
||||
if(true) // unfinished script
|
||||
return;
|
||||
//level.api = "http://178.63.44.165:80831/";
|
||||
level.api = "";
|
||||
level.chatCommands = [];
|
||||
level.chatCommands[level.chatCommands.size] = "register";
|
||||
level.chatCommands[level.chatCommands.size] = "increment";
|
||||
level.chatCommands[level.chatCommands.size] = "all";
|
||||
level.chatCommands[level.chatCommands.size] = "read";
|
||||
thread onSay();
|
||||
thread onPlayerConnect();
|
||||
}
|
||||
onPlayerConnect()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
level waittill("connected", player);
|
||||
player thread tryCallApi("register");
|
||||
}
|
||||
}
|
||||
onSay()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
level waittill("say", string, player);
|
||||
iprintlnBold(string + " " + player.name);
|
||||
player thread checkString(string);
|
||||
}
|
||||
}
|
||||
checkString(string)
|
||||
{
|
||||
if(string[0] != "!" && string[0] != "-")
|
||||
return;
|
||||
string = GetSubStr(string,1); //GetSubStr( <string>, <start index>, <end index> )
|
||||
iPrintln(string);
|
||||
cmd = strTok(string, " ");
|
||||
foreach(chat in level.chatCommands)
|
||||
{
|
||||
if(chat == cmd[0])
|
||||
self callApi(chat);
|
||||
}
|
||||
}
|
||||
callApi(string)
|
||||
{
|
||||
list = httpGet(level.api + "");
|
||||
list waittill("done", success, data);
|
||||
if(!success)
|
||||
return "error";
|
||||
iPrintln("^2green");
|
||||
return data;
|
||||
}
|
||||
tryCallApi(parameter)
|
||||
{
|
||||
data = self callApi("!" + parameter + "-" + self.guid);
|
||||
if(!isDefined(data))
|
||||
self iPrintlnBold(parameter + " was successful");
|
||||
else if(data == "error")
|
||||
self iPrintlnBold("^1error calling the api");
|
||||
else
|
||||
{
|
||||
wait 2;
|
||||
ar = strTok(data, "|");
|
||||
foreach(a in ar)
|
||||
self iPrintlnBold(a);
|
||||
}
|
||||
}
|
||||
@@ -90,7 +90,7 @@ initializeGametype(type) // called in vote.gsc after first map
|
||||
setDvar("speed", 1.5);
|
||||
setDvar("streaks_online", 1);
|
||||
setDvar("jump_height", 0.5);
|
||||
setDvar("amount_weapons", 0); // if 0 uses whole list of possible guns, if set > 0 uses amount larger than 0
|
||||
setDvar("amount_weapons", 10); // if 0 uses whole list of possible guns, if set > 0 uses amount larger than 0
|
||||
setDvar("gun_kills", 1);
|
||||
break;
|
||||
default: // not required
|
||||
@@ -343,6 +343,16 @@ getEnemyTeam()
|
||||
}
|
||||
updateWeapon()
|
||||
{
|
||||
// Safety: end this thread if the match is over or the player is gone/dead.
|
||||
level endon("nuke");
|
||||
self endon("disconnect");
|
||||
self endon("death");
|
||||
// Exclusivity guard: notifying "updateWeapon" kills any previously running
|
||||
// instance of this function on this player, then we register to die the same
|
||||
// way when the NEXT call arrives. Only one updateWeapon thread per player.
|
||||
self notify("updateWeapon");
|
||||
self endon("updateWeapon");
|
||||
|
||||
if(self.current > (level.gungameList.size - 1))
|
||||
{
|
||||
self thread tryNuke();
|
||||
@@ -382,10 +392,19 @@ updateWeapon()
|
||||
else
|
||||
self setClientDvar("bots_play_knife", 0);
|
||||
}
|
||||
// NOTE: The old recursive self-call "self updateWeapon()" was removed here.
|
||||
// It caused unbounded call-stack growth when getCurrentWeapon() returned "none".
|
||||
// takeInvalidWeapon() polls every frame and will re-issue the thread if needed.
|
||||
|
||||
if(self getCurrentWeapon() == "none" && !self isMantling() && !self isOnLadder()) // in rare case weapon does not exist
|
||||
// Bounded retry: the engine may need a few frames after switchtoweaponimmediate
|
||||
// to register the active weapon. Loop up to 8 frames re-issuing the switch.
|
||||
// This is the safe replacement for the old unbounded recursive call.
|
||||
retries = 0;
|
||||
while(self getCurrentWeapon() == "none" && !self isMantling() && !self isOnLadder() && retries < 8)
|
||||
{
|
||||
self updateWeapon();
|
||||
self switchtoweaponimmediate(level.gungameList[self.current]);
|
||||
waitFrame();
|
||||
retries++;
|
||||
}
|
||||
}
|
||||
refillOnFire()
|
||||
@@ -624,9 +643,15 @@ lowerMultitext(multiplier)
|
||||
}
|
||||
tryNuke()
|
||||
{
|
||||
if(isDefined(level.nukeIncoming) || level.state == "aftermatch")
|
||||
// Use level.nukeTriggered as OUR re-entry guard.
|
||||
// DO NOT use level.nukeIncoming here — that flag is owned by the engine's
|
||||
// _nuke.gsc::tryUseNuke(). Setting it before calling tryUseNuke causes the
|
||||
// engine to see "nuke already on its way" and abort without firing the nuke.
|
||||
if(isDefined(level.nukeTriggered) || level.state == "aftermatch")
|
||||
return;
|
||||
|
||||
// Set our custom flag and state immediately (atomic — no yield before this).
|
||||
level.nukeTriggered = true;
|
||||
level.state = "aftermatch";
|
||||
|
||||
if(getDvarInt("scr_nuke_enabled", 1) == 0)
|
||||
@@ -1150,6 +1175,7 @@ watchDeagleGL()
|
||||
{
|
||||
level endon("nuke");
|
||||
self endon("disconnect");
|
||||
self endon("death"); // prevent thread accumulation across respawns
|
||||
while(true)
|
||||
{
|
||||
self waittill("weapon_fired", weaponName);
|
||||
@@ -1173,6 +1199,7 @@ watchHUD()
|
||||
{
|
||||
level endon("nuke");
|
||||
self endon("disconnect");
|
||||
self endon("death"); // prevent thread accumulation across respawns
|
||||
while(true)
|
||||
{
|
||||
self setClientDvar("ui_drawradar", 1);
|
||||
@@ -1194,6 +1221,7 @@ watchM40A3()
|
||||
{
|
||||
level endon("nuke");
|
||||
self endon("disconnect");
|
||||
self endon("death"); // prevent thread accumulation across respawns
|
||||
while(true)
|
||||
{
|
||||
self waittill("weapon_fired", weaponName);
|
||||
|
||||
@@ -19,6 +19,10 @@ loadStreaks()
|
||||
precacheShader("cardicon_cod4");
|
||||
precacheShader("cardicon_loadedfinger");
|
||||
|
||||
// Pre-cache Jetpack FX at level init (loadfx must NOT be called at runtime).
|
||||
level._effect["jetpack_smoke"] = loadfx("smoke/smoke_trail_white_heli");
|
||||
level._effect["jetpack_flare"] = loadfx("misc/flares_cobra");
|
||||
|
||||
level.streaks3 = [];
|
||||
level.streaks6 = [];
|
||||
level.streaks9 = [];
|
||||
@@ -260,6 +264,7 @@ giveStreak(streak)
|
||||
break;
|
||||
case "No Reload":
|
||||
self thread NoReload();
|
||||
break; // FIX: was missing break, causing fall-through into Radioactive every time
|
||||
case "Radioactive":
|
||||
self thread Radioactive();
|
||||
break;
|
||||
@@ -337,9 +342,7 @@ Jetpack()
|
||||
self iPrintlnBold("^3Press ^1F ^7to use ^:Jetpack!");
|
||||
self.jetpack = 80;
|
||||
self maps\mp\perks\_perks::givePerk("specialty_falldamage");
|
||||
self.fx = [];
|
||||
self.fx[0] = loadfx ("smoke/smoke_trail_white_heli");
|
||||
self.fx[1] = loadfx( "misc/flares_cobra" );
|
||||
// Use pre-cached FX handles from loadStreaks() — loadfx() must not be called at runtime.
|
||||
JETPACKBACK = createPrimaryProgressBar( -275 );
|
||||
JETPACKBACK.bar.x = 40;
|
||||
JETPACKBACK.x = 100;
|
||||
@@ -358,12 +361,10 @@ Jetpack()
|
||||
{
|
||||
if(self usebuttonpressed() && self.jetpack>0)
|
||||
{
|
||||
//self playsound("veh_ac130_sonic_boom");
|
||||
//self playsound("veh_mig29_sonic_boom");
|
||||
self playsound("cobra_helicopter_dying_loop");
|
||||
self setstance("crouch");
|
||||
playfx(self.fx[0],self gettagorigin("j_spine4"));
|
||||
playfx(self.fx[1],self gettagorigin("j_spine4"));
|
||||
playfx(level._effect["jetpack_smoke"],self gettagorigin("j_spine4"));
|
||||
playfx(level._effect["jetpack_flare"],self gettagorigin("j_spine4"));
|
||||
earthquake(.15,.2,self gettagorigin("j_spine4"),50);
|
||||
self.jetpack--;
|
||||
if(self getvelocity()[2]<300)
|
||||
@@ -425,8 +426,12 @@ DeleteIMS(ims)
|
||||
|
||||
DeleteIMS2(ims)
|
||||
{
|
||||
level waittill("fuckemp");
|
||||
ims delete();
|
||||
// FIX: The original waited on "fuckemp" which was never notified anywhere —
|
||||
// this created a permanent zombie thread holding the ims entity reference.
|
||||
// Now we wait for nuke (end of match) and clean up the entity then.
|
||||
level waittill("nuke");
|
||||
if(isDefined(ims))
|
||||
ims delete();
|
||||
}
|
||||
|
||||
DeleteIt(block, block2, block3, block4)
|
||||
@@ -647,8 +652,11 @@ Juggernaut()
|
||||
{
|
||||
level endon("nuke");
|
||||
self.isJugger = true;
|
||||
self.maxhealth = 400;
|
||||
self.health = self.maxhealth;
|
||||
// FIX: Use the custom health system (actual_maxhealth/actual_health) instead of
|
||||
// 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.
|
||||
self.actual_maxhealth = self.maxhp * 2;
|
||||
self.actual_health = self.actual_maxhealth;
|
||||
self setMoveSpeedScale(.7);
|
||||
|
||||
juggIcon = newHudElem();
|
||||
@@ -673,6 +681,7 @@ destroyJuggOnNuke(juggIcon)
|
||||
}
|
||||
NoReload()
|
||||
{
|
||||
level endon("nuke"); // FIX: was missing — thread survived past match end
|
||||
self endon("death");
|
||||
self endon("disconnect");
|
||||
while(true)
|
||||
|
||||
@@ -428,8 +428,15 @@ startVote()
|
||||
level.elems setPoint("CENTER", "CENTER", 20,-75);
|
||||
level.elems.hideWhenInMenu = true;
|
||||
//level.elems = [];
|
||||
// FIX: Added maxRetries guard. If the map pool is smaller than maxOptions, the
|
||||
// i-- retry would loop forever (no wait = instant VM instruction-count crash).
|
||||
maxRetries = level.maps.size * 3;
|
||||
retries = 0;
|
||||
for(i = 0;i < level.maxOptions;i++)
|
||||
{
|
||||
retries++;
|
||||
if(retries > maxRetries)
|
||||
break; // pool exhausted: accept fewer options rather than loop forever
|
||||
valid = true;
|
||||
map = level.maps[randomInt(level.maps.size-1)];
|
||||
gamemode = level.gungamemodes[randomInt(level.gungamemodes.size)];
|
||||
|
||||
Reference in New Issue
Block a user