MUTATOR_CALLHOOK(PlayerPhysics_UpdateStats, this);
float maxspd_mod = PHYS_HIGHSPEED(this) * ((this.swampslug.active == ACTIVE_ACTIVE) ? this.swampslug.swamp_slowdown : 1);
- STAT(MOVEVARS_MAXSPEED, this) = Physics_ClientOption(this, "maxspeed", autocvar_sv_maxspeed) * maxspd_mod; // also slow walking
- if (autocvar_g_movement_highspeed_q3_compat) {
- STAT(MOVEVARS_AIRACCEL_QW, this) = Physics_ClientOption(this, "airaccel_qw", autocvar_sv_airaccel_qw);
- STAT(MOVEVARS_AIRSTRAFEACCEL_QW, this) = Physics_ClientOption(this, "airstrafeaccel_qw", autocvar_sv_airstrafeaccel_qw);
- STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, this) = Physics_ClientOption(this, "airspeedlimit_nonqw", autocvar_sv_airspeedlimit_nonqw);
- } else {
- STAT(MOVEVARS_AIRACCEL_QW, this) = AdjustAirAccelQW(Physics_ClientOption(this, "airaccel_qw", autocvar_sv_airaccel_qw), maxspd_mod);
- STAT(MOVEVARS_AIRSTRAFEACCEL_QW, this) = (Physics_ClientOption(this, "airstrafeaccel_qw", autocvar_sv_airstrafeaccel_qw))
- ? AdjustAirAccelQW(Physics_ClientOption(this, "airstrafeaccel_qw", autocvar_sv_airstrafeaccel_qw), maxspd_mod)
- : 0;
- STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, this) = Physics_ClientOption(this, "airspeedlimit_nonqw", autocvar_sv_airspeedlimit_nonqw) * maxspd_mod;
- }
+ STAT(MOVEVARS_MAXSPEED, this) = Physics_ClientOption(this, "maxspeed", autocvar_sv_maxspeed) * maxspd_mod; // also slow walking
+ if (autocvar_g_movement_highspeed_q3_compat)
+ {
+ STAT(MOVEVARS_AIRACCEL_QW, this) = Physics_ClientOption(this, "airaccel_qw", autocvar_sv_airaccel_qw);
+ STAT(MOVEVARS_AIRSTRAFEACCEL_QW, this) = Physics_ClientOption(this, "airstrafeaccel_qw", autocvar_sv_airstrafeaccel_qw);
+ STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, this) = Physics_ClientOption(this, "airspeedlimit_nonqw", autocvar_sv_airspeedlimit_nonqw);
+ }
+ else
+ {
+ STAT(MOVEVARS_AIRACCEL_QW, this) = AdjustAirAccelQW(Physics_ClientOption(this, "airaccel_qw", autocvar_sv_airaccel_qw), maxspd_mod);
+ STAT(MOVEVARS_AIRSTRAFEACCEL_QW, this) = (Physics_ClientOption(this, "airstrafeaccel_qw", autocvar_sv_airstrafeaccel_qw))
+ ? AdjustAirAccelQW(Physics_ClientOption(this, "airstrafeaccel_qw", autocvar_sv_airstrafeaccel_qw), maxspd_mod)
+ : 0;
+ STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, this) = Physics_ClientOption(this, "airspeedlimit_nonqw", autocvar_sv_airspeedlimit_nonqw) * maxspd_mod;
+ }
+
bool q3hb = q3compat && autocvar_sv_q3compat_changehitbox;
STAT(PL_MIN, this) = (q3hb) ? '-15 -15 -20' : autocvar_sv_player_mins;
STAT(PL_MAX, this) = (q3hb) ? '15 15 36' : autocvar_sv_player_maxs;
// fix some new settings
STAT(MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, this) = Physics_ClientOption(this, "airaccel_qw_stretchfactor", autocvar_sv_airaccel_qw_stretchfactor);
STAT(MOVEVARS_MAXAIRSTRAFESPEED, this) = Physics_ClientOption(this, "maxairstrafespeed", autocvar_sv_maxairstrafespeed);
- if (autocvar_g_movement_highspeed_q3_compat) {
- STAT(MOVEVARS_MAXAIRSPEED, this) = Physics_ClientOption(this, "maxairspeed", autocvar_sv_maxairspeed) * maxspd_mod;
- } else {
- STAT(MOVEVARS_MAXAIRSPEED, this) = Physics_ClientOption(this, "maxairspeed", autocvar_sv_maxairspeed);
- }
+ if (autocvar_g_movement_highspeed_q3_compat)
+ STAT(MOVEVARS_MAXAIRSPEED, this) = Physics_ClientOption(this, "maxairspeed", autocvar_sv_maxairspeed) * maxspd_mod;
+ else
+ STAT(MOVEVARS_MAXAIRSPEED, this) = Physics_ClientOption(this, "maxairspeed", autocvar_sv_maxairspeed);
STAT(MOVEVARS_AIRSTRAFEACCELERATE, this) = Physics_ClientOption(this, "airstrafeaccelerate", autocvar_sv_airstrafeaccelerate);
STAT(MOVEVARS_WARSOWBUNNY_TURNACCEL, this) = Physics_ClientOption(this, "warsowbunny_turnaccel", autocvar_sv_warsowbunny_turnaccel);
do_crouch = false;
} else if (STAT(FROZEN, this) || IS_DEAD(this)) {
do_crouch = false;
- }
+ }
- MUTATOR_CALLHOOK(PlayerCanCrouch, this, do_crouch);
- do_crouch = M_ARGV(1, bool);
+ MUTATOR_CALLHOOK(PlayerCanCrouch, this, do_crouch);
+ do_crouch = M_ARGV(1, bool);
if (do_crouch) {
if (!IS_DUCKED(this)) {
// setanim(this, this.anim_duck, false, true, true); // this anim is BROKEN anyway
}
} else if (IS_DUCKED(this)) {
- tracebox(this.origin, STAT(PL_MIN, this), STAT(PL_MAX, this), this.origin, false, this);
- if (!trace_startsolid) {
- UNSET_DUCKED(this);
- this.view_ofs = STAT(PL_VIEW_OFS, this);
- setsize(this, STAT(PL_MIN, this), STAT(PL_MAX, this));
- }
+ tracebox(this.origin, STAT(PL_MIN, this), STAT(PL_MAX, this), this.origin, false, this);
+ if (!trace_startsolid) {
+ UNSET_DUCKED(this);
+ this.view_ofs = STAT(PL_VIEW_OFS, this);
+ setsize(this, STAT(PL_MIN, this), STAT(PL_MAX, this));
+ }
}
_Movetype_CheckWater(this); // needs to be run on the client, might as well use the latest on the server too!
{
#ifdef SVQC
if (!this.wasFlying) return;
- this.wasFlying = false;
- if (this.waterlevel >= WATERLEVEL_SWIMMING) return;
- if (this.ladder_entity) return;
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
- if(this.(weaponentity).hook)
- return;
- }
- this.nextstep = time + 0.3 + random() * 0.1;
- trace_dphitq3surfaceflags = 0;
- tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
- if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS) return;
- entity gs = (trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS)
- ? GS_FALL_METAL
- : GS_FALL;
- float vol = ((IS_DUCKED(this)) ? VOL_MUFFLED : VOL_BASE);
- GlobalSound(this, gs, CH_PLAYER, vol, VOICETYPE_PLAYERSOUND);
+ this.wasFlying = false;
+ if (this.waterlevel >= WATERLEVEL_SWIMMING) return;
+ if (this.ladder_entity) return;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(this.(weaponentity).hook)
+ return;
+ }
+ this.nextstep = time + 0.3 + random() * 0.1;
+ trace_dphitq3surfaceflags = 0;
+ tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
+ if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS) return;
+ entity gs = (trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS)
+ ? GS_FALL_METAL
+ : GS_FALL;
+ float vol = ((IS_DUCKED(this)) ? VOL_MUFFLED : VOL_BASE);
+ GlobalSound(this, gs, CH_PLAYER, vol, VOICETYPE_PLAYERSOUND);
#endif
}
e = new(info_player_deathmatch); // safeguard against player joining
- // assign reflectively to avoid "assignment to world" warning
- for (int i = 0, n = numentityfields(); i < n; ++i) {
- string k = entityfieldname(i);
- if (k == "classname") {
- // safeguard against various stuff ;)
- putentityfieldstring(i, this, "worldspawn");
- break;
- }
- }
+ // assign reflectively to avoid "assignment to world" warning
+ for (int i = 0, n = numentityfields(); i < n; ++i)
+ {
+ string k = entityfieldname(i);
+ if (k == "classname")
+ {
+ // safeguard against various stuff ;)
+ putentityfieldstring(i, this, "worldspawn");
+ break;
+ }
+ }
// needs to be done so early because of the constants they create
static_init();
// find out good world mins/maxs bounds, either the static bounds found by looking for solid, or the mapinfo specified bounds
get_mi_min_max(1);
// assign reflectively to avoid "assignment to world" warning
- int done = 0; for (int i = 0, n = numentityfields(); i < n; ++i) {
- string k = entityfieldname(i); vector v = (k == "mins") ? mi_min : (k == "maxs") ? mi_max : '0 0 0';
- if (v) {
- putentityfieldstring(i, world, sprintf("%v", v));
- if (++done == 2) break;
- }
+ for (int i = 0, done = 0, n = numentityfields(); i < n; ++i)
+ {
+ string k = entityfieldname(i);
+ vector v = (k == "mins") ? mi_min : (k == "maxs") ? mi_max : '0 0 0';
+ if (v)
+ {
+ putentityfieldstring(i, world, sprintf("%v", v));
+ if (++done == 2) break;
+ }
}
// currently, NetRadiant's limit is 131072 qu for each side
// distance from one corner of a 131072qu cube to the opposite corner is approx. 227023 qu
bool MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax, float goodcontents, float badcontents, float badsurfaceflags, int attempts, float maxaboveground, float minviewdistance, bool frompos)
{
- float m = e.dphitcontentsmask;
- e.dphitcontentsmask = goodcontents | badcontents;
-
- vector org = boundmin;
- vector delta = boundmax - boundmin;
-
- vector start, end;
- start = end = org;
- int j; // used after the loop
- for(j = 0; j < attempts; ++j)
- {
- start.x = org.x + random() * delta.x;
- start.y = org.y + random() * delta.y;
- start.z = org.z + random() * delta.z;
-
- // rule 1: start inside world bounds, and outside
- // solid, and don't start from somewhere where you can
- // fall down to evil
- tracebox(start, e.mins, e.maxs, start - '0 0 1' * delta.z, MOVE_NORMAL, e);
- if (trace_fraction >= 1)
- continue;
- if (trace_startsolid)
- continue;
- if (trace_dphitcontents & badcontents)
- continue;
- if (trace_dphitq3surfaceflags & badsurfaceflags)
- continue;
-
- // rule 2: if we are too high, lower the point
- if (trace_fraction * delta.z > maxaboveground)
- start = trace_endpos + '0 0 1' * maxaboveground;
- vector enddown = trace_endpos;
-
- // rule 3: make sure we aren't outside the map. This only works
- // for somewhat well formed maps. A good rule of thumb is that
- // the map should have a convex outside hull.
- // these can be traceLINES as we already verified the starting box
- vector mstart = start + 0.5 * (e.mins + e.maxs);
- traceline(mstart, mstart + '1 0 0' * delta.x, MOVE_NORMAL, e);
- if (trace_fraction >= 1 || trace_dphittexturename == "common/caulk")
- continue;
- traceline(mstart, mstart - '1 0 0' * delta.x, MOVE_NORMAL, e);
- if (trace_fraction >= 1 || trace_dphittexturename == "common/caulk")
- continue;
- traceline(mstart, mstart + '0 1 0' * delta.y, MOVE_NORMAL, e);
- if (trace_fraction >= 1 || trace_dphittexturename == "common/caulk")
- continue;
- traceline(mstart, mstart - '0 1 0' * delta.y, MOVE_NORMAL, e);
- if (trace_fraction >= 1 || trace_dphittexturename == "common/caulk")
- continue;
- traceline(mstart, mstart + '0 0 1' * delta.z, MOVE_NORMAL, e);
- if (trace_fraction >= 1 || trace_dphittexturename == "common/caulk")
- continue;
+ float m = e.dphitcontentsmask;
+ e.dphitcontentsmask = goodcontents | badcontents;
+
+ vector org = boundmin;
+ vector delta = boundmax - boundmin;
+
+ vector start, end;
+ start = end = org;
+ int j; // used after the loop
+ for(j = 0; j < attempts; ++j)
+ {
+ start.x = org.x + random() * delta.x;
+ start.y = org.y + random() * delta.y;
+ start.z = org.z + random() * delta.z;
+
+ // rule 1: start inside world bounds, and outside
+ // solid, and don't start from somewhere where you can
+ // fall down to evil
+ tracebox(start, e.mins, e.maxs, start - '0 0 1' * delta.z, MOVE_NORMAL, e);
+ if (trace_fraction >= 1)
+ continue;
+ if (trace_startsolid)
+ continue;
+ if (trace_dphitcontents & badcontents)
+ continue;
+ if (trace_dphitq3surfaceflags & badsurfaceflags)
+ continue;
+
+ // rule 2: if we are too high, lower the point
+ if (trace_fraction * delta.z > maxaboveground)
+ start = trace_endpos + '0 0 1' * maxaboveground;
+ vector enddown = trace_endpos;
+
+ // rule 3: make sure we aren't outside the map. This only works
+ // for somewhat well formed maps. A good rule of thumb is that
+ // the map should have a convex outside hull.
+ // these can be traceLINES as we already verified the starting box
+ vector mstart = start + 0.5 * (e.mins + e.maxs);
+ traceline(mstart, mstart + '1 0 0' * delta.x, MOVE_NORMAL, e);
+ if (trace_fraction >= 1 || trace_dphittexturename == "common/caulk")
+ continue;
+ traceline(mstart, mstart - '1 0 0' * delta.x, MOVE_NORMAL, e);
+ if (trace_fraction >= 1 || trace_dphittexturename == "common/caulk")
+ continue;
+ traceline(mstart, mstart + '0 1 0' * delta.y, MOVE_NORMAL, e);
+ if (trace_fraction >= 1 || trace_dphittexturename == "common/caulk")
+ continue;
+ traceline(mstart, mstart - '0 1 0' * delta.y, MOVE_NORMAL, e);
+ if (trace_fraction >= 1 || trace_dphittexturename == "common/caulk")
+ continue;
+ traceline(mstart, mstart + '0 0 1' * delta.z, MOVE_NORMAL, e);
+ if (trace_fraction >= 1 || trace_dphittexturename == "common/caulk")
+ continue;
// rule 4: we must "see" some spawnpoint or item
entity sp = NULL;
continue;
}
- // find a random vector to "look at"
- end.x = org.x + random() * delta.x;
- end.y = org.y + random() * delta.y;
- end.z = org.z + random() * delta.z;
- end = start + normalize(end - start) * vlen(delta);
-
- // rule 4: start TO end must not be too short
- tracebox(start, e.mins, e.maxs, end, MOVE_NORMAL, e);
- if(trace_startsolid)
- continue;
- if(trace_fraction < minviewdistance / vlen(delta))
- continue;
-
- // rule 5: don't want to look at sky
- if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
- continue;
-
- // rule 6: we must not end up in trigger_hurt
- if(tracebox_hits_trigger_hurt(start, e.mins, e.maxs, enddown))
- continue;
-
- break;
- }
-
- e.dphitcontentsmask = m;
-
- if(j < attempts)
- {
- setorigin(e, start);
- e.angles = vectoangles(end - start);
- LOG_DEBUG("Needed ", ftos(j + 1), " attempts");
- return true;
- }
- return false;
+ // find a random vector to "look at"
+ end.x = org.x + random() * delta.x;
+ end.y = org.y + random() * delta.y;
+ end.z = org.z + random() * delta.z;
+ end = start + normalize(end - start) * vlen(delta);
+
+ // rule 4: start TO end must not be too short
+ tracebox(start, e.mins, e.maxs, end, MOVE_NORMAL, e);
+ if(trace_startsolid)
+ continue;
+ if(trace_fraction < minviewdistance / vlen(delta))
+ continue;
+
+ // rule 5: don't want to look at sky
+ if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
+ continue;
+
+ // rule 6: we must not end up in trigger_hurt
+ if(tracebox_hits_trigger_hurt(start, e.mins, e.maxs, enddown))
+ continue;
+
+ break;
+ }
+
+ e.dphitcontentsmask = m;
+
+ if(j < attempts)
+ {
+ setorigin(e, start);
+ e.angles = vectoangles(end - start);
+ LOG_DEBUG("Needed ", ftos(j + 1), " attempts");
+ return true;
+ }
+ return false;
}
float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
g_pickup_ammo_anyway = cvar("g_pickup_ammo_anyway");
g_pickup_weapons_anyway = cvar("g_pickup_weapons_anyway");
- g_weapon_stay = cvar(strcat("g_", GetGametype(), "_weapon_stay"));
- if(!g_weapon_stay)
- g_weapon_stay = cvar("g_weapon_stay");
+ g_weapon_stay = cvar(strcat("g_", GetGametype(), "_weapon_stay"));
+ if(!g_weapon_stay)
+ g_weapon_stay = cvar("g_weapon_stay");
- MUTATOR_CALLHOOK(ReadLevelCvars);
+ MUTATOR_CALLHOOK(ReadLevelCvars);
if (!warmup_stage && !autocvar_g_campaign)
game_starttime = time + cvar("g_start_delay");
void InitializeEntity(entity e, void(entity this) func, int order)
{
- entity prev, cur;
-
- if (!e || e.initialize_entity)
- {
- // make a proxy initializer entity
- entity e_old = e;
- e = new(initialize_entity);
- e.enemy = e_old;
- }
-
- e.initialize_entity = func;
- e.initialize_entity_order = order;
-
- cur = initialize_entity_first;
- prev = NULL;
- for (;;)
- {
- if (!cur || cur.initialize_entity_order > order)
- {
- // insert between prev and cur
- if (prev)
- prev.initialize_entity_next = e;
- else
- initialize_entity_first = e;
- e.initialize_entity_next = cur;
- return;
- }
- prev = cur;
- cur = cur.initialize_entity_next;
- }
+ entity prev, cur;
+
+ if (!e || e.initialize_entity)
+ {
+ // make a proxy initializer entity
+ entity e_old = e;
+ e = new(initialize_entity);
+ e.enemy = e_old;
+ }
+
+ e.initialize_entity = func;
+ e.initialize_entity_order = order;
+
+ cur = initialize_entity_first;
+ prev = NULL;
+ for (;;)
+ {
+ if (!cur || cur.initialize_entity_order > order)
+ {
+ // insert between prev and cur
+ if (prev)
+ prev.initialize_entity_next = e;
+ else
+ initialize_entity_first = e;
+ e.initialize_entity_next = cur;
+ return;
+ }
+ prev = cur;
+ cur = cur.initialize_entity_next;
+ }
}
void InitializeEntitiesRun()
{
- entity startoflist = initialize_entity_first;
- initialize_entity_first = NULL;
- delete_fn = remove_except_protected;
- for (entity e = startoflist; e; e = e.initialize_entity_next)
- {
+ entity startoflist = initialize_entity_first;
+ initialize_entity_first = NULL;
+ delete_fn = remove_except_protected;
+ for (entity e = startoflist; e; e = e.initialize_entity_next)
+ {
e.remove_except_protected_forbidden = 1;
- }
- for (entity e = startoflist; e; )
- {
+ }
+ for (entity e = startoflist; e; )
+ {
e.remove_except_protected_forbidden = 0;
- e.initialize_entity_order = 0;
- entity next = e.initialize_entity_next;
- e.initialize_entity_next = NULL;
- var void(entity this) func = e.initialize_entity;
- e.initialize_entity = func_null;
- if (e.classname == "initialize_entity")
- {
- entity wrappee = e.enemy;
- builtin_remove(e);
- e = wrappee;
- }
- //dprint("Delayed initialization: ", e.classname, "\n");
- if (func)
- {
- func(e);
- }
- else
- {
- eprint(e);
- backtrace(strcat("Null function in: ", e.classname, "\n"));
- }
- e = next;
- }
- delete_fn = remove_unsafely;
+ e.initialize_entity_order = 0;
+ entity next = e.initialize_entity_next;
+ e.initialize_entity_next = NULL;
+ var void(entity this) func = e.initialize_entity;
+ e.initialize_entity = func_null;
+ if (e.classname == "initialize_entity")
+ {
+ entity wrappee = e.enemy;
+ builtin_remove(e);
+ e = wrappee;
+ }
+ //dprint("Delayed initialization: ", e.classname, "\n");
+ if (func)
+ {
+ func(e);
+ }
+ else
+ {
+ eprint(e);
+ backtrace(strcat("Null function in: ", e.classname, "\n"));
+ }
+ e = next;
+ }
+ delete_fn = remove_unsafely;
}
// deferred dropping