self.team = activator.team;
some_spawn_has_been_used = 1;
}
-};
+}
// Returns:
// _x: prio (-1 if unusable)
// _y: weight
-vector Spawn_Score(entity spot, entity playerlist, float teamcheck, float anypoint)
+vector Spawn_Score(entity spot, float mindist, float teamcheck)
{
float shortest, thisdist;
float prio;
return '-1 0 0';
}
+ shortest = vlen(world.maxs - world.mins);
+ FOR_EACH_PLAYER(player) if (player != self)
+ {
+ thisdist = vlen(player.origin - spot.origin);
+ if (thisdist < shortest)
+ shortest = thisdist;
+ }
+ if(shortest > mindist)
+ prio += SPAWN_PRIO_GOOD_DISTANCE;
+
+ spawn_score = prio * '1 0 0' + shortest * '0 1 0';
+ spawn_spot = spot;
+
// filter out spots for assault
if(spot.target != "") {
- local entity ent;
- float good, found;
- ent = find(world, targetname, spot.target);
+ entity ent;
+ float found;
- while(ent) {
- if(ent.classname == "target_objective")
- {
- found = 1;
- if(ent.health < 0 || ent.health >= ASSAULT_VALUE_INACTIVE)
- return '-1 0 0';
- good = 1;
- }
- else if(ent.classname == "trigger_race_checkpoint")
+ found = 0;
+ for(ent = world; (ent = find(ent, targetname, spot.target)); )
+ {
+ ++found;
+ if(ent.spawn_evalfunc)
{
- found = 1;
- if(!anypoint) // spectators may spawn everywhere
-
- {
- if(g_race_qualifying)
- {
- // spawn at first
- if(ent.race_checkpoint != 0)
- return '-1 0 0';
- if(spot.race_place != race_lowest_place_spawn)
- return '-1 0 0';
- }
- else
- {
- if(ent.race_checkpoint != self.race_respawn_checkpoint)
- return '-1 0 0';
- // try reusing the previous spawn
- if(ent == self.race_respawn_spotref || spot == self.race_respawn_spotref)
- prio += 1;
- if(ent.race_checkpoint == 0)
- {
- float pl;
- pl = self.race_place;
- if(pl > race_highest_place_spawn)
- pl = 0;
- if(pl == 0 && !self.race_started)
- pl = race_highest_place_spawn; // use last place if he has not even touched finish yet
- if(spot.race_place != pl)
- return '-1 0 0';
- }
- }
- }
- good = 1;
+ entity oldself = self;
+ self = ent;
+ spawn_score = ent.spawn_evalfunc(oldself, spot, spawn_score);
+ self = oldself;
+ if(spawn_score_x < 0)
+ return spawn_score;
}
- ent = find(ent, targetname, spot.target);
}
- if(found && !good)
+ if(!found)
+ {
+ dprint("WARNING: spawnpoint at ", vtos(spot.origin), " could not find its target ", spot.target, "\n");
return '-1 0 0';
+ }
}
- player = playerlist;
- shortest = vlen(world.maxs - world.mins);
- for(player = playerlist; player; player = player.chain)
- if (player != self)
- {
- thisdist = vlen(player.origin - spot.origin);
- if (thisdist < shortest)
- shortest = thisdist;
- }
- return prio * '1 0 0' + shortest * '0 1 0';
+ MUTATOR_CALLHOOK(Spawn_Score);
+ return spawn_score;
+}
+
+void Spawn_ScoreAll(entity firstspot, float mindist, float teamcheck)
+{
+ entity spot;
+ for(spot = firstspot; spot; spot = spot.chain)
+ spot.spawnpoint_score = Spawn_Score(spot, mindist, teamcheck);
}
-float spawn_allbad;
-float spawn_allgood;
-entity Spawn_FilterOutBadSpots(entity firstspot, entity playerlist, float mindist, float teamcheck, float anypoint)
+entity Spawn_FilterOutBadSpots(entity firstspot, float mindist, float teamcheck)
{
- local entity spot, spotlist, spotlistend;
- spawn_allgood = TRUE;
- spawn_allbad = TRUE;
+ entity spot, spotlist, spotlistend;
spotlist = world;
spotlistend = world;
+ Spawn_ScoreAll(firstspot, mindist, teamcheck);
+
for(spot = firstspot; spot; spot = spot.chain)
{
- spot.spawnpoint_score = Spawn_Score(spot, playerlist, teamcheck, anypoint);
-
- if(autocvar_spawn_debugview)
- {
- setmodel(spot, "models/runematch/rune.mdl");
- if(spot.spawnpoint_score_y < mindist)
- {
- spot.colormod = '1 0 0';
- spot.scale = 1;
- }
- else
- {
- spot.colormod = '0 1 0';
- spot.scale = spot.spawnpoint_score_y / mindist;
- }
- }
-
if(spot.spawnpoint_score_x >= 0) // spawning allowed here
{
- if(spot.spawnpoint_score_y < mindist)
- {
- // too short distance
- spawn_allgood = FALSE;
- }
- else
- {
- // perfect
- spawn_allbad = FALSE;
-
- if(spotlistend)
- spotlistend.chain = spot;
- spotlistend = spot;
- if(!spotlist)
- spotlist = spot;
-
- /*
- if(teamcheck >= 0)
- if(spot.team != teamcheck)
- error("invalid spawn added");
-
- print("added ", etos(spot), "\n");
- */
- }
+ if(spotlistend)
+ spotlistend.chain = spot;
+ spotlistend = spot;
+ if(!spotlist)
+ spotlist = spot;
}
}
if(spotlistend)
spotlistend.chain = world;
- /*
- entity e;
- if(teamcheck >= 0)
- for(e = spotlist; e; e = e.chain)
- {
- print("seen ", etos(e), "\n");
- if(e.team != teamcheck)
- error("invalid spawn found");
- }
- */
-
return spotlist;
}
{
// weight of a point: bound(lower, mindisttoplayer, upper)^exponent
// multiplied by spot.cnt (useful if you distribute many spawnpoints in a small area)
- local entity spot;
+ entity spot;
RandomSelection_Init();
for(spot = firstspot; spot; spot = spot.chain)
*/
entity SelectSpawnPoint (float anypoint)
{
- local float teamcheck;
- local entity firstspot_new;
- local entity spot, firstspot, playerlist;
+ float teamcheck;
+ entity spot, firstspot;
spot = find (world, classname, "testplayerstart");
if (spot)
return spot;
- if(anypoint)
+ if(anypoint || autocvar_g_spawn_useallspawns)
teamcheck = -1;
else if(have_team_spawns > 0)
{
// if we get here, we either require team spawns but have none, or we require non-team spawns and have none; use any spawn then
- // get the list of players
- playerlist = findchain(classname, "player");
// get the entire list of spots
firstspot = findchain(classname, "info_player_deathmatch");
// filter out the bad ones
}
else
{
- firstspot_new = Spawn_FilterOutBadSpots(firstspot, playerlist, 100, teamcheck, anypoint);
- if(!firstspot_new)
- firstspot_new = Spawn_FilterOutBadSpots(firstspot, playerlist, -1, teamcheck, anypoint);
- firstspot = firstspot_new;
+ float mindist;
+ if (arena_roundbased && !g_ca)
+ mindist = 800;
+ else
+ mindist = 100;
+ firstspot = Spawn_FilterOutBadSpots(firstspot, mindist, teamcheck);
// there is 50/50 chance of choosing a random spot or the furthest spot
// (this means that roughly every other spawn will be furthest, so you
// usually won't get fragged at spawn twice in a row)
- if (arena_roundbased && !g_ca)
- {
- firstspot_new = Spawn_FilterOutBadSpots(firstspot, playerlist, 800, teamcheck, anypoint);
- if(firstspot_new)
- firstspot = firstspot_new;
- spot = Spawn_WeightedPoint(firstspot, 1, 1, 1);
- }
- else if (random() > autocvar_g_spawn_furthest)
+ if (random() > autocvar_g_spawn_furthest)
spot = Spawn_WeightedPoint(firstspot, 1, 1, 1);
else
spot = Spawn_WeightedPoint(firstspot, 1, 5000, 5); // chooses a far far away spawnpoint
}
- if(autocvar_spawn_debugview)
- {
- print("spot mindistance: ", vtos(spot.spawnpoint_score), "\n");
-
- entity e;
- if(teamcheck >= 0)
- for(e = firstspot; e; e = e.chain)
- if(e.team != teamcheck)
- error("invalid spawn found");
- }
-
if (!spot)
{
if(autocvar_spawn_debug)
self.classname = "observer";
self.iscreature = FALSE;
+ self.damagedbycontents = FALSE;
self.health = -666;
self.takedamage = DAMAGE_NO;
self.solid = SOLID_NOT;
self.frags = FRAGS_SPECTATOR;
}
+.float model_randomizer;
void FixPlayermodel()
{
- local string defaultmodel;
- local float defaultskin, chmdl, oldskin;
- local vector m1, m2;
+ string defaultmodel;
+ float defaultskin, chmdl, oldskin, n, i;
+ vector m1, m2;
defaultmodel = "";
- if(autocvar_sv_defaultcharacter == 1) {
+ if(autocvar_sv_defaultcharacter == 1)
+ {
defaultskin = 0;
if(teamplay)
defaultmodel = autocvar_sv_defaultplayermodel;
defaultskin = autocvar_sv_defaultplayerskin;
}
+
+ n = tokenize_console(defaultmodel);
+ if(n > 0)
+ defaultmodel = argv(floor(n * self.model_randomizer));
+
+ i = strstrofs(defaultmodel, ":", 0);
+ if(i >= 0)
+ {
+ defaultskin = stof(substring(defaultmodel, i+1, -1));
+ defaultmodel = substring(defaultmodel, 0, i);
+ }
}
if(self.modelindex == 0 && self.deadflag == DEAD_NO)
WriteByte(MSG_ONE, SVC_SETVIEW);
WriteEntity(MSG_ONE, self);
}
+
+ // reset player keys
+ self.itemkeys = 0;
// player is dead and becomes observer
// FIXME fix LMS scoring for new system
self.classname = "player";
self.wasplayer = TRUE;
self.iscreature = TRUE;
+ self.damagedbycontents = TRUE;
self.movetype = MOVETYPE_WALK;
self.solid = SOLID_SLIDEBOX;
self.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_SOLID;
if(INDEPENDENT_PLAYERS)
MAKE_INDEPENDENT_PLAYER(self);
self.flags = FL_CLIENT;
+ if(autocvar__notarget)
+ self.flags |= FL_NOTARGET;
self.takedamage = DAMAGE_AIM;
if(g_minstagib)
self.effects = EF_FULLBRIGHT;
self.prevorigin = self.origin;
self.lastrocket = world; // stop rocket guiding, no revenge from the grave!
self.lastteleporttime = time; // prevent insane speeds due to changing origin
-
+ self.hud = HUD_NORMAL;
+
if(g_arena)
{
Spawnqueue_Remove(self);
race_PostSpawn(spot);
- if(autocvar_spawn_debug)
- {
- sprint(self, strcat("spawnpoint origin: ", vtos(spot.origin), "\n"));
- remove(spot); // usefull for checking if there are spawnpoints, that let drop through the floor
- }
-
//stuffcmd(self, "chase_active 0");
//stuffcmd(self, "set viewsize $tmpviewsize \n");
entity e;
e = get_weaponinfo(j);
if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
- self.weapon_load[j] = cvar(strcat("g_balance_", e.netname, "_reload_ammo"));
+ self.(weapon_load[j]) = cvar(strcat("g_balance_", e.netname, "_reload_ammo"));
}
oldself = self;
activator = world;
self = oldself;
+ spawn_spot = spot;
MUTATOR_CALLHOOK(PlayerSpawn);
+ if(autocvar_spawn_debug)
+ {
+ sprint(self, strcat("spawnpoint origin: ", vtos(spot.origin), "\n"));
+ remove(spot); // usefull for checking if there are spawnpoints, that let drop through the floor
+ }
+
self.switchweapon = w_getbestweapon(self);
self.cnt = -1; // W_LastWeapon will not complain
self.weapon = 0;
if(!self.alivetime)
self.alivetime = time;
+
+ antilag_clear(self);
} else if(self.classname == "observer" || (g_ca && !allowed_to_spawn)) {
PutObserverInServer ();
}
// Wazat's grappling hook
SetGrappleHookBindings();
- // get autoswitch state from player when he toggles it
- stuffcmd(self, "alias autoswitch \"set cl_autoswitch $1 ; cmd autoswitch $1\"\n"); // default.cfg-ed in 2.4.1
-
// get version info from player
stuffcmd(self, "cmd clientversion $gameversion\n");
if(!autocvar_g_campaign)
Send_CSQC_Centerprint_Generic(self, CPID_MOTD, getwelcomemessage(), autocvar_welcome_message_time, 0);
+
+ self.model_randomizer = random();
}
/*
Portal_ClearAll(self);
+ RemoveGrapplingHook(self);
if(self.flagcarried)
DropFlag(self.flagcarried, world, world);
if(self.ballcarried && g_nexball)
self.model = self.mdl;
else
self.model = "";
-};
+}
void UpdateChatBubble()
{
// added to the model skins
/*void UpdateColorModHack()
{
- local float c;
+ float c;
c = self.clientcolors & 15;
// LordHavoc: only bothering to support white, green, red, yellow, blue
if (!teamplay) self.colormod = '0 0 0';
else if (c == 12) self.colormod = '1.22 1.22 0.10';
else if (c == 13) self.colormod = '0.10 0.10 1.73';
else self.colormod = '1 1 1';
-};*/
+}*/
.float oldcolormap;
void respawn(void)
self.avelocity = randomvec() * autocvar_g_respawn_ghosts_speed * 3 - randomvec() * autocvar_g_respawn_ghosts_speed * 3;
self.effects |= EF_ADDITIVE;
self.oldcolormap = self.colormap;
- self.colormap = 512;
+ self.colormap = 0; // this originally was 512, but raises a warning in the engine, so get rid of it
pointparticles(particleeffectnum("respawn_ghost"), self.origin, '0 0 0', 1);
if(autocvar_g_respawn_ghosts_maxtime)
SUB_SetFade (self, time + autocvar_g_respawn_ghosts_maxtime / 2 + random () * (autocvar_g_respawn_ghosts_maxtime - autocvar_g_respawn_ghosts_maxtime / 2), 1.5);
self.dmg_save = spectatee.dmg_save;
self.dmg_inflictor = spectatee.dmg_inflictor;
self.angles = spectatee.v_angle;
- if(!(self.BUTTON_USELEGACY || self.BUTTON_USEPRESSED))
+ if(!self.BUTTON_USE)
self.fixangle = TRUE;
setorigin(self, spectatee.origin);
setsize(self, spectatee.mins, spectatee.maxs);
return FALSE; // forced spectators can never join
// TODO simplify this
- local entity e;
+ entity e;
- local float totalClients;
+ float totalClients;
FOR_EACH_CLIENT(e)
totalClients += 1;
if (!autocvar_g_maxplayers)
return maxclients - totalClients + includeMe;
- local float currentlyPlaying;
+ float currentlyPlaying;
FOR_EACH_REALPLAYER(e)
currentlyPlaying += 1;
self.classname = "spectator";
}
} else {
- prefered_movetype = ((!(self.BUTTON_USELEGACY || self.BUTTON_USEPRESSED) ? self.cvar_cl_clippedspectating : !self.cvar_cl_clippedspectating) ? MOVETYPE_FLY_WORLDONLY : MOVETYPE_NOCLIP);
+ prefered_movetype = ((!self.BUTTON_USE ? self.cvar_cl_clippedspectating : !self.cvar_cl_clippedspectating) ? MOVETYPE_FLY_WORLDONLY : MOVETYPE_NOCLIP);
if (self.movetype != prefered_movetype)
self.movetype = prefered_movetype;
}
MUTATOR_CALLHOOK(PlayerPreThink);
- if(self.BUTTON_USELEGACY && !self.usekeypressed)
- PlayerUseKey();
- self.usekeypressed = self.BUTTON_USELEGACY;
+ if(!self.cvar_cl_newusekeysupported) // FIXME remove this - it was a stupid idea to begin with, we can JUST use the button
+ {
+ if(self.BUTTON_USE && !self.usekeypressed)
+ PlayerUseKey();
+ self.usekeypressed = self.BUTTON_USE;
+ }
PrintWelcomeMessage();
{
if(frametime)
player_anim();
- button_pressed = (self.BUTTON_ATCK || self.BUTTON_JUMP || self.BUTTON_ATCK2 || self.BUTTON_HOOK || self.BUTTON_USELEGACY || self.BUTTON_USEPRESSED);
+ button_pressed = (self.BUTTON_ATCK || self.BUTTON_JUMP || self.BUTTON_ATCK2 || self.BUTTON_HOOK || self.BUTTON_USE);
force_respawn = (g_lms || g_ca || g_cts || autocvar_g_forced_respawn);
if (self.deadflag == DEAD_DYING)
{
self.prevorigin = self.origin;
- if ((self.BUTTON_CROUCH && !self.hook.state) || self.health <= g_bloodloss)
+ if (((self.BUTTON_CROUCH && !self.hook.state) || self.health <= g_bloodloss) && self.animstate_startframe != self.anim_melee_x) // prevent crouching if using melee attack
{
if (!self.crouch)
{
self.crouch = TRUE;
self.view_ofs = PL_CROUCH_VIEW_OFS;
setsize (self, PL_CROUCH_MIN, PL_CROUCH_MAX);
- setanim(self, self.anim_duck, FALSE, TRUE, TRUE);
+ // setanim(self, self.anim_duck, FALSE, TRUE, TRUE); // this anim is BROKEN anyway
}
}
else
if(g_nexball)
nexball_setstatus();
-
+
+ // secret status
+ secrets_setstatus();
+
self.dmg_team = max(0, self.dmg_team - autocvar_g_teamdamage_resetspeed * frametime);
//self.angles_y=self.v_angle_y + 90; // temp
self.stored_netname = strzone(uid2name(self.crypto_idfp));
if(self.stored_netname != self.netname)
{
- db_put(ServerProgsDB, strcat("uid2name", self.crypto_idfp), self.netname);
+ db_put(ServerProgsDB, strcat("/uid2name/", self.crypto_idfp), self.netname);
strunzone(self.stored_netname);
self.stored_netname = strzone(self.netname);
}