@@ -324,7 +324,7 @@ namespace physics
return vel;
}

float impulsevelocity(physent *d, float amt, int &cost, int type, float redir, vec &keep)
float impulsevelocity(physent *d, float amt, int type, float redir, vec &keep)
{
float scale = d->speedscale;
if(gameent::is(d))
@@ -336,21 +336,6 @@ namespace physics
if(m_capture(game::gamemode)) scale *= capturecarryspeed;
else if(m_bomber(game::gamemode)) scale *= bombercarryspeed;
}
if(cost && m_impulsemeter(game::gamemode, game::mutators))
{
if(impulsecostscale) cost = int(cost*scale);
int diff = impulsemeter-e->impulse[IM_METER];
if(cost > diff)
{
if(type >= A_A_IMFIRST && impulsecostrelax&(1<<(type-A_A_IMFIRST)))
{
scale *= float(diff)/float(cost);
cost = diff;
}
else return 0.f;
}
}
else cost = 0;
}
float speed = (impulsespeed*amt*scale)+(keep.magnitude()*redir);
keep.mul(1-min(redir, 1.f));
@@ -733,9 +718,8 @@ namespace physics
if(!power) skew = impulsedash;
if(!dash && !melee) d->impulse[IM_JUMP] = lastmillis;
}
int cost = int(impulsecost*(melee ? impulsecostmelee : (dash ? impulsecostdash : impulsecostboost)));
vec keepvel = vec(d->vel).add(d->falling);
float force = impulsevelocity(d, skew, cost, melee ? A_A_PARKOUR : (dash ? A_A_DASH : A_A_BOOST), melee ? impulsemeleeredir : (dash ? impulsedashredir : (moving ? impulseboostredir : impulsejumpredir)), keepvel);
float force = impulsevelocity(d, skew, melee ? A_A_PARKOUR : (dash ? A_A_DASH : A_A_BOOST), melee ? impulsemeleeredir : (dash ? impulsedashredir : (moving ? impulseboostredir : impulsejumpredir)), keepvel);
if(force > 0)
{
vec dir(0, 0, 1);
@@ -751,7 +735,7 @@ namespace physics
}
d->vel = vec(dir).mul(force).add(keepvel);
if(power) d->vel.z += jumpvel(d, true);
d->doimpulse(cost, melee ? IM_T_MELEE : (dash ? IM_T_DASH : IM_T_BOOST), lastmillis);
d->doimpulse(melee ? IM_T_MELEE : (dash ? IM_T_DASH : IM_T_BOOST), lastmillis);
d->action[AC_JUMP] = false;
if(power || pulse) onfloor = false;
client::addmsg(N_SPHY, "ri2", d->clientnum, melee ? SPHY_MELEE : (dash ? SPHY_DASH : SPHY_BOOST));
@@ -776,15 +760,14 @@ namespace physics
{
if(d->action[AC_JUMP] && canimpulse(d, A_A_PARKOUR, true))
{
int cost = int(impulsecost*impulsecostkick);
vec keepvel = vec(d->vel).add(d->falling);
float mag = impulsevelocity(d, impulseparkourkick, cost, A_A_PARKOUR, impulseparkourkickredir, keepvel);
float mag = impulsevelocity(d, impulseparkourkick, A_A_PARKOUR, impulseparkourkickredir, keepvel);
if(mag > 0)
{
vec rft;
vecfromyawpitch(d->yaw, d->actortype >= A_BOT || !kickoffstyle ? kickoffangle : d->pitch, 1, 0, rft);
d->vel = vec(rft).mul(mag).add(keepvel);
d->doimpulse(cost, IM_T_KICK, lastmillis);
d->doimpulse(IM_T_KICK, lastmillis);
d->turnmillis = PHYSMILLIS;
d->turnside = 0; d->turnyaw = d->turnroll = 0;
d->action[AC_JUMP] = onfloor = false;
@@ -891,16 +874,15 @@ namespace physics
}
if(!d->turnside && (parkour || vault) && iskick)
{
int cost = int(impulsecost*(vault ? impulsecostvault : impulsecostclimb));
vec keepvel = vec(d->vel).add(d->falling);
float mag = impulsevelocity(d, vault ? impulseparkourvault : impulseparkourclimb, cost, A_A_PARKOUR, vault ? impulseparkourvaultredir : impulseparkourclimbredir, keepvel);
float mag = impulsevelocity(d, vault ? impulseparkourvault : impulseparkourclimb, A_A_PARKOUR, vault ? impulseparkourvaultredir : impulseparkourclimbredir, keepvel);
if(mag > 0)
{
vec rft;
vecfromyawpitch(d->yaw, vault || d->actortype >= A_BOT || !kickupstyle ? kickupangle : fabs(d->pitch), 1, 0, rft);
rft.reflect(face);
d->vel = vec(rft).mul(mag).add(keepvel);
d->doimpulse(cost, vault ? IM_T_VAULT : IM_T_KICK, lastmillis);
d->doimpulse(vault ? IM_T_VAULT : IM_T_KICK, lastmillis);
d->turnmillis = PHYSMILLIS;
d->turnside = 0;
d->turnyaw = d->turnroll = 0;
@@ -921,16 +903,15 @@ namespace physics
vecfromyawpitch(yaw, 0.f, 1, 0, rft);
if(!d->turnside)
{
int cost = int(impulsecost*impulsecostparkour);
vec keepvel = vec(d->vel).add(d->falling);
float mag = impulsevelocity(d, impulseparkour, cost, A_A_PARKOUR, impulseparkourredir, keepvel);
float mag = impulsevelocity(d, impulseparkour, A_A_PARKOUR, impulseparkourredir, keepvel);
if(mag > 0)
{
d->vel = vec(rft).mul(mag).add(keepvel);
off = yaw-d->yaw;
if(off > 180) off -= 360;
else if(off < -180) off += 360;
d->doimpulse(cost, IM_T_SKATE, lastmillis);
d->doimpulse(IM_T_SKATE, lastmillis);
d->turnmillis = PHYSMILLIS;
d->turnside = side;
d->turnyaw = off;
@@ -1831,8 +1831,7 @@ namespace projs
{
gameent *e = (gameent *)proj.owner;
vec keepvel = vec(e->vel).add(e->falling);
int cost = int(impulsecost*(d ? impulsecostgrabplayer : impulsecostgrab));
float mag = physics::impulsevelocity(e, d ? impulseparkourgrabplayer : impulseparkourgrab, cost, A_A_PARKOUR, d ? impulseparkourgrabplayerredir : impulseparkourgrabredir, keepvel);
float mag = physics::impulsevelocity(e, d ? impulseparkourgrabplayer : impulseparkourgrab, A_A_PARKOUR, d ? impulseparkourgrabplayerredir : impulseparkourgrabredir, keepvel);
if(mag > 0)
{
float yaw = e->yaw, pitch = 89.9f;
@@ -1851,7 +1850,7 @@ namespace projs
default: break;
}
e->vel = vec(yaw*RAD, pitch*RAD).mul(mag).add(keepvel);
e->doimpulse(cost, IM_T_GRAB, lastmillis);
e->doimpulse(IM_T_GRAB, lastmillis);
client::addmsg(N_SPHY, "ri2", e->clientnum, SPHY_GRAB);
game::impulseeffect(e);
game::footstep(e);
@@ -2212,7 +2212,7 @@ namespace server
if(ci->actortype >= A_ENEMY) return ci->spawnpoint;
else
{
if(m_race(gamemode) && !ci->cpnodes.empty() && (!m_ra_gauntlet(gamemode, mutators) || ci->team == T_ALPHA))
if(m_race(gamemode) && !ci->cpnodes.empty() && !m_ra_endurance(gamemode, mutators) && (!m_ra_gauntlet(gamemode, mutators) || ci->team == T_ALPHA))
{
int checkpoint = ci->cpnodes.last();
if(sents.inrange(checkpoint)) return checkpoint;
@@ -3401,7 +3401,7 @@ namespace server
}
}
}
requestmasterf("stats game %s %d %d %d %d %d\n", escapestring(smapname), gamemode, mutators, gamemillis/1000, unique, m_normalweapons(gamemode, mutators) ? 1 : 0);
requestmasterf("stats game %s %d %d %d %d %d\n", escapestring(smapname), gamemode, mutators, gamemillis/1000, unique, m_normweaps(gamemode, mutators) ? 1 : 0);
flushmasteroutput();
requestmasterf("stats server %s %s %d\n", escapestring(limitstring(G(serverdesc), MAXSDESCLEN+1)), versionstring, serverport);
flushmasteroutput();
@@ -5083,7 +5083,7 @@ namespace server

void checkclients()
{
bool avgposcalc = (m_normalweapons(gamemode, mutators) && gamemillis-lastavgposcalc >= G(teambalanceavgposdelay));
bool avgposcalc = (m_normweaps(gamemode, mutators) && gamemillis-lastavgposcalc >= G(teambalanceavgposdelay));
int maxpoints = 0;
if(avgposcalc)
{
@@ -6056,7 +6056,6 @@ namespace server
clientinfo *cp = (clientinfo *)getinfo(lcn);
if(!hasclient(cp, ci)) havecn = false;
getuint(p);
getuint(p);
uint flags = getuint(p);
vec pos, floorpos, vel, falling;
float yaw, pitch, roll;
@@ -491,7 +491,7 @@ GFVAR(IDF_GAMEMOD, impulseparkourgrabplayer, 0, 1.1f, FVAR_MAX); // parkour grab
GFVAR(IDF_GAMEMOD, impulseparkourgrabplayerredir, 0, 1, FVAR_MAX); // how much of the old velocity is redirected into the new one
GFVAR(IDF_GAMEMOD, impulseparkournorm, 0, 0.5f, FVAR_MAX); // minimum parkour surface z normal
GVAR(IDF_GAMEMOD, impulsestyle, 0, 1, 3); // impulse style; 0 = off, 1 = touch and count, 2 = count only, 3 = freestyle
GVAR(IDF_GAMEMOD, impulsecount, 0, 6, VAR_MAX); // number of impulse actions per air transit
GVAR(IDF_GAMEMOD, impulsecount, 0, 5, VAR_MAX); // number of impulse actions per air transit
GVAR(IDF_GAMEMOD, impulseslip, 0, 500, VAR_MAX); // time before floor friction kicks back in
GVAR(IDF_GAMEMOD, impulseslide, 0, 1000, VAR_MAX); // time before powerslides end
GVAR(IDF_GAMEMOD, impulsejumpdelay, 0, 100, VAR_MAX); // minimum time after jump for boost
@@ -500,29 +500,7 @@ GVAR(IDF_GAMEMOD, impulsedashdelay, 0, 500, VAR_MAX); // minimum time between da
GVAR(IDF_GAMEMOD, impulsekickdelay, 0, 350, VAR_MAX); // minimum time between wall kicks/climbs/grabs
GFVAR(IDF_GAMEMOD, impulsevaultmin, FVAR_NONZERO, 0.25f, FVAR_MAX); // minimum percentage of height for vault
GFVAR(IDF_GAMEMOD, impulsevaultmax, FVAR_NONZERO, 1.6f, FVAR_MAX); // maximum percentage of height for vault

GVAR(IDF_GAMEMOD, impulsemeter, 1, 30000, VAR_MAX); // impulse dash length; timer
GVAR(IDF_GAMEMOD, impulsecost, 1, 5000, VAR_MAX); // cost of impulse move
GFVAR(IDF_GAMEMOD, impulsecostparkour, 0, 1, FVAR_MAX); // scale cost boost move
GFVAR(IDF_GAMEMOD, impulsecostboost, 0, 1, FVAR_MAX); // scale cost boost move
GFVAR(IDF_GAMEMOD, impulsecostdash, 0, 1, FVAR_MAX); // scale cost dash move
GFVAR(IDF_GAMEMOD, impulsecostkick, 0, 1, FVAR_MAX); // scale cost vault move
GFVAR(IDF_GAMEMOD, impulsecostmelee, 0, 1, FVAR_MAX); // scale cost melee move
GFVAR(IDF_GAMEMOD, impulsecostclimb, 0, 1, FVAR_MAX); // scale cost climb move
GFVAR(IDF_GAMEMOD, impulsecostvault, 0, 1, FVAR_MAX); // scale cost vault move
GFVAR(IDF_GAMEMOD, impulsecostgrab, 0, 0.5f, FVAR_MAX); // scale cost of grab move
GFVAR(IDF_GAMEMOD, impulsecostgrabplayer, 0, 0.25f, FVAR_MAX); // scale cost of grab move
GVAR(IDF_GAMEMOD, impulsecostrelax, 0, A_A_IMRELAX, A_A_IMOFFSET); // whether the cost of an impulse move is unimportant
GVAR(IDF_GAMEMOD, impulsecostscale, 0, 0, 1); // whether the cost scales depend on the amount the impulse scales

GVAR(IDF_GAMEMOD, impulseskate, 0, 1000, VAR_MAX); // length of time a run along a wall can last
GFVAR(IDF_GAMEMOD, impulseregen, 0, 5, FVAR_MAX); // impulse regen multiplier
GFVAR(IDF_GAMEMOD, impulseregencrouch, 0, 2.5f, FVAR_MAX); // impulse regen crouch modifier
GFVAR(IDF_GAMEMOD, impulseregenrun, 0, 0.75f, FVAR_MAX); // impulse regen running modifier
GFVAR(IDF_GAMEMOD, impulseregenmove, 0, 1, FVAR_MAX); // impulse regen moving modifier
GFVAR(IDF_GAMEMOD, impulseregeninair, 0, 0.75f, FVAR_MAX); // impulse regen in-air modifier
GFVAR(IDF_GAMEMOD, impulseregenslide, 0, 0, FVAR_MAX); // impulse regen sliding modifier
GVAR(IDF_GAMEMOD, impulseregendelay, 0, 350, VAR_MAX); // delay before impulse regens

GFVAR(IDF_GAMEMOD, spreadcrouch, 0, 0.25f, FVAR_MAX);
GFVAR(IDF_GAMEMOD, spreadzoom, 0, 0.125f, FVAR_MAX);
@@ -136,7 +136,7 @@ WPSVARM(IDF_GAMEMOD, desc,
"is a fast, highly explosive rocket with a large shockwave, causes burn residual damage",
"allows you to use parkour and kick moves as melee attacks",
// begin secondary
"is a slower and weaker claw attack that pulls you towards the enemy or performs low impulse cost wall grabs",
"is a slower and weaker claw attack that pulls you towards the enemy and allows wall grabs",
"is a slower rate of fire than the primary attack, but does more damage",
"is a slower vertical slice with much more power, causes bleed residual damage",
"shoots a slug that explodes and disintegrates into shavings, causes bleed residual damage",