set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
+set g_balance_contents_playerdamage_lava_burn 0 // extra burning damage after leaving lava
+set g_balance_contents_playerdamage_lava_burn_time 2.5 // time across which the damage is applied (note: not dps!)
set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
+set g_balance_contents_playerdamage_lava_burn 0 // extra burning damage after leaving lava
+set g_balance_contents_playerdamage_lava_burn_time 2.5 // time across which the damage is applied (note: not dps!)
set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
+set g_balance_contents_playerdamage_lava_burn 0 // extra burning damage after leaving lava
+set g_balance_contents_playerdamage_lava_burn_time 2.5 // time across which the damage is applied (note: not dps!)
set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
+set g_balance_contents_playerdamage_lava_burn 0 // extra burning damage after leaving lava
+set g_balance_contents_playerdamage_lava_burn_time 2.5 // time across which the damage is applied (note: not dps!)
set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
+set g_balance_contents_playerdamage_lava_burn 0 // extra burning damage after leaving lava
+set g_balance_contents_playerdamage_lava_burn_time 2.5 // time across which the damage is applied (note: not dps!)
set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
+set g_balance_contents_playerdamage_lava_burn 0 // extra burning damage after leaving lava
+set g_balance_contents_playerdamage_lava_burn_time 2.5 // time across which the damage is applied (note: not dps!)
set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
case NUM_TEAM_2: tex = "particles/hook_blue"; rgb = '0.3 0.3 1'; break;
case NUM_TEAM_3: tex = "particles/hook_yellow"; rgb = '1 1 0.3'; break;
case NUM_TEAM_4: tex = "particles/hook_pink"; rgb = '1 0.3 1'; break;
- default: tex = "particles/hook_white"; rgb = getcsqcplayercolor(self.sv_entnum); break;
+ default: tex = "particles/hook_white"; rgb = getcsqcplayercolor(self.sv_entnum - 1); break;
}
break;
case NET_ENT_CLIENT_ARC_BEAM: // todo
float stringwidth_colors(string s, vector theSize);
float stringwidth_nocolors(string s, vector theSize);
-float GetPlayerColorForce(int i);
-int GetPlayerColor(int i);
-string GetPlayerName(int i);
void HUD_Panel_DrawProgressBar(vector theOrigin, vector theSize, string pic, float length_ratio, bool vertical, float baralign, vector theColor, float theAlpha, int drawflag);
.int panel_showflags;
}
}
-// TODO: entcs
-float getplayeralpha(int pl)
-{
- entity e = CSQCModel_server2csqc(pl + 1);
- return (e) ? e.alpha : 1;
-}
-
-// TODO: entcs
-vector getcsqcplayercolor(int pl)
-{
- entity e = CSQCModel_server2csqc(pl);
- return (e && e.colormap > 0) ? colormapPaletteColor(((e.colormap >= 1024) ? e.colormap : stof(getplayerkeyvalue(e.colormap - 1, "colors"))) & 0x0F, true) : '1 1 1';
-}
-
-// TODO: entcs
-bool getplayerisdead(int pl)
-{
- entity e = CSQCModel_server2csqc(pl + 1);
- return e ? e.csqcmodel_isdead : false;
-}
-
/** engine callback */
void URI_Get_Callback(int id, float status, string data)
{
vector rotate(vector v, float a);
-string ColorTranslateRGB(string s);
-
// decolorizes and team colors the player name when needed
string playername(string thename, float teamid);
void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector rgb, float a, float drawflag);
-float getplayeralpha(float pl);
-
-vector getcsqcplayercolor(float pl);
-
-float getplayerisdead(float pl);
-
const int MAX_ACCURACY_LEVELS = 10;
float acc_lev[MAX_ACCURACY_LEVELS];
vector acc_col[MAX_ACCURACY_LEVELS];
string checkmodel_input, checkmodel_command;
MUTATOR_HOOKABLE(GetModelParams, EV_GetModelParams);
-/** called when a player presses the jump key */
-#define EV_PlayerJump(i, o) \
- /**/ i(float, player_multijump) \
- /**/ i(float, player_jumpheight) \
- /**/ o(float, player_multijump) \
- /**/ o(float, player_jumpheight) \
- /**/
-float player_multijump;
-float player_jumpheight;
-MUTATOR_HOOKABLE(PlayerJump, EV_PlayerJump);
-
/** Called checking if 3rd person mode should be forced on */
#define EV_WantEventchase(i, o) \
/** entity id */ i(entity, __self) \
#define HUD_DefaultColumnLayout() \
"ping pl name | " \
-"-teams,rc,lms/kills +ft,tdm/kills -teams,lms/deaths +ft,tdm/deaths -teams,lms,rc,ka/suicides +ft,tdm/suicides -rc,dm,tdm,ka,ft/frags " /* tdm already has this in "score" */ \
-"dmg dmgtaken " \
+"-teams,cts,lms/kills +ft,tdm/kills -teams,lms/deaths +ft,tdm/deaths -teams,lms,rc,ka/suicides +ft,tdm/suicides -cts,dm,tdm,ka,ft/frags " /* tdm already has this in "score" */ \
+"-rc,cts,nb/dmg -rc,cts,nb/dmgtaken " \
"+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns +ons/caps +ons/takes " \
"+lms/lives +lms/rank " \
"+kh/caps +kh/pushes +kh/destroyed " \
// self.pointtime = last time you pointed at this player
// self.csqcmodel_isdead = value of csqcmodel_isdead to know when the player is dead or not
+LinkedList shownames_ent;
+STATIC_INIT(shownames_ent)
+{
+ shownames_ent = LL_NEW();
+ for (int i = 0; i < maxclients; ++i)
+ {
+ entity e = new(shownames_tag);
+ e.sv_entnum = i + 1;
+ LL_PUSH(shownames_ent, e);
+ }
+}
+
const float SHOWNAMES_FADESPEED = 4;
const float SHOWNAMES_FADEDELAY = 0.4;
void Draw_ShowNames(entity this)
if (autocvar_hud_shownames_antioverlap)
{
// fade tag out if another tag that is closer to you overlaps
- for (entity e = world; (e = find(e, classname, "shownames_tag")); )
- {
- if (e == this) continue;
- vector eo = project_3d_to_2d(e.origin);
+ LL_EACH(shownames_ent, it != this && entcs_receiver(i), LAMBDA(
+ vector eo = project_3d_to_2d(it.origin);
if (eo.z < 0 || eo.x < 0 || eo.y < 0 || eo.x > vid_conwidth || eo.y > vid_conheight) continue;
eo.z = 0;
if (vlen((eX * o.x + eY * o.y) - eo) < autocvar_hud_shownames_antioverlap_distance
- && dist > vlen(e.origin - view_origin))
+ && dist > vlen(it.origin - view_origin))
{
overlap = true;
break;
}
- }
+ ));
}
bool onscreen = (o.z >= 0 && o.x >= 0 && o.y >= 0 && o.x <= vid_conwidth && o.y <= vid_conheight);
float crosshairdistance = sqrt(pow(o.x - vid_conwidth / 2, 2) + pow(o.y - vid_conheight / 2, 2));
}
}
-LinkedList shownames_ent;
-STATIC_INIT(shownames_ent)
-{
- shownames_ent = LL_NEW();
- for (int i = 0; i < maxclients; ++i)
- {
- entity e = new(shownames_tag);
- e.sv_entnum = i + 1;
- LL_PUSH(shownames_ent, e);
- }
-}
-
void Draw_ShowNames_All()
{
if (!autocvar_hud_shownames) return;
{
// self.move_flags &= ~FL_ONGROUND;
if (self.move_movetype == MOVETYPE_NONE || self.move_movetype == MOVETYPE_FLY)
- Movetype_Physics_NoMatchServer();
+ Movetype_Physics_NoMatchServer(self);
// the trivial movetypes do not have to match the
// server's ticrate as they are ticrate independent
// NOTE: this assumption is only true if MOVETYPE_FLY
// projectiles detonate on impact. If they continue
// moving, we might still be ticrate dependent.
else
- Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
+ Movetype_Physics_MatchServer(self, autocvar_cl_projectiles_sloppy);
if (!(self.move_flags & FL_ONGROUND))
if (self.velocity != '0 0 0')
self.move_angles = self.angles = vectoangles(self.velocity);
CSQCMODEL_PROPERTY(BIT(11), int, ReadByte, WriteByte, traileffect) \
CSQCMODEL_PROPERTY_SCALED(BIT(12), float, ReadByte, WriteByte, scale, 16, 0, 255) \
CSQCMODEL_PROPERTY(BIT(13), int, ReadInt24_t, WriteInt24_t, dphitcontentsmask) \
- CSQCMODEL_PROPERTY(BIT(14), TAG_VIEWLOC_TYPE, ReadShort, WriteEntity, TAG_VIEWLOC_NAME)
+ CSQCMODEL_PROPERTY(BIT(14), TAG_VIEWLOC_TYPE, ReadShort, WriteEntity, TAG_VIEWLOC_NAME) \
+ CSQCMODEL_PROPERTY(BIT(15), int, ReadByte, WriteByte, multijump_count)
// TODO get rid of colormod/glowmod here, find good solution for vortex charge glowmod hack; also get rid of some useless properties on non-players that only exist for CopyBody
// add hook function calls here
self.flags &= ~FL_ONGROUND;
}
- Movetype_Physics_MatchTicrate(autocvar_cl_casings_ticrate, autocvar_cl_casings_sloppy);
+ Movetype_Physics_MatchTicrate(self, autocvar_cl_casings_ticrate, autocvar_cl_casings_sloppy);
if (wasfreed(self))
return; // deleted by touch function
vector oldorg;
oldorg = self.origin;
- Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
+ Movetype_Physics_MatchTicrate(self, autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
if(wasfreed(self))
return;
bool entcs_send(entity this, entity to, int sf)
{
entity player = this.owner;
- sf |= 1;
+ sf |= BIT(0) | BIT(1);
if (IS_PLAYER(to) || to.caplayer) // unless spectating,
{
bool same_team = (to == player) || (teamplay && player.team == to.team);
{
SELFPARAM();
this.nextthink = time;
- entity e = CSQCModel_server2csqc(this.sv_entnum + 1);
+ entity e = CSQCModel_server2csqc(this.sv_entnum);
bool exists = e != NULL;
if (exists)
{
InterpolateOrigin_Undo(this);
int sf = ReadShort();
this.has_sv_origin = false;
- this.m_entcs_private = boolean(sf & 1);
+ this.m_entcs_private = boolean(sf & BIT(0));
int i = 1;
#define X(public, fld, sv, cl) { if (sf & BIT(i)) cl; } i += 1;
ENTCS_NETPROPS(X);
.bool has_sv_origin;
#ifdef SVQC
-/**
+/*
* The point of these entities is to avoid the problems
* with clientprediction.
* If you add SendEntity to players, the engine will not
* in onslaught... YAY ;)
*/
-.entity entcs;
+ .entity entcs;
-bool entcs_send(entity this, entity to, int sf);
+ bool entcs_send(entity this, entity to, int sf);
-void entcs_think();
+ void entcs_think();
-void entcs_attach(entity e);
+ void entcs_attach(entity e);
-void entcs_detach(entity e);
+ void entcs_detach(entity e);
-.int m_forceupdate;
+ .int m_forceupdate;
/** Force an origin update, for player sounds */
-#define entcs_force_origin(e) ((e).entcs.m_forceupdate = BIT(2))
+ #define entcs_force_origin(e) ((e).entcs.m_forceupdate = BIT(2))
#endif
#ifdef CSQC
-AL_declare(_entcs);
-STATIC_INIT(_entcs)
-{
- AL_init(_entcs, 255, NULL, e); // 255 is the engine limit on maxclients
-}
-#define entcs_receiver(...) EVAL(OVERLOAD(entcs_receiver, __VA_ARGS__))
-#define entcs_receiver_1(i) AL_gete(_entcs, i)
-#define entcs_receiver_2(i, v) AL_sete(_entcs, i, v)
-#define entcs_is_self(e) ((e).sv_entnum + 1 == player_localentnum)
+ AL_declare(_entcs);
+ STATIC_INIT(_entcs)
+ {
+ AL_init(_entcs, 255, NULL, e); // 255 is the engine limit on maxclients
+ }
+ SHUTDOWN(_entcs)
+ {
+ AL_delete(_entcs);
+ }
+ #define entcs_receiver(...) EVAL(OVERLOAD(entcs_receiver, __VA_ARGS__))
+ #define entcs_receiver_1(i) AL_gete(_entcs, i)
+ #define entcs_receiver_2(i, v) AL_sete(_entcs, i, v)
+ #define entcs_is_self(e) ((e).sv_entnum == player_localentnum - 1)
+
+ /**
+ * @param i zero indexed player
+ * @returns 0 if not teamplay
+ */
+ int GetPlayerColorForce(int i)
+ {
+ return (!teamplay) ? 0 : stof(getplayerkeyvalue(i, "colors")) & 15;
+ }
+
+ /**
+ * @param i zero indexed player
+ * @returns 0 if not teamplay | NUM_TEAM_##N | NUM_SPECTATOR
+ */
+ int GetPlayerColor(int i)
+ {
+ bool unconnected = !playerslots[i].gotscores;
+ bool spec = unconnected || stof(getplayerkeyvalue(i, "frags")) == FRAGS_SPECTATOR;
+ return (spec) ? NUM_SPECTATOR : GetPlayerColorForce(i);
+ }
+
+ /**
+ * @param i zero indexed player
+ */
+ string GetPlayerName(int i)
+ {
+ return ColorTranslateRGB(getplayerkeyvalue(i, "name"));
+ }
+
+ /**
+ * @param i zero indexed player
+ */
+ entity CSQCModel_server2csqc(int i);
+
+ .float alpha;
+
+ /**
+ * @param i zero indexed player
+ */
+ float getplayeralpha(int i)
+ {
+ entity e = CSQCModel_server2csqc(i);
+ return e ? e.alpha : 1;
+ }
+
+ /**
+ * @param i zero indexed player
+ */
+ vector getcsqcplayercolor(int i)
+ {
+ entity e = CSQCModel_server2csqc(i);
+ return (!e || e.colormap <= 0)
+ ? '1 1 1'
+ : colormapPaletteColor(((e.colormap >= 1024)
+ ? e.colormap
+ : stof(getplayerkeyvalue(e.colormap - 1, "colors"))) & 15, true)
+ ;
+ }
+
+ /**
+ * @param i zero indexed player
+ */
+ bool getplayerisdead(int i)
+ {
+ entity e = CSQCModel_server2csqc(i);
+ return e ? e.csqcmodel_isdead : false;
+ }
#endif
#ifdef SVQC
+.float spider_slowness; // effect time of slowness inflicted by spiders
+
.float spider_web_delay;
float autocvar_g_monster_spider_attack_web_damagetime;
void M_Spider_Attack_Web();
+REGISTER_MUTATOR(spiderweb, true);
+
+MUTATOR_HOOKFUNCTION(spiderweb, PlayerPhysics)
+{
+ if (time >= self.spider_slowness)
+ return false;
+ PHYS_MAXSPEED(self) *= 0.5; // half speed while slow from spider
+ PHYS_MAXAIRSPEED(self) *= 0.5;
+ PHYS_AIRSPEEDLIMIT_NONQW(self) *= 0.5;
+ PHYS_AIRSTRAFEACCELERATE(self) *= 0.5;
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(spiderweb, MonsterMove)
+{
+ if(time < self.spider_slowness)
+ {
+ monster_speed_run *= 0.5;
+ monster_speed_walk *= 0.5;
+ }
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(spiderweb, PlayerSpawn)
+{
+ self.spider_slowness = 0;
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(spiderweb, MonsterSpawn)
+{
+ self.spider_slowness = 0;
+ return false;
+}
+
SOUND(SpiderAttack_FIRE, W_Sound("electro_fire"));
METHOD(SpiderAttack, wr_think, void(SpiderAttack thiswep, entity actor, .entity weaponentity, int fire)) {
bool isPlayer = IS_PLAYER(actor);
runspeed = bound(0, monster_speed_run * MONSTER_SKILLMOD(self), runspeed * 2.5); // limit maxspeed to prevent craziness
walkspeed = bound(0, monster_speed_walk * MONSTER_SKILLMOD(self), walkspeed * 2.5); // limit maxspeed to prevent craziness
- if(time < self.spider_slowness)
- {
- runspeed *= 0.5;
- walkspeed *= 0.5;
- }
-
if(teamplay)
if(autocvar_g_monsters_teams)
if(DIFF_TEAM(self.monster_follow, self))
self.deadflag = DEAD_NO;
self.noalign = ((mon.spawnflags & MONSTER_TYPE_FLY) || (mon.spawnflags & MONSTER_TYPE_SWIM));
self.spawn_time = time;
- self.spider_slowness = 0;
self.gravity = 1;
self.monster_moveto = '0 0 0';
self.monster_face = '0 0 0';
// other properties
.bool monster_attack; // indicates whether an entity can be attacked by monsters
-.float spider_slowness; // effect time of slowness inflicted by spiders
// monster state declarations
const int MONSTER_MOVE_FOLLOW = 1; // monster will follow if in range, or stand still
-void _Movetype_Physics_Follow() // SV_Physics_Follow
-{SELFPARAM();
- entity e = self.move_aiment; // TODO: networking?
+void _Movetype_Physics_Follow(entity this) // SV_Physics_Follow
+{
+ entity e = this.move_aiment; // TODO: networking?
// LordHavoc: implemented rotation on MOVETYPE_FOLLOW objects
- if(self.move_angles == self.move_punchangle)
+ if(this.move_angles == this.move_punchangle)
{
- self.move_origin = e.move_origin + self.view_ofs;
+ this.move_origin = e.move_origin + this.view_ofs;
}
else
{
vector ang, v;
- ang_x = -self.move_punchangle_x;
- ang_y = self.move_punchangle_y;
- ang_z = self.move_punchangle_z;
+ ang_x = -this.move_punchangle_x;
+ ang_y = this.move_punchangle_y;
+ ang_z = this.move_punchangle_z;
makevectors(ang);
- v_x = self.view_ofs_x * v_forward_x + self.view_ofs_y * v_right_x + self.view_ofs_z * v_up_x;
- v_y = self.view_ofs_x * v_forward_y + self.view_ofs_y * v_right_y + self.view_ofs_z * v_up_y;
- v_z = self.view_ofs_x * v_forward_z + self.view_ofs_y * v_right_z + self.view_ofs_z * v_up_z;
+ v_x = this.view_ofs_x * v_forward_x + this.view_ofs_y * v_right_x + this.view_ofs_z * v_up_x;
+ v_y = this.view_ofs_x * v_forward_y + this.view_ofs_y * v_right_y + this.view_ofs_z * v_up_y;
+ v_z = this.view_ofs_x * v_forward_z + this.view_ofs_y * v_right_z + this.view_ofs_z * v_up_z;
ang_x = -e.move_angles_x;
ang_y = e.move_angles_y;
ang_z = e.move_angles_z;
makevectors(ang);
- self.move_origin_x = v_x * v_forward_x + v_y * v_forward_y + v_z * v_forward_z + e.move_origin_x;
- self.move_origin_x = v_x * v_right_x + v_y * v_right_y + v_z * v_right_z + e.move_origin_y;
- self.move_origin_x = v_x * v_up_x + v_y * v_up_y + v_z * v_up_z + e.move_origin_z;
+ this.move_origin_x = v_x * v_forward_x + v_y * v_forward_y + v_z * v_forward_z + e.move_origin_x;
+ this.move_origin_x = v_x * v_right_x + v_y * v_right_y + v_z * v_right_z + e.move_origin_y;
+ this.move_origin_x = v_x * v_up_x + v_y * v_up_y + v_z * v_up_z + e.move_origin_z;
}
- self.move_angles = e.move_angles + self.v_angle;
- _Movetype_LinkEdict(false);
+ this.move_angles = e.move_angles + this.v_angle;
+ _Movetype_LinkEdict(this, false);
}
#include "../../server/autocvars.qh"
#endif
-void _Movetype_WallFriction(vector stepnormal) // SV_WallFriction
+void _Movetype_WallFriction(entity this, vector stepnormal) // SV_WallFriction
{
/*float d, i;
vector into, side;
- makevectors(self.v_angle);
+ makevectors(this.v_angle);
d = (stepnormal * v_forward) + 0.5;
if(d < 0)
{
- i = (stepnormal * self.move_velocity);
+ i = (stepnormal * this.move_velocity);
into = i * stepnormal;
- side = self.move_velocity - into;
- self.move_velocity_x = side.x * (1 * d);
- self.move_velocity_y = side.y * (1 * d);
+ side = this.move_velocity - into;
+ this.move_velocity_x = side.x * (1 * d);
+ this.move_velocity_y = side.y * (1 * d);
}*/
}
vector planes[MAX_CLIP_PLANES];
-int _Movetype_FlyMove(float dt, bool applygravity, vector stepnormal, float stepheight) // SV_FlyMove
-{SELFPARAM();
+int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnormal, float stepheight) // SV_FlyMove
+{
int blocked = 0, bumpcount;
int i, j, numplanes = 0;
float time_left = dt, grav = 0;
if(applygravity)
{
- self.move_didgravity = 1;
- grav = dt * (PHYS_ENTGRAVITY(self) ? PHYS_ENTGRAVITY(self) : 1) * PHYS_GRAVITY(this);
+ this.move_didgravity = 1;
+ grav = dt * (PHYS_ENTGRAVITY(this) ? PHYS_ENTGRAVITY(this) : 1) * PHYS_GRAVITY(this);
- if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !(self.move_flags & FL_ONGROUND))
+ if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !(this.move_flags & FL_ONGROUND))
{
if(GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
- self.move_velocity_z -= grav * 0.5;
+ this.move_velocity_z -= grav * 0.5;
else
- self.move_velocity_z -= grav;
+ this.move_velocity_z -= grav;
}
}
- original_velocity = primal_velocity = restore_velocity = self.move_velocity;
+ original_velocity = primal_velocity = restore_velocity = this.move_velocity;
for(bumpcount = 0;bumpcount < MAX_CLIP_PLANES;bumpcount++)
{
- if(self.move_velocity == '0 0 0')
+ if(this.move_velocity == '0 0 0')
break;
- push = self.move_velocity * time_left;
- vector prev_origin = self.move_origin;
- _Movetype_PushEntity(push, true);
- if(trace_startsolid && self.move_origin != prev_origin)
+ push = this.move_velocity * time_left;
+ vector prev_origin = this.move_origin;
+ _Movetype_PushEntity(this, push, true);
+ if(trace_startsolid && this.move_origin != prev_origin)
{
// we got teleported by a touch function
// let's abort the move
// abort move if we're stuck in the world (and didn't make it out)
if(trace_startsolid && trace_allsolid)
{
- self.move_velocity = restore_velocity;
+ this.move_velocity = restore_velocity;
return 3;
}
trace_ent = world;
}
- self.move_flags |= FL_ONGROUND;
- self.move_groundentity = trace_ent;
+ this.move_flags |= FL_ONGROUND;
+ this.move_groundentity = trace_ent;
}
}
else if(stepheight)
{
// step - handle it immediately
- vector org = self.move_origin;
+ vector org = this.move_origin;
vector steppush = '0 0 1' * stepheight;
- _Movetype_PushEntity(steppush, true);
- if(trace_startsolid && self.move_origin != org)
+ _Movetype_PushEntity(this, steppush, true);
+ if(trace_startsolid && this.move_origin != org)
{
blocked |= 8;
break;
}
- _Movetype_PushEntity(push, true);
- if(trace_startsolid && self.move_origin != org)
+ _Movetype_PushEntity(this, push, true);
+ if(trace_startsolid && this.move_origin != org)
{
blocked |= 8;
break;
}
float trace2_fraction = trace_fraction;
- steppush = '0 0 1' * (org_z - self.move_origin_z);
- _Movetype_PushEntity(steppush, true);
- if(trace_startsolid && self.move_origin != org)
+ steppush = '0 0 1' * (org_z - this.move_origin_z);
+ _Movetype_PushEntity(this, steppush, true);
+ if(trace_startsolid && this.move_origin != org)
{
blocked |= 8;
break;
}
// accept the new position if it made some progress...
- if(fabs(self.move_origin_x - org_x) >= 0.03125 || fabs(self.move_origin_y - org_y) >= 0.03125)
+ if(fabs(this.move_origin_x - org_x) >= 0.03125 || fabs(this.move_origin_y - org_y) >= 0.03125)
{
- trace_endpos = self.move_origin;
+ trace_endpos = this.move_origin;
time_left *= 1 - trace2_fraction;
numplanes = 0;
continue;
}
else
- self.move_origin = org;
+ this.move_origin = org;
}
else
{
if(my_trace_fraction >= 0.001)
{
// actually covered some distance
- original_velocity = self.move_velocity;
+ original_velocity = this.move_velocity;
numplanes = 0;
}
if(numplanes >= MAX_CLIP_PLANES)
{
// this shouldn't really happen
- self.move_velocity = '0 0 0';
+ this.move_velocity = '0 0 0';
blocked = 3;
break;
}
if(i != numplanes)
{
// go along this plane
- self.move_velocity = new_velocity;
+ this.move_velocity = new_velocity;
}
else
{
// go along the crease
if(numplanes != 2)
{
- self.move_velocity = '0 0 0';
+ this.move_velocity = '0 0 0';
blocked = 7;
break;
}
dir.x *= ilength;
dir.y *= ilength;
dir.z *= ilength;
- float d = (dir * self.move_velocity);
- self.move_velocity = dir * d;
+ float d = (dir * this.move_velocity);
+ this.move_velocity = dir * d;
}
// if current velocity is against the original velocity,
// stop dead to avoid tiny occilations in sloping corners
- if((self.move_velocity * primal_velocity) <= 0)
+ if((this.move_velocity * primal_velocity) <= 0)
{
- self.move_velocity = '0 0 0';
+ this.move_velocity = '0 0 0';
break;
}
}
// LordHavoc: this came from QW and allows you to get out of water more easily
- if(GAMEPLAYFIX_EASIERWATERJUMP && (self.move_flags & FL_WATERJUMP) && !(blocked & 8))
- self.move_velocity = primal_velocity;
+ if(GAMEPLAYFIX_EASIERWATERJUMP && (this.move_flags & FL_WATERJUMP) && !(blocked & 8))
+ this.move_velocity = primal_velocity;
if(applygravity)
{
- if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !(self.move_flags & FL_ONGROUND))
+ if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !(this.move_flags & FL_ONGROUND))
{
if(GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
- self.move_velocity_z -= grav * 0.5f;
+ this.move_velocity_z -= grav * 0.5f;
}
}
return blocked;
}
-void _Movetype_CheckVelocity() // SV_CheckVelocity
+void _Movetype_CheckVelocity(entity this) // SV_CheckVelocity
{
- // if(vlen(self.move_velocity) < 0.0001)
- // self.move_velocity = '0 0 0';
+ // if(vlen(this.move_velocity) < 0.0001)
+ // this.move_velocity = '0 0 0';
}
bool _Movetype_CheckWater(entity ent) // SV_CheckWater
}
}
-void _Movetype_Impact(entity oth) // SV_Impact
-{SELFPARAM();
+void _Movetype_Impact(entity this, entity oth) // SV_Impact
+{
entity oldother = other;
- if(self.move_touch)
+ if(this.move_touch)
{
other = oth;
- self.move_touch();
+ WITH(entity, self, this, this.move_touch());
other = oldother;
}
if(oth.move_touch)
{
- other = self;
+ other = this;
WITH(entity, self, oth, oth.move_touch());
}
}
-void _Movetype_LinkEdict_TouchAreaGrid() // SV_LinkEdict_TouchAreaGrid
-{SELFPARAM();
+void _Movetype_LinkEdict_TouchAreaGrid(entity this) // SV_LinkEdict_TouchAreaGrid
+{
entity oldother = other;
- for (entity e = findradius(0.5 * (self.absmin + self.absmax), 0.5 * vlen(self.absmax - self.absmin)); e; e = e.chain)
+ for (entity e = findradius(0.5 * (this.absmin + this.absmax), 0.5 * vlen(this.absmax - this.absmin)); e; e = e.chain)
{
if(e.move_touch && boxesoverlap(e.absmin, e.absmax, this.absmin, this.absmax))
{
- setself(e);
other = this;
trace_allsolid = false;
trace_plane_dist = 0;
trace_ent = this;
- e.move_touch();
+ WITH(entity, self, e, e.move_touch());
}
}
other = oldother;
- setself(this);
}
-void _Movetype_LinkEdict(bool touch_triggers) // SV_LinkEdict
-{SELFPARAM();
+void _Movetype_LinkEdict(entity this, bool touch_triggers) // SV_LinkEdict
+{
vector mi, ma;
- if(self.solid == SOLID_BSP)
+ if(this.solid == SOLID_BSP)
{
// TODO set the absolute bbox
- mi = self.mins;
- ma = self.maxs;
+ mi = this.mins;
+ ma = this.maxs;
}
else
{
- mi = self.mins;
- ma = self.maxs;
+ mi = this.mins;
+ ma = this.maxs;
}
- mi += self.move_origin;
- ma += self.move_origin;
+ mi += this.move_origin;
+ ma += this.move_origin;
- if(self.move_flags & FL_ITEM)
+ if(this.move_flags & FL_ITEM)
{
mi.x -= 15;
mi.y -= 15;
ma.z += 1;
}
- self.absmin = mi;
- self.absmax = ma;
+ this.absmin = mi;
+ this.absmax = ma;
if(touch_triggers)
- _Movetype_LinkEdict_TouchAreaGrid();
+ _Movetype_LinkEdict_TouchAreaGrid(this);
}
-bool _Movetype_TestEntityPosition(vector ofs) // SV_TestEntityPosition
-{SELFPARAM();
-// vector org = self.move_origin + ofs;
+bool _Movetype_TestEntityPosition(entity this, vector ofs) // SV_TestEntityPosition
+{
+// vector org = this.move_origin + ofs;
- int cont = self.dphitcontentsmask;
- self.dphitcontentsmask = DPCONTENTS_SOLID;
- tracebox(self.move_origin, self.mins, self.maxs, self.move_origin, MOVE_NOMONSTERS, self);
- self.dphitcontentsmask = cont;
+ int cont = this.dphitcontentsmask;
+ this.dphitcontentsmask = DPCONTENTS_SOLID;
+ tracebox(this.move_origin, this.mins, this.maxs, this.move_origin, MOVE_NOMONSTERS, this);
+ this.dphitcontentsmask = cont;
if(trace_startsolid)
return true;
- if(vlen(trace_endpos - self.move_origin) > 0.0001)
- self.move_origin = trace_endpos;
+ if(vlen(trace_endpos - this.move_origin) > 0.0001)
+ this.move_origin = trace_endpos;
return false;
}
-bool _Movetype_UnstickEntity() // SV_UnstickEntity
-{SELFPARAM();
- if(!_Movetype_TestEntityPosition('0 0 0')) return true;
- if(!_Movetype_TestEntityPosition('-1 0 0')) goto success;
- if(!_Movetype_TestEntityPosition('1 0 0')) goto success;
- if(!_Movetype_TestEntityPosition('0 -1 0')) goto success;
- if(!_Movetype_TestEntityPosition('0 1 0')) goto success;
- if(!_Movetype_TestEntityPosition('-1 -1 0')) goto success;
- if(!_Movetype_TestEntityPosition('1 -1 0')) goto success;
- if(!_Movetype_TestEntityPosition('-1 1 0')) goto success;
- if(!_Movetype_TestEntityPosition('1 1 0')) goto success;
+bool _Movetype_UnstickEntity(entity this) // SV_UnstickEntity
+{
+ if(!_Movetype_TestEntityPosition(this, '0 0 0')) return true;
+ if(!_Movetype_TestEntityPosition(this, '-1 0 0')) goto success;
+ if(!_Movetype_TestEntityPosition(this, '1 0 0')) goto success;
+ if(!_Movetype_TestEntityPosition(this, '0 -1 0')) goto success;
+ if(!_Movetype_TestEntityPosition(this, '0 1 0')) goto success;
+ if(!_Movetype_TestEntityPosition(this, '-1 -1 0')) goto success;
+ if(!_Movetype_TestEntityPosition(this, '1 -1 0')) goto success;
+ if(!_Movetype_TestEntityPosition(this, '-1 1 0')) goto success;
+ if(!_Movetype_TestEntityPosition(this, '1 1 0')) goto success;
for (int i = 1; i <= 17; ++i)
{
- if(!_Movetype_TestEntityPosition('0 0 -1' * i)) goto success;
- if(!_Movetype_TestEntityPosition('0 0 1' * i)) goto success;
+ if(!_Movetype_TestEntityPosition(this, '0 0 -1' * i)) goto success;
+ if(!_Movetype_TestEntityPosition(this, '0 0 1' * i)) goto success;
}
LOG_TRACEF("Can't unstick an entity (edict: %d, classname: %s, origin: %s)\n",
- num_for_edict(self), self.classname, vtos(self.move_origin));
+ num_for_edict(this), this.classname, vtos(this.move_origin));
return false;
: success;
LOG_TRACEF("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)\n",
- num_for_edict(self), self.classname, vtos(self.move_origin));
- _Movetype_LinkEdict(true);
+ num_for_edict(this), this.classname, vtos(this.move_origin));
+ _Movetype_LinkEdict(this, true);
return true;
}
return vel;
}
-void _Movetype_PushEntityTrace(vector push)
-{SELFPARAM();
- vector end = self.move_origin + push;
+void _Movetype_PushEntityTrace(entity this, vector push)
+{
+ vector end = this.move_origin + push;
int type;
- if(self.move_nomonsters)
- type = max(0, self.move_nomonsters);
- else if(self.move_movetype == MOVETYPE_FLYMISSILE)
+ if(this.move_nomonsters)
+ type = max(0, this.move_nomonsters);
+ else if(this.move_movetype == MOVETYPE_FLYMISSILE)
type = MOVE_MISSILE;
- else if(self.solid == SOLID_TRIGGER || self.solid == SOLID_NOT)
+ else if(this.solid == SOLID_TRIGGER || this.solid == SOLID_NOT)
type = MOVE_NOMONSTERS;
else
type = MOVE_NORMAL;
- tracebox(self.move_origin, self.mins, self.maxs, end, type, self);
+ tracebox(this.move_origin, this.mins, this.maxs, end, type, this);
}
-float _Movetype_PushEntity(vector push, bool failonstartsolid) // SV_PushEntity
-{SELFPARAM();
- _Movetype_PushEntityTrace(push);
+float _Movetype_PushEntity(entity this, vector push, bool failonstartsolid) // SV_PushEntity
+{
+ _Movetype_PushEntityTrace(this, push);
if(trace_startsolid && failonstartsolid)
return trace_fraction;
- self.move_origin = trace_endpos;
+ this.move_origin = trace_endpos;
if(trace_fraction < 1)
- if(self.solid >= SOLID_TRIGGER && (!(self.move_flags & FL_ONGROUND) || (self.move_groundentity != trace_ent)))
- _Movetype_Impact(trace_ent);
+ if(this.solid >= SOLID_TRIGGER && (!(this.move_flags & FL_ONGROUND) || (this.move_groundentity != trace_ent)))
+ _Movetype_Impact(this, trace_ent);
return trace_fraction;
}
}
}
-void _Movetype_Physics_Frame(float movedt)
-{SELFPARAM();
- self.move_didgravity = -1;
- switch (self.move_movetype)
+void _Movetype_Physics_Frame(entity this, float movedt)
+{
+ this.move_didgravity = -1;
+ switch (this.move_movetype)
{
case MOVETYPE_PUSH:
case MOVETYPE_FAKEPUSH:
- _Movetype_Physics_Pusher(movedt);
+ _Movetype_Physics_Pusher(this, movedt);
break;
case MOVETYPE_NONE:
break;
case MOVETYPE_FOLLOW:
- _Movetype_Physics_Follow();
+ _Movetype_Physics_Follow(this);
break;
case MOVETYPE_NOCLIP:
- _Movetype_CheckWater(self);
- self.move_origin = self.move_origin + TICRATE * self.move_velocity;
- self.move_angles = self.move_angles + TICRATE * self.move_avelocity;
- _Movetype_LinkEdict(false);
+ _Movetype_CheckWater(this);
+ this.move_origin = this.move_origin + TICRATE * this.move_velocity;
+ this.move_angles = this.move_angles + TICRATE * this.move_avelocity;
+ _Movetype_LinkEdict(this, false);
break;
case MOVETYPE_STEP:
- _Movetype_Physics_Step(movedt);
+ _Movetype_Physics_Step(this, movedt);
break;
case MOVETYPE_WALK:
- _Movetype_Physics_Walk(movedt);
+ _Movetype_Physics_Walk(this, movedt);
break;
case MOVETYPE_TOSS:
case MOVETYPE_BOUNCE:
case MOVETYPE_BOUNCEMISSILE:
case MOVETYPE_FLYMISSILE:
case MOVETYPE_FLY:
- _Movetype_Physics_Toss(movedt);
+ _Movetype_Physics_Toss(this, movedt);
break;
}
}
-void Movetype_Physics_NoMatchServer() // optimized
-{SELFPARAM();
- float movedt = time - self.move_time;
- self.move_time = time;
+void Movetype_Physics_NoMatchServer(entity this) // optimized
+{
+ float movedt = time - this.move_time;
+ this.move_time = time;
- _Movetype_Physics_Frame(movedt);
- if(wasfreed(self))
+ _Movetype_Physics_Frame(this, movedt);
+ if(wasfreed(this))
return;
- self.avelocity = self.move_avelocity;
- self.velocity = self.move_velocity;
- self.angles = self.move_angles;
- setorigin(self, self.move_origin);
+ this.avelocity = this.move_avelocity;
+ this.velocity = this.move_velocity;
+ this.angles = this.move_angles;
+ setorigin(this, this.move_origin);
}
-void Movetype_Physics_MatchServer(bool sloppy)
+void Movetype_Physics_MatchServer(entity this, bool sloppy)
{
- Movetype_Physics_MatchTicrate(TICRATE, sloppy);
+ Movetype_Physics_MatchTicrate(this, TICRATE, sloppy);
}
-void Movetype_Physics_MatchTicrate(float tr, bool sloppy) // SV_Physics_Entity
-{SELFPARAM();
+void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy) // SV_Physics_Entity
+{
if(tr <= 0)
{
- Movetype_Physics_NoMatchServer();
+ Movetype_Physics_NoMatchServer(this);
return;
}
- float dt = time - self.move_time;
+ float dt = time - this.move_time;
int n = max(0, floor(dt / tr));
dt -= n * tr;
- self.move_time += n * tr;
+ this.move_time += n * tr;
- if(!self.move_didgravity)
- self.move_didgravity = ((self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS) && !(self.move_flags & FL_ONGROUND));
+ if(!this.move_didgravity)
+ this.move_didgravity = ((this.move_movetype == MOVETYPE_BOUNCE || this.move_movetype == MOVETYPE_TOSS) && !(this.move_flags & FL_ONGROUND));
for (int i = 0; i < n; ++i)
{
- _Movetype_Physics_Frame(tr);
- if(wasfreed(self))
+ _Movetype_Physics_Frame(this, tr);
+ if(wasfreed(this))
return;
}
- self.avelocity = self.move_avelocity;
+ this.avelocity = this.move_avelocity;
- if(dt > 0 && self.move_movetype != MOVETYPE_NONE && !(self.move_flags & FL_ONGROUND))
+ if(dt > 0 && this.move_movetype != MOVETYPE_NONE && !(this.move_flags & FL_ONGROUND))
{
// now continue the move from move_time to time
- self.velocity = self.move_velocity;
+ this.velocity = this.move_velocity;
- if(self.move_didgravity > 0)
+ if(this.move_didgravity > 0)
{
- self.velocity_z -= (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1)
+ this.velocity_z -= (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1)
* dt
- * (self.gravity ? self.gravity : 1)
+ * (this.gravity ? this.gravity : 1)
* PHYS_GRAVITY(this);
}
- self.angles = self.move_angles + dt * self.avelocity;
+ this.angles = this.move_angles + dt * this.avelocity;
- if(sloppy || self.move_movetype == MOVETYPE_NOCLIP)
+ if(sloppy || this.move_movetype == MOVETYPE_NOCLIP)
{
- setorigin(self, self.move_origin + dt * self.velocity);
+ setorigin(this, this.move_origin + dt * this.velocity);
}
else
{
- _Movetype_PushEntityTrace(dt * self.velocity);
+ _Movetype_PushEntityTrace(this, dt * this.velocity);
if(!trace_startsolid)
- setorigin(self, trace_endpos);
+ setorigin(this, trace_endpos);
}
- if(self.move_didgravity > 0 && GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
- self.velocity_z -= 0.5 * dt * (self.gravity ? self.gravity : 1) * PHYS_GRAVITY(this);
+ if(this.move_didgravity > 0 && GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
+ this.velocity_z -= 0.5 * dt * (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
}
else
{
- self.velocity = self.move_velocity;
- self.angles = self.move_angles;
- setorigin(self, self.move_origin);
+ this.velocity = this.move_velocity;
+ this.angles = this.move_angles;
+ setorigin(this, this.move_origin);
}
}
.float move_suspendedinair;
.float move_didgravity;
-void _Movetype_WallFriction(vector stepnormal);
-int _Movetype_FlyMove(float dt, bool applygravity, vector stepnormal, float stepheight);
-void _Movetype_CheckVelocity();
+void _Movetype_WallFriction(entity this, vector stepnormal);
+int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnormal, float stepheight);
+void _Movetype_CheckVelocity(entity this);
void _Movetype_CheckWaterTransition(entity ent);
float _Movetype_CheckWater(entity ent);
-void _Movetype_LinkEdict_TouchAreaGrid();
-void _Movetype_LinkEdict(float touch_triggers);
-float _Movetype_TestEntityPosition(vector ofs);
-float _Movetype_UnstickEntity();
+void _Movetype_LinkEdict_TouchAreaGrid(entity this);
+void _Movetype_LinkEdict(entity this, float touch_triggers);
+float _Movetype_TestEntityPosition(entity this, vector ofs);
+float _Movetype_UnstickEntity(entity this);
vector _Movetype_ClipVelocity(vector vel, vector norm, float f);
-void _Movetype_PushEntityTrace(vector push);
-float _Movetype_PushEntity(vector push, float failonstartsolid);
+void _Movetype_PushEntityTrace(entity this, vector push);
+float _Movetype_PushEntity(entity this, vector push, float failonstartsolid);
void makevectors_matrix(vector myangles);
-void Movetype_Physics_MatchTicrate(float tr, bool sloppy);
-void Movetype_Physics_MatchServer(bool sloppy);
-void Movetype_Physics_NoMatchServer();
-void _Movetype_LinkEdict(float touch_triggers);
-void _Movetype_LinkEdict_TouchAreaGrid();
+void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy);
+void Movetype_Physics_MatchServer(entity this, bool sloppy);
+void Movetype_Physics_NoMatchServer(entity this);
+void _Movetype_LinkEdict(entity this, float touch_triggers);
+void _Movetype_LinkEdict_TouchAreaGrid(entity this);
-float _Movetype_UnstickEntity();
+float _Movetype_UnstickEntity(entity this);
const int MAX_CLIP_PLANES = 5;
-void _Movetype_PushMove(float dt) // SV_PushMove
-{SELFPARAM();
- if (self.move_velocity == '0 0 0' && self.move_avelocity == '0 0 0')
+void _Movetype_PushMove(entity this, float dt) // SV_PushMove
+{
+ if (this.move_velocity == '0 0 0' && this.move_avelocity == '0 0 0')
{
- self.move_ltime += dt;
+ this.move_ltime += dt;
return;
}
- switch (self.solid)
+ switch (this.solid)
{
// LordHavoc: valid pusher types
case SOLID_BSP:
// LordHavoc: no collisions
case SOLID_NOT:
case SOLID_TRIGGER:
- self.move_origin = self.move_origin + dt * self.move_velocity;
- self.move_angles = self.move_angles + dt * self.move_avelocity;
- self.move_angles_x -= 360.0 * floor(self.move_angles.x * (1.0 / 360.0));
- self.move_angles_y -= 360.0 * floor(self.move_angles.y * (1.0 / 360.0));
- self.move_angles_z -= 360.0 * floor(self.move_angles.z * (1.0 / 360.0));
- self.move_ltime += dt;
- _Movetype_LinkEdict(true);
+ this.move_origin = this.move_origin + dt * this.move_velocity;
+ this.move_angles = this.move_angles + dt * this.move_avelocity;
+ this.move_angles_x -= 360.0 * floor(this.move_angles.x * (1.0 / 360.0));
+ this.move_angles_y -= 360.0 * floor(this.move_angles.y * (1.0 / 360.0));
+ this.move_angles_z -= 360.0 * floor(this.move_angles.z * (1.0 / 360.0));
+ this.move_ltime += dt;
+ _Movetype_LinkEdict(this, true);
return;
default:
- LOG_TRACEF("_Movetype_PushMove: entity %e, unrecognized solid type %d\n", self, self.solid);
+ LOG_TRACEF("_Movetype_PushMove: entity %e, unrecognized solid type %d\n", this, this.solid);
return;
}
- bool rotated = (self.move_angles * self.move_angles) + (self.move_avelocity * self.move_avelocity) > 0;
+ bool rotated = (this.move_angles * this.move_angles) + (this.move_avelocity * this.move_avelocity) > 0;
- vector move1 = self.move_velocity * dt;
- vector moveangle = self.move_avelocity * dt;
+ vector move1 = this.move_velocity * dt;
+ vector moveangle = this.move_avelocity * dt;
makevectors_matrix(-moveangle);
-// vector pushorig = self.move_origin;
-// vector pushang = self.move_angles;
-// float pushltime = self.move_ltime;
+// vector pushorig = this.move_origin;
+// vector pushang = this.move_angles;
+// float pushltime = this.move_ltime;
// move the pusher to its final position
- self.move_origin = self.move_origin + dt * self.move_velocity;
- self.move_angles = self.move_angles + dt * self.move_avelocity;
+ this.move_origin = this.move_origin + dt * this.move_velocity;
+ this.move_angles = this.move_angles + dt * this.move_avelocity;
- self.move_ltime += dt;
- _Movetype_LinkEdict(true);
+ this.move_ltime += dt;
+ _Movetype_LinkEdict(this, true);
- int savesolid = self.solid;
+ int savesolid = this.solid;
- if (self.move_movetype != MOVETYPE_FAKEPUSH)
+ if (this.move_movetype != MOVETYPE_FAKEPUSH)
{
- for (entity check = findradius(0.5 * (self.absmin + self.absmax), 0.5 * vlen(self.absmax - self.absmin)); check; check = check.chain)
+ for (entity check = findradius(0.5 * (this.absmin + this.absmax), 0.5 * vlen(this.absmax - this.absmin)); check; check = check.chain)
{
switch (check.move_movetype)
{
break;
}
- if (check.owner == self)
+ if (check.owner == this)
continue;
- if (self.owner == check)
+ if (this.owner == check)
continue;
vector pivot = check.mins + 0.5 * (check.maxs - check.mins);
vector move;
if (rotated)
{
- vector org = (check.move_origin - self.move_origin) + pivot;
+ vector org = (check.move_origin - this.move_origin) + pivot;
vector org2;
org2.x = org * v_forward;
org2.y = org * v_right;
if (check.move_movetype == 32) // MOVETYPE_PHYSICS
{
check.move_origin = check.move_origin + move;
- WITH(entity, self, check, _Movetype_LinkEdict(true));
+ WITH(entity, this, check, _Movetype_LinkEdict(this, true));
continue;
}
// try moving the contacted entity
- self.solid = SOLID_NOT;
+ this.solid = SOLID_NOT;
bool flag;
- WITH(entity, self, check, {
- flag = _Movetype_PushEntity(move, true);
+ WITH(entity, this, check, {
+ flag = _Movetype_PushEntity(this, move, true);
});
if (!flag)
{
// entity "check" got teleported
check.move_angles_y += trace_fraction * moveangle.y;
- self.solid = savesolid;
+ this.solid = savesolid;
continue; // pushed enough
}
// FIXME: turn players specially
check.move_angles_y += trace_fraction * moveangle.y;
- self.solid = savesolid;
+ this.solid = savesolid;
// this trace.fraction < 1 check causes items to fall off of pushers
// if they pass under or through a wall
// the groundentity check causes items to fall off of ledges
- if (check.move_movetype != MOVETYPE_WALK && (trace_fraction < 1 || check.move_groundentity != self))
+ if (check.move_movetype != MOVETYPE_WALK && (trace_fraction < 1 || check.move_groundentity != this))
check.move_flags &= ~FL_ONGROUND;
}
}
- self.move_angles_x -= 360.0 * floor(self.move_angles.x * (1.0 / 360.0));
- self.move_angles_y -= 360.0 * floor(self.move_angles.y * (1.0 / 360.0));
- self.move_angles_z -= 360.0 * floor(self.move_angles.z * (1.0 / 360.0));
+ this.move_angles_x -= 360.0 * floor(this.move_angles.x * (1.0 / 360.0));
+ this.move_angles_y -= 360.0 * floor(this.move_angles.y * (1.0 / 360.0));
+ this.move_angles_z -= 360.0 * floor(this.move_angles.z * (1.0 / 360.0));
}
-void _Movetype_Physics_Pusher(float dt) // SV_Physics_Pusher
-{SELFPARAM();
- float oldltime = self.move_ltime;
- float thinktime = self.move_nextthink;
+void _Movetype_Physics_Pusher(entity this, float dt) // SV_Physics_Pusher
+{
+ float oldltime = this.move_ltime;
+ float thinktime = this.move_nextthink;
float movetime;
- if (thinktime < self.move_ltime + dt)
+ if (thinktime < this.move_ltime + dt)
{
- movetime = thinktime - self.move_ltime;
+ movetime = thinktime - this.move_ltime;
if (movetime < 0)
movetime = 0;
}
}
if (movetime)
- // advances self.move_ltime if not blocked
- _Movetype_PushMove(movetime);
+ // advances this.move_ltime if not blocked
+ _Movetype_PushMove(this, movetime);
- if (thinktime > oldltime && thinktime <= self.move_ltime)
+ if (thinktime > oldltime && thinktime <= this.move_ltime)
{
- self.move_nextthink = 0;
- self.move_time = time;
+ this.move_nextthink = 0;
+ this.move_time = time;
other = world;
- if (self.move_think)
- self.move_think();
+ WITH(entity, self, this, this.move_think());
}
}
#ifndef MOVETYPE_PUSH_H
#define MOVETYPE_PUSH_H
-void _Movetype_Physics_Pusher(float dt);
+void _Movetype_Physics_Pusher(entity this, float dt);
#endif
-void _Movetype_Physics_Step(float dt) // SV_Physics_Step
-{SELFPARAM();
- if(self.move_flags & FL_ONGROUND)
+void _Movetype_Physics_Step(entity this, float dt) // SV_Physics_Step
+{
+ if(this.move_flags & FL_ONGROUND)
{
- if(self.velocity_z >= (1.0 / 32.0) && UPWARD_VELOCITY_CLEARS_ONGROUND)
+ if(this.velocity_z >= (1.0 / 32.0) && UPWARD_VELOCITY_CLEARS_ONGROUND)
{
- self.move_flags &= ~FL_ONGROUND;
- _Movetype_CheckVelocity();
- _Movetype_FlyMove(dt, true, '0 0 0', 0);
- _Movetype_LinkEdict(true);
+ this.move_flags &= ~FL_ONGROUND;
+ _Movetype_CheckVelocity(this);
+ _Movetype_FlyMove(this, dt, true, '0 0 0', 0);
+ _Movetype_LinkEdict(this, true);
}
}
else
{
- _Movetype_CheckVelocity();
- _Movetype_FlyMove(dt, true, '0 0 0', 0);
- _Movetype_LinkEdict(true);
+ _Movetype_CheckVelocity(this);
+ _Movetype_FlyMove(this, dt, true, '0 0 0', 0);
+ _Movetype_LinkEdict(this, true);
// TODO? movetypesteplandevent
}
- _Movetype_CheckWaterTransition(self);
+ _Movetype_CheckWaterTransition(this);
}
#include "../physics.qh"
-void _Movetype_Physics_Toss(float dt) // SV_Physics_Toss
-{SELFPARAM();
- if (self.move_flags & FL_ONGROUND)
+void _Movetype_Physics_Toss(entity this, float dt) // SV_Physics_Toss
+{
+ if (this.move_flags & FL_ONGROUND)
{
- if (self.move_velocity.z >= 1 / 32)
+ if (this.move_velocity.z >= 1 / 32)
{
- self.move_flags &= ~FL_ONGROUND;
+ this.move_flags &= ~FL_ONGROUND;
}
- else if (!self.move_groundentity)
+ else if (!this.move_groundentity)
{
return;
}
- else if (self.move_suspendedinair && wasfreed(self.move_groundentity))
+ else if (this.move_suspendedinair && wasfreed(this.move_groundentity))
{
- self.move_groundentity = world;
+ this.move_groundentity = world;
return;
}
}
- self.move_suspendedinair = false;
+ this.move_suspendedinair = false;
- _Movetype_CheckVelocity();
+ _Movetype_CheckVelocity(this);
- if (self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS)
+ if (this.move_movetype == MOVETYPE_BOUNCE || this.move_movetype == MOVETYPE_TOSS)
{
- self.move_didgravity = 1;
- self.move_velocity_z -= (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1)
+ this.move_didgravity = 1;
+ this.move_velocity_z -= (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1)
* dt
- * (self.gravity ? self.gravity : 1)
+ * (this.gravity ? this.gravity : 1)
* PHYS_GRAVITY(this);
}
- self.move_angles = self.move_angles + self.move_avelocity * dt;
+ this.move_angles = this.move_angles + this.move_avelocity * dt;
float movetime = dt;
for (int bump = 0; bump < MAX_CLIP_PLANES && movetime > 0; ++bump)
{
- vector move = self.move_velocity * movetime;
- _Movetype_PushEntity(move, true);
- if (wasfreed(self))
+ vector move = this.move_velocity * movetime;
+ _Movetype_PushEntity(this, move, true);
+ if (wasfreed(this))
return;
if (trace_startsolid)
{
- _Movetype_UnstickEntity();
- _Movetype_PushEntity(move, false);
- if (wasfreed(self))
+ _Movetype_UnstickEntity(this);
+ _Movetype_PushEntity(this, move, false);
+ if (wasfreed(this))
return;
}
movetime *= 1 - min(1, trace_fraction);
- if (self.move_movetype == MOVETYPE_BOUNCEMISSILE)
+ if (this.move_movetype == MOVETYPE_BOUNCEMISSILE)
{
- self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 2.0);
- self.move_flags &= ~FL_ONGROUND;
+ this.move_velocity = _Movetype_ClipVelocity(this.move_velocity, trace_plane_normal, 2.0);
+ this.move_flags &= ~FL_ONGROUND;
}
- else if (self.move_movetype == MOVETYPE_BOUNCE)
+ else if (this.move_movetype == MOVETYPE_BOUNCE)
{
- float bouncefac = self.move_bounce_factor; if (!bouncefac) bouncefac = 0.5;
- float bouncestop = self.move_bounce_stopspeed; if (!bouncestop) bouncestop = 60 / 800;
- bouncestop *= (self.gravity ? self.gravity : 1) * PHYS_GRAVITY(this);
+ float bouncefac = this.move_bounce_factor; if (!bouncefac) bouncefac = 0.5;
+ float bouncestop = this.move_bounce_stopspeed; if (!bouncestop) bouncestop = 60 / 800;
+ bouncestop *= (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
- self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1 + bouncefac);
+ this.move_velocity = _Movetype_ClipVelocity(this.move_velocity, trace_plane_normal, 1 + bouncefac);
- float d = trace_plane_normal * self.move_velocity;
+ float d = trace_plane_normal * this.move_velocity;
if (trace_plane_normal.z > 0.7 && d < bouncestop && d > -bouncestop)
{
- self.move_flags |= FL_ONGROUND;
- self.move_groundentity = trace_ent;
- self.move_velocity = '0 0 0';
- self.move_avelocity = '0 0 0';
+ this.move_flags |= FL_ONGROUND;
+ this.move_groundentity = trace_ent;
+ this.move_velocity = '0 0 0';
+ this.move_avelocity = '0 0 0';
}
else
{
- self.move_flags &= ~FL_ONGROUND;
+ this.move_flags &= ~FL_ONGROUND;
}
}
else
{
- self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1.0);
+ this.move_velocity = _Movetype_ClipVelocity(this.move_velocity, trace_plane_normal, 1.0);
if (trace_plane_normal.z > 0.7)
{
- self.move_flags |= FL_ONGROUND;
- self.move_groundentity = trace_ent;
+ this.move_flags |= FL_ONGROUND;
+ this.move_groundentity = trace_ent;
if (trace_ent.solid == SOLID_BSP)
- self.move_suspendedinair = true;
- self.move_velocity = '0 0 0';
- self.move_avelocity = '0 0 0';
+ this.move_suspendedinair = true;
+ this.move_velocity = '0 0 0';
+ this.move_avelocity = '0 0 0';
}
else
{
- self.move_flags &= ~FL_ONGROUND;
+ this.move_flags &= ~FL_ONGROUND;
}
}
// DP revision 8905 (just, WHY...)
- if (self.move_movetype == MOVETYPE_BOUNCEMISSILE)
+ if (this.move_movetype == MOVETYPE_BOUNCEMISSILE)
break;
// DP revision 8918 (WHY...)
- if (self.move_flags & FL_ONGROUND)
+ if (this.move_flags & FL_ONGROUND)
break;
}
- if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE && self.move_didgravity > 0 && !(self.move_flags & FL_ONGROUND))
- self.move_velocity_z -= 0.5 * dt * (self.gravity ? self.gravity : 1) * PHYS_GRAVITY(this);
+ if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE && this.move_didgravity > 0 && !(this.move_flags & FL_ONGROUND))
+ this.move_velocity_z -= 0.5 * dt * (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
- _Movetype_CheckWaterTransition(self);
+ _Movetype_CheckWaterTransition(this);
}
#ifndef MOVETYPE_TOSS_H
#define MOVETYPE_TOSS_H
-void _Movetype_Physics_Toss(float dt);
+void _Movetype_Physics_Toss(entity this, float dt);
#endif
-void _Movetype_Physics_Walk(float dt) // SV_WalkMove
-{SELFPARAM();
+void _Movetype_Physics_Walk(entity this, float dt) // SV_WalkMove
+{
vector stepnormal = '0 0 0';
// if frametime is 0 (due to client sending the same timestamp twice), don't move
return;
if (GAMEPLAYFIX_UNSTICKPLAYERS)
- _Movetype_UnstickEntity();
+ _Movetype_UnstickEntity(this);
- bool applygravity = (!_Movetype_CheckWater(self) && self.move_movetype == MOVETYPE_WALK && !(self.move_flags & FL_WATERJUMP));
+ bool applygravity = (!_Movetype_CheckWater(this) && this.move_movetype == MOVETYPE_WALK && !(this.move_flags & FL_WATERJUMP));
- _Movetype_CheckVelocity();
+ _Movetype_CheckVelocity(this);
// do a regular slide move unless it looks like you ran into a step
- bool oldonground = (self.move_flags & FL_ONGROUND);
+ bool oldonground = (this.move_flags & FL_ONGROUND);
- vector start_origin = self.move_origin;
- vector start_velocity = self.move_velocity;
+ vector start_origin = this.move_origin;
+ vector start_velocity = this.move_velocity;
- int clip = _Movetype_FlyMove(dt, applygravity, stepnormal, GAMEPLAYFIX_STEPMULTIPLETIMES ? PHYS_STEPHEIGHT : 0);
+ int clip = _Movetype_FlyMove(this, dt, applygravity, stepnormal, GAMEPLAYFIX_STEPMULTIPLETIMES ? PHYS_STEPHEIGHT : 0);
if (GAMEPLAYFIX_DOWNTRACEONGROUND && !(clip & 1))
{
// only try this if there was no floor in the way in the trace (no,
// this check seems to be not REALLY necessary, because if clip & 1,
// our trace will hit that thing too)
- vector upmove = self.move_origin + '0 0 1';
- vector downmove = self.move_origin - '0 0 1';
+ vector upmove = this.move_origin + '0 0 1';
+ vector downmove = this.move_origin - '0 0 1';
int type;
- if (self.move_movetype == MOVETYPE_FLYMISSILE)
+ if (this.move_movetype == MOVETYPE_FLYMISSILE)
type = MOVE_MISSILE;
- else if (self.move_movetype == MOVETYPE_FLY_WORLDONLY)
+ else if (this.move_movetype == MOVETYPE_FLY_WORLDONLY)
type = MOVE_WORLDONLY;
- else if (self.solid == SOLID_TRIGGER || self.solid == SOLID_NOT)
+ else if (this.solid == SOLID_TRIGGER || this.solid == SOLID_NOT)
type = MOVE_NOMONSTERS;
else type = MOVE_NORMAL;
- tracebox(upmove, self.mins, self.maxs, downmove, type, self);
+ tracebox(upmove, this.mins, this.maxs, downmove, type, this);
if (trace_fraction < 1 && trace_plane_normal.z > 0.7)
clip |= 1; // but we HAVE found a floor
}
// if the move did not hit the ground at any point, we're not on ground
if (!(clip & 1))
- self.move_flags &= ~FL_ONGROUND;
+ this.move_flags &= ~FL_ONGROUND;
- _Movetype_CheckVelocity();
- _Movetype_LinkEdict(true);
+ _Movetype_CheckVelocity(this);
+ _Movetype_LinkEdict(this, true);
if (clip & 8) // teleport
return;
- if (self.move_flags & FL_WATERJUMP)
+ if (this.move_flags & FL_WATERJUMP)
return;
if (PHYS_NOSTEP)
return;
- vector originalmove_origin = self.move_origin;
- vector originalmove_velocity = self.move_velocity;
+ vector originalmove_origin = this.move_origin;
+ vector originalmove_velocity = this.move_velocity;
// originalmove_clip = clip;
- int originalmove_flags = self.move_flags;
- entity originalmove_groundentity = self.move_groundentity;
+ int originalmove_flags = this.move_flags;
+ entity originalmove_groundentity = this.move_groundentity;
// if move didn't block on a step, return
if (clip & 2)
if (fabs(start_velocity.x) < 0.03125 && fabs(start_velocity.y) < 0.03125)
return;
- if (self.move_movetype != MOVETYPE_FLY)
+ if (this.move_movetype != MOVETYPE_FLY)
{
// return if gibbed by a trigger
- if (self.move_movetype != MOVETYPE_WALK)
+ if (this.move_movetype != MOVETYPE_WALK)
return;
// return if attempting to jump while airborn (unless sv_jumpstep)
if (!PHYS_JUMPSTEP)
- if (!oldonground && self.move_waterlevel == 0)
+ if (!oldonground && this.move_waterlevel == 0)
return;
}
// try moving up and forward to go up a step
// back to start pos
- self.move_origin = start_origin;
- self.move_velocity = start_velocity;
+ this.move_origin = start_origin;
+ this.move_velocity = start_velocity;
// move up
vector upmove = '0 0 1' * PHYS_STEPHEIGHT;
- vector prev_origin = self.move_origin;
- _Movetype_PushEntity(upmove, true);
- if(wasfreed(self))
+ vector prev_origin = this.move_origin;
+ _Movetype_PushEntity(this, upmove, true);
+ if(wasfreed(this))
return;
- if(trace_startsolid && self.move_origin != prev_origin)
+ if(trace_startsolid && this.move_origin != prev_origin)
{
// we got teleported when upstepping... must abort the move
return;
}
// move forward
- self.move_velocity_z = 0;
- clip = _Movetype_FlyMove(dt, applygravity, stepnormal, 0);
- self.move_velocity_z += start_velocity.z;
+ this.move_velocity_z = 0;
+ clip = _Movetype_FlyMove(this, dt, applygravity, stepnormal, 0);
+ this.move_velocity_z += start_velocity.z;
if (clip & 8)
{
// we got teleported when upstepping... must abort the move
return;
}
- _Movetype_CheckVelocity();
- _Movetype_LinkEdict(true);
+ _Movetype_CheckVelocity(this);
+ _Movetype_LinkEdict(this, true);
// check for stuckness, possibly due to the limited precision of floats
// in the clipping hulls
if (clip
- && fabs(originalmove_origin.y - self.move_origin.y) < 0.03125
- && fabs(originalmove_origin.x - self.move_origin.x) < 0.03125)
+ && fabs(originalmove_origin.y - this.move_origin.y) < 0.03125
+ && fabs(originalmove_origin.x - this.move_origin.x) < 0.03125)
{
// Con_Printf("wall\n");
// stepping up didn't make any progress, revert to original move
- self.move_origin = originalmove_origin;
- self.move_velocity = originalmove_velocity;
+ this.move_origin = originalmove_origin;
+ this.move_velocity = originalmove_velocity;
// clip = originalmove_clip;
- self.move_flags = originalmove_flags;
- self.move_groundentity = originalmove_groundentity;
+ this.move_flags = originalmove_flags;
+ this.move_groundentity = originalmove_groundentity;
// now try to unstick if needed
// clip = SV_TryUnstick (ent, oldvel);
return;
// extra friction based on view angle
if ((clip & 2) && PHYS_WALLFRICTION)
- _Movetype_WallFriction(stepnormal);
+ _Movetype_WallFriction(this, stepnormal);
}
// don't do the down move if stepdown is disabled, moving upward, not in water, or the move started offground or ended onground
- else if (!GAMEPLAYFIX_STEPDOWN || self.move_waterlevel >= 3 || start_velocity.z >= (1.0 / 32.0) || !oldonground || (self.move_flags & FL_ONGROUND))
+ else if (!GAMEPLAYFIX_STEPDOWN || this.move_waterlevel >= 3 || start_velocity.z >= (1.0 / 32.0) || !oldonground || (this.move_flags & FL_ONGROUND))
{
return;
}
// move down
vector downmove = '0 0 1' * (-PHYS_STEPHEIGHT + start_velocity.z * dt);
- vector prev_origin = self.move_origin;
- _Movetype_PushEntity(downmove, true);
- if(wasfreed(self))
+ vector prev_origin = this.move_origin;
+ _Movetype_PushEntity(this, downmove, true);
+ if(wasfreed(this))
return;
- if(trace_startsolid && self.move_origin != prev_origin)
+ if(trace_startsolid && this.move_origin != prev_origin)
{
// we got teleported when downstepping... must abort the move
return;
// if the push down didn't end up on good ground, use the move without
// the step up. This happens near wall / slope combinations, and can
// cause the player to hop up higher on a slope too steep to climb
- self.move_origin = originalmove_origin;
- self.move_velocity = originalmove_velocity;
- self.move_flags = originalmove_flags;
- self.move_groundentity = originalmove_groundentity;
+ this.move_origin = originalmove_origin;
+ this.move_velocity = originalmove_velocity;
+ this.move_flags = originalmove_flags;
+ this.move_groundentity = originalmove_groundentity;
}
- _Movetype_CheckVelocity();
- _Movetype_LinkEdict(true);
+ _Movetype_CheckVelocity(this);
+ _Movetype_LinkEdict(this, true);
}
#ifndef MOVETYPE_WALK_H
#define MOVETYPE_WALK_H
-void _Movetype_Physics_Walk(float dt);
+void _Movetype_Physics_Walk(entity this, float dt);
#endif
#include "mutator/bloodloss/module.inc"
#include "mutator/breakablehook/module.inc"
#include "mutator/buffs/module.inc"
+#include "mutator/bugrigs/module.inc"
#include "mutator/campcheck/module.inc"
#include "mutator/cloaked/module.inc"
#include "mutator/damagetext/module.inc"
#include "mutator/dodging/module.inc"
+#include "mutator/doublejump/module.inc"
#include "mutator/hook/module.inc"
#include "mutator/instagib/module.inc"
#include "mutator/invincibleproj/module.inc"
/**/
MUTATOR_HOOKABLE(WP_Format, EV_WP_Format);
+/**
+ * called before any player physics, may adjust variables for movement,
+ * is run AFTER bot code and idle checking on the server
+ */
+#define EV_PlayerPhysics(i, o) \
+ /**/ i(entity, __self) \
+ /**/
+MUTATOR_HOOKABLE(PlayerPhysics, EV_PlayerPhysics);
+
+/** called when a player presses the jump key */
+#define EV_PlayerJump(i, o) \
+ /**/ i(entity, __self) \
+ /**/ i(float, player_multijump) \
+ /**/ i(float, player_jumpheight) \
+ /**/ o(float, player_multijump) \
+ /**/ o(float, player_jumpheight) \
+ /**/
+float player_multijump;
+float player_jumpheight;
+MUTATOR_HOOKABLE(PlayerJump, EV_PlayerJump);
+
+/** called during player physics, allows adjusting the movement type used */
+#define EV_PM_Physics(i, o) \
+ /**/ i(entity, __self) \
+ /**/ i(float, pm_maxspeed_mod) \
+ /**/
+float pm_maxspeed_mod;
+MUTATOR_HOOKABLE(PM_Physics, EV_PM_Physics);
+
#endif
{
vh_vehicle.buffs = vh_player.buffs;
vh_player.buffs = 0;
- vh_vehicle.buff_time = vh_player.buff_time - time;
+ vh_vehicle.buff_time = max(0, time - vh_player.buff_time);
vh_player.buff_time = 0;
return false;
}
--- /dev/null
+#ifdef IMPLEMENTATION
+#ifdef SVQC
+ #include "../../../../server/antilag.qh"
+#endif
+#include "../../../physics.qh"
+
+
+#if defined(SVQC)
+void bugrigs_SetVars();
+
+REGISTER_MUTATOR(bugrigs, cvar("g_bugrigs"))
+{
+ MUTATOR_ONADD
+ {
+ bugrigs_SetVars();
+ }
+ return false;
+}
+#elif defined(CSQC)
+REGISTER_MUTATOR(bugrigs, true);
+#endif
+
+
+#define PHYS_BUGRIGS(s) STAT(BUGRIGS, s)
+#define PHYS_BUGRIGS_ACCEL(s) STAT(BUGRIGS_ACCEL, s)
+#define PHYS_BUGRIGS_AIR_STEERING(s) STAT(BUGRIGS_AIR_STEERING, s)
+#define PHYS_BUGRIGS_ANGLE_SMOOTHING(s) STAT(BUGRIGS_ANGLE_SMOOTHING, s)
+#define PHYS_BUGRIGS_CAR_JUMPING(s) STAT(BUGRIGS_CAR_JUMPING, s)
+#define PHYS_BUGRIGS_FRICTION_AIR(s) STAT(BUGRIGS_FRICTION_AIR, s)
+#define PHYS_BUGRIGS_FRICTION_BRAKE(s) STAT(BUGRIGS_FRICTION_BRAKE, s)
+#define PHYS_BUGRIGS_FRICTION_FLOOR(s) STAT(BUGRIGS_FRICTION_FLOOR, s)
+#define PHYS_BUGRIGS_PLANAR_MOVEMENT(s) STAT(BUGRIGS_PLANAR_MOVEMENT, s)
+#define PHYS_BUGRIGS_REVERSE_SPEEDING(s) STAT(BUGRIGS_REVERSE_SPEEDING, s)
+#define PHYS_BUGRIGS_REVERSE_SPINNING(s) STAT(BUGRIGS_REVERSE_SPINNING, s)
+#define PHYS_BUGRIGS_REVERSE_STOPPING(s) STAT(BUGRIGS_REVERSE_STOPPING, s)
+#define PHYS_BUGRIGS_SPEED_POW(s) STAT(BUGRIGS_SPEED_POW, s)
+#define PHYS_BUGRIGS_SPEED_REF(s) STAT(BUGRIGS_SPEED_REF, s)
+#define PHYS_BUGRIGS_STEER(s) STAT(BUGRIGS_STEER, s)
+
+#if defined(SVQC)
+
+void bugrigs_SetVars()
+{
+ g_bugrigs = cvar("g_bugrigs");
+ g_bugrigs_planar_movement = cvar("g_bugrigs_planar_movement");
+ g_bugrigs_planar_movement_car_jumping = cvar("g_bugrigs_planar_movement_car_jumping");
+ g_bugrigs_reverse_spinning = cvar("g_bugrigs_reverse_spinning");
+ g_bugrigs_reverse_speeding = cvar("g_bugrigs_reverse_speeding");
+ g_bugrigs_reverse_stopping = cvar("g_bugrigs_reverse_stopping");
+ g_bugrigs_air_steering = cvar("g_bugrigs_air_steering");
+ g_bugrigs_angle_smoothing = cvar("g_bugrigs_angle_smoothing");
+ g_bugrigs_friction_floor = cvar("g_bugrigs_friction_floor");
+ g_bugrigs_friction_brake = cvar("g_bugrigs_friction_brake");
+ g_bugrigs_friction_air = cvar("g_bugrigs_friction_air");
+ g_bugrigs_accel = cvar("g_bugrigs_accel");
+ g_bugrigs_speed_ref = cvar("g_bugrigs_speed_ref");
+ g_bugrigs_speed_pow = cvar("g_bugrigs_speed_pow");
+ g_bugrigs_steer = cvar("g_bugrigs_steer");
+}
+
+#endif
+
+void RaceCarPhysics(entity this)
+{
+ // using this move type for "big rigs"
+ // the engine does not push the entity!
+
+ vector rigvel;
+
+ vector angles_save = this.angles;
+ float accel = bound(-1, this.movement.x / PHYS_MAXSPEED(this), 1);
+ float steer = bound(-1, this.movement.y / PHYS_MAXSPEED(this), 1);
+
+ if (PHYS_BUGRIGS_REVERSE_SPEEDING(this))
+ {
+ if (accel < 0)
+ {
+ // back accel is DIGITAL
+ // to prevent speedhack
+ if (accel < -0.5)
+ accel = -1;
+ else
+ accel = 0;
+ }
+ }
+
+ this.angles_x = 0;
+ this.angles_z = 0;
+ makevectors(this.angles); // new forward direction!
+
+ if (IS_ONGROUND(this) || PHYS_BUGRIGS_AIR_STEERING(this))
+ {
+ float myspeed = this.velocity * v_forward;
+ float upspeed = this.velocity * v_up;
+
+ // responsiveness factor for steering and acceleration
+ float f = 1 / (1 + pow(max(-myspeed, myspeed) / PHYS_BUGRIGS_SPEED_REF(this), PHYS_BUGRIGS_SPEED_POW(this)));
+ //MAXIMA: f(v) := 1 / (1 + (v / PHYS_BUGRIGS_SPEED_REF(this)) ^ PHYS_BUGRIGS_SPEED_POW(this));
+
+ float steerfactor;
+ if (myspeed < 0 && PHYS_BUGRIGS_REVERSE_SPINNING(this))
+ steerfactor = -myspeed * PHYS_BUGRIGS_STEER(this);
+ else
+ steerfactor = -myspeed * f * PHYS_BUGRIGS_STEER(this);
+
+ float accelfactor;
+ if (myspeed < 0 && PHYS_BUGRIGS_REVERSE_SPEEDING(this))
+ accelfactor = PHYS_BUGRIGS_ACCEL(this);
+ else
+ accelfactor = f * PHYS_BUGRIGS_ACCEL(this);
+ //MAXIMA: accel(v) := f(v) * PHYS_BUGRIGS_ACCEL(this);
+
+ if (accel < 0)
+ {
+ if (myspeed > 0)
+ {
+ myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * (PHYS_BUGRIGS_FRICTION_FLOOR(this) - PHYS_BUGRIGS_FRICTION_BRAKE(this) * accel));
+ }
+ else
+ {
+ if (!PHYS_BUGRIGS_REVERSE_SPEEDING(this))
+ myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_FRICTION_FLOOR(this));
+ }
+ }
+ else
+ {
+ if (myspeed >= 0)
+ {
+ myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_FRICTION_FLOOR(this));
+ }
+ else
+ {
+ if (PHYS_BUGRIGS_REVERSE_STOPPING(this))
+ myspeed = 0;
+ else
+ myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * (PHYS_BUGRIGS_FRICTION_FLOOR(this) + PHYS_BUGRIGS_FRICTION_BRAKE(this) * accel));
+ }
+ }
+ // terminal velocity = velocity at which 50 == accelfactor, that is, 1549 units/sec
+ //MAXIMA: friction(v) := PHYS_BUGRIGS_FRICTION_FLOOR(this);
+
+ this.angles_y += steer * PHYS_INPUT_TIMELENGTH * steerfactor; // apply steering
+ makevectors(this.angles); // new forward direction!
+
+ myspeed += accel * accelfactor * PHYS_INPUT_TIMELENGTH;
+
+ rigvel = myspeed * v_forward + '0 0 1' * upspeed;
+ }
+ else
+ {
+ float myspeed = vlen(this.velocity);
+
+ // responsiveness factor for steering and acceleration
+ float f = 1 / (1 + pow(max(0, myspeed / PHYS_BUGRIGS_SPEED_REF(this)), PHYS_BUGRIGS_SPEED_POW(this)));
+ float steerfactor = -myspeed * f;
+ this.angles_y += steer * PHYS_INPUT_TIMELENGTH * steerfactor; // apply steering
+
+ rigvel = this.velocity;
+ makevectors(this.angles); // new forward direction!
+ }
+
+ rigvel *= max(0, 1 - vlen(rigvel) * PHYS_BUGRIGS_FRICTION_AIR(this) * PHYS_INPUT_TIMELENGTH);
+ //MAXIMA: airfriction(v) := v * v * PHYS_BUGRIGS_FRICTION_AIR(this);
+ //MAXIMA: total_acceleration(v) := accel(v) - friction(v) - airfriction(v);
+ //MAXIMA: solve(total_acceleration(v) = 0, v);
+
+ if (PHYS_BUGRIGS_PLANAR_MOVEMENT(this))
+ {
+ vector rigvel_xy, neworigin, up;
+ float mt;
+
+ rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY(this); // 4x gravity plays better
+ rigvel_xy = vec2(rigvel);
+
+ if (PHYS_BUGRIGS_CAR_JUMPING(this))
+ mt = MOVE_NORMAL;
+ else
+ mt = MOVE_NOMONSTERS;
+
+ tracebox(this.origin, this.mins, this.maxs, this.origin + '0 0 1024', mt, this);
+ up = trace_endpos - this.origin;
+
+ // BUG RIGS: align the move to the surface instead of doing collision testing
+ // can we move?
+ tracebox(trace_endpos, this.mins, this.maxs, trace_endpos + rigvel_xy * PHYS_INPUT_TIMELENGTH, mt, this);
+
+ // align to surface
+ tracebox(trace_endpos, this.mins, this.maxs, trace_endpos - up + '0 0 1' * rigvel_z * PHYS_INPUT_TIMELENGTH, mt, this);
+
+ if (trace_fraction < 0.5)
+ {
+ trace_fraction = 1;
+ neworigin = this.origin;
+ }
+ else
+ neworigin = trace_endpos;
+
+ if (trace_fraction < 1)
+ {
+ // now set angles_x so that the car points parallel to the surface
+ this.angles = vectoangles(
+ '1 0 0' * v_forward_x * trace_plane_normal_z
+ +
+ '0 1 0' * v_forward_y * trace_plane_normal_z
+ +
+ '0 0 1' * -(v_forward_x * trace_plane_normal_x + v_forward_y * trace_plane_normal_y)
+ );
+ SET_ONGROUND(this);
+ }
+ else
+ {
+ // now set angles_x so that the car points forward, but is tilted in velocity direction
+ UNSET_ONGROUND(this);
+ }
+
+ this.velocity = (neworigin - this.origin) * (1.0 / PHYS_INPUT_TIMELENGTH);
+ this.movetype = MOVETYPE_NOCLIP;
+ }
+ else
+ {
+ rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY(this); // 4x gravity plays better
+ this.velocity = rigvel;
+ this.movetype = MOVETYPE_FLY;
+ }
+
+ trace_fraction = 1;
+ tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 4', MOVE_NORMAL, this);
+ if (trace_fraction != 1)
+ {
+ this.angles = vectoangles2(
+ '1 0 0' * v_forward_x * trace_plane_normal_z
+ +
+ '0 1 0' * v_forward_y * trace_plane_normal_z
+ +
+ '0 0 1' * -(v_forward_x * trace_plane_normal_x + v_forward_y * trace_plane_normal_y),
+ trace_plane_normal
+ );
+ }
+ else
+ {
+ vector vel_local;
+
+ vel_local_x = v_forward * this.velocity;
+ vel_local_y = v_right * this.velocity;
+ vel_local_z = v_up * this.velocity;
+
+ this.angles_x = racecar_angle(vel_local_x, vel_local_z);
+ this.angles_z = racecar_angle(-vel_local_y, vel_local_z);
+ }
+
+ // smooth the angles
+ vector vf1, vu1, smoothangles;
+ makevectors(this.angles);
+ float f = bound(0, PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_ANGLE_SMOOTHING(this), 1);
+ if (f == 0)
+ f = 1;
+ vf1 = v_forward * f;
+ vu1 = v_up * f;
+ makevectors(angles_save);
+ vf1 = vf1 + v_forward * (1 - f);
+ vu1 = vu1 + v_up * (1 - f);
+ smoothangles = vectoangles2(vf1, vu1);
+ this.angles_x = -smoothangles_x;
+ this.angles_z = smoothangles_z;
+
+ PM_ClientMovement_Move(this);
+}
+
+#ifdef SVQC
+.vector bugrigs_prevangles;
+#endif
+MUTATOR_HOOKFUNCTION(bugrigs, PM_Physics)
+{
+ if(!PHYS_BUGRIGS(self) || !IS_PLAYER(self)) { return false; }
+
+#ifdef SVQC
+ self.angles = self.bugrigs_prevangles;
+#endif
+
+ RaceCarPhysics(self);
+ return true;
+}
+
+MUTATOR_HOOKFUNCTION(bugrigs, PlayerPhysics)
+{
+ if(!PHYS_BUGRIGS(self)) { return false; }
+#ifdef SVQC
+ self.bugrigs_prevangles = self.angles;
+#endif
+ return false;
+}
+
+#ifdef SVQC
+
+MUTATOR_HOOKFUNCTION(bugrigs, ClientConnect)
+{
+ stuffcmd(self, "cl_cmd settemp chase_active 1\n");
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(bugrigs, BuildMutatorsString)
+{
+ ret_string = strcat(ret_string, ":bugrigs");
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(bugrigs, BuildMutatorsPrettyString)
+{
+ ret_string = strcat(ret_string, ", Bug rigs");
+ return false;
+}
+
+#endif
+#endif
--- /dev/null
+#ifndef MENUQC
+#include "bugrigs.qc"
+#endif
return false;
}
+#elif defined(CSQC)
+REGISTER_MUTATOR(dodging, true);
#endif
// set to 1 to indicate dodging has started.. reset by physics hook after dodge has been done..
#endif
// returns 1 if the player is close to a wall
-bool check_close_to_wall(float threshold)
-{SELFPARAM();
+bool check_close_to_wall(entity this, float threshold)
+{
if (PHYS_DODGING_WALL == 0) { return false; }
#define X(OFFSET) \
- tracebox(self.origin, self.mins, self.maxs, self.origin + OFFSET, true, self); \
- if (trace_fraction < 1 && vlen (self.origin - trace_endpos) < threshold) \
+ tracebox(this.origin, this.mins, this.maxs, this.origin + OFFSET, true, this); \
+ if (trace_fraction < 1 && vlen (this.origin - trace_endpos) < threshold) \
return true;
X(1000*v_right);
X(-1000*v_right);
return false;
}
-bool check_close_to_ground(float threshold)
-{SELFPARAM();
- return IS_ONGROUND(self) ? true : false;
+bool check_close_to_ground(entity this, float threshold)
+{
+ return IS_ONGROUND(this) ? true : false;
}
-float PM_dodging_checkpressedkeys()
-{SELFPARAM();
+float PM_dodging_checkpressedkeys(entity this)
+{
if(!PHYS_DODGING)
return false;
- float frozen_dodging = (PHYS_FROZEN(self) && PHYS_DODGING_FROZEN);
+ float frozen_dodging = (PHYS_FROZEN(this) && PHYS_DODGING_FROZEN);
float frozen_no_doubletap = (frozen_dodging && !PHYS_DODGING_FROZEN_NODOUBLETAP);
// first check if the last dodge is far enough back in time so we can dodge again
- if ((time - self.last_dodging_time) < PHYS_DODGING_DELAY)
+ if ((time - this.last_dodging_time) < PHYS_DODGING_DELAY)
return false;
- makevectors(self.angles);
+ makevectors(this.angles);
- if (check_close_to_ground(PHYS_DODGING_HEIGHT_THRESHOLD) != 1
- && check_close_to_wall(PHYS_DODGING_DISTANCE_THRESHOLD) != 1)
+ if (check_close_to_ground(this, PHYS_DODGING_HEIGHT_THRESHOLD) != 1
+ && check_close_to_wall(this, PHYS_DODGING_DISTANCE_THRESHOLD) != 1)
return true;
float tap_direction_x = 0;
float tap_direction_y = 0;
- float dodge_detected = 0;
+ bool dodge_detected = false;
#define X(COND,BTN,RESULT) \
- if (self.movement_##COND) \
+ if (this.movement_##COND) \
/* is this a state change? */ \
- if(!(PHYS_DODGING_PRESSED_KEYS(self) & KEY_##BTN) || frozen_no_doubletap) { \
+ if(!(PHYS_DODGING_PRESSED_KEYS(this) & KEY_##BTN) || frozen_no_doubletap) { \
tap_direction_##RESULT; \
- if ((time - self.last_##BTN##_KEY_time) < PHYS_DODGING_TIMEOUT(self)) \
- dodge_detected = 1; \
- self.last_##BTN##_KEY_time = time; \
+ if ((time - this.last_##BTN##_KEY_time) < PHYS_DODGING_TIMEOUT(this)) \
+ dodge_detected = true; \
+ this.last_##BTN##_KEY_time = time; \
}
X(x < 0, BACKWARD, x--);
X(x > 0, FORWARD, x++);
X(y > 0, RIGHT, y++);
#undef X
- if (dodge_detected == 1)
+ if (dodge_detected)
{
- self.last_dodging_time = time;
+ this.last_dodging_time = time;
- self.dodging_action = 1;
- self.dodging_single_action = 1;
+ this.dodging_action = 1;
+ this.dodging_single_action = 1;
- self.dodging_velocity_gain = PHYS_DODGING_HORIZ_SPEED;
+ this.dodging_velocity_gain = PHYS_DODGING_HORIZ_SPEED;
- self.dodging_direction_x = tap_direction_x;
- self.dodging_direction_y = tap_direction_y;
+ this.dodging_direction_x = tap_direction_x;
+ this.dodging_direction_y = tap_direction_y;
// normalize the dodging_direction vector.. (unlike UT99) XD
- float length = self.dodging_direction_x * self.dodging_direction_x
- + self.dodging_direction_y * self.dodging_direction_y;
+ float length = this.dodging_direction_x * this.dodging_direction_x
+ + this.dodging_direction_y * this.dodging_direction_y;
length = sqrt(length);
- self.dodging_direction_x = self.dodging_direction_x * 1.0 / length;
- self.dodging_direction_y = self.dodging_direction_y * 1.0 / length;
+ this.dodging_direction_x = this.dodging_direction_x * 1.0 / length;
+ this.dodging_direction_y = this.dodging_direction_y * 1.0 / length;
return true;
}
return false;
}
-void PM_dodging()
-{SELFPARAM();
+void PM_dodging(entity this)
+{
if (!PHYS_DODGING)
return;
- if (PHYS_DEAD(self))
+ if (PHYS_DEAD(this))
return;
// when swimming, no dodging allowed..
- if (self.waterlevel >= WATERLEVEL_SWIMMING)
+ if (this.waterlevel >= WATERLEVEL_SWIMMING)
{
- self.dodging_action = 0;
- self.dodging_direction_x = 0;
- self.dodging_direction_y = 0;
+ this.dodging_action = 0;
+ this.dodging_direction_x = 0;
+ this.dodging_direction_y = 0;
return;
}
// make sure v_up, v_right and v_forward are sane
- makevectors(self.angles);
+ makevectors(this.angles);
// if we have e.g. 0.5 sec ramptime and a frametime of 0.25, then the ramp code
// will be called ramp_time/frametime times = 2 times. so, we need to
// if ramp time is smaller than frametime we get problems ;D
common_factor = min(common_factor, 1);
- float horiz_speed = PHYS_FROZEN(self) ? PHYS_DODGING_HORIZ_SPEED_FROZEN : PHYS_DODGING_HORIZ_SPEED;
- float new_velocity_gain = self.dodging_velocity_gain - (common_factor * horiz_speed);
+ float horiz_speed = PHYS_FROZEN(this) ? PHYS_DODGING_HORIZ_SPEED_FROZEN : PHYS_DODGING_HORIZ_SPEED;
+ float new_velocity_gain = this.dodging_velocity_gain - (common_factor * horiz_speed);
new_velocity_gain = max(0, new_velocity_gain);
- float velocity_difference = self.dodging_velocity_gain - new_velocity_gain;
+ float velocity_difference = this.dodging_velocity_gain - new_velocity_gain;
// ramp up dodging speed by adding some velocity each frame.. TODO: do it! :D
- if (self.dodging_action == 1)
+ if (this.dodging_action == 1)
{
//disable jump key during dodge accel phase
- if(self.movement_z > 0) { self.movement_z = 0; }
+ if(this.movement_z > 0) { this.movement_z = 0; }
- self.velocity += ((self.dodging_direction_y * velocity_difference) * v_right)
- + ((self.dodging_direction_x * velocity_difference) * v_forward);
+ this.velocity += ((this.dodging_direction_y * velocity_difference) * v_right)
+ + ((this.dodging_direction_x * velocity_difference) * v_forward);
- self.dodging_velocity_gain = self.dodging_velocity_gain - velocity_difference;
+ this.dodging_velocity_gain = this.dodging_velocity_gain - velocity_difference;
}
// the up part of the dodge is a single shot action
- if (self.dodging_single_action == 1)
+ if (this.dodging_single_action == 1)
{
- UNSET_ONGROUND(self);
+ UNSET_ONGROUND(this);
- self.velocity += PHYS_DODGING_UP_SPEED * v_up;
+ this.velocity += PHYS_DODGING_UP_SPEED * v_up;
#ifdef SVQC
if (autocvar_sv_dodging_sound)
PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND);
- animdecide_setaction(self, ANIMACTION_JUMP, true);
+ animdecide_setaction(this, ANIMACTION_JUMP, true);
#endif
- self.dodging_single_action = 0;
+ this.dodging_single_action = 0;
}
// are we done with the dodging ramp yet?
- if((self.dodging_action == 1) && ((time - self.last_dodging_time) > PHYS_DODGING_RAMP_TIME))
+ if((this.dodging_action == 1) && ((time - this.last_dodging_time) > PHYS_DODGING_RAMP_TIME))
{
// reset state so next dodge can be done correctly
- self.dodging_action = 0;
- self.dodging_direction_x = 0;
- self.dodging_direction_y = 0;
+ this.dodging_action = 0;
+ this.dodging_direction_x = 0;
+ this.dodging_direction_y = 0;
}
}
-#ifdef SVQC
-
-MUTATOR_HOOKFUNCTION(dodging, GetCvars)
+void PM_dodging_GetPressedKeys(entity this)
{
- GetCvars_handleFloat(get_cvars_s, get_cvars_f, cvar_cl_dodging_timeout, "cl_dodging_timeout");
- return false;
+#ifdef CSQC
+ if(!PHYS_DODGING) { return; }
+
+ PM_dodging_checkpressedkeys(this);
+
+ int keys = this.pressedkeys;
+ keys = BITSET(keys, KEY_FORWARD, this.movement.x > 0);
+ keys = BITSET(keys, KEY_BACKWARD, this.movement.x < 0);
+ keys = BITSET(keys, KEY_RIGHT, this.movement.y > 0);
+ keys = BITSET(keys, KEY_LEFT, this.movement.y < 0);
+
+ keys = BITSET(keys, KEY_JUMP, PHYS_INPUT_BUTTON_JUMP(this));
+ keys = BITSET(keys, KEY_CROUCH, PHYS_INPUT_BUTTON_CROUCH(this));
+ keys = BITSET(keys, KEY_ATCK, PHYS_INPUT_BUTTON_ATCK(this));
+ keys = BITSET(keys, KEY_ATCK2, PHYS_INPUT_BUTTON_ATCK2(this));
+ this.pressedkeys = keys;
+#endif
}
MUTATOR_HOOKFUNCTION(dodging, PlayerPhysics)
{
// print("dodging_PlayerPhysics\n");
- PM_dodging();
+ PM_dodging_GetPressedKeys(self);
+ PM_dodging(self);
+ return false;
+}
+
+#ifdef SVQC
+MUTATOR_HOOKFUNCTION(dodging, GetCvars)
+{
+ GetCvars_handleFloat(get_cvars_s, get_cvars_f, cvar_cl_dodging_timeout, "cl_dodging_timeout");
return false;
}
MUTATOR_HOOKFUNCTION(dodging, GetPressedKeys)
{
- PM_dodging_checkpressedkeys();
-
+ PM_dodging_checkpressedkeys(self);
return false;
}
#endif
-
#endif
#ifdef SVQC
-#include "dodging.qc"
+ #include "dodging.qc"
#endif
--- /dev/null
+#ifdef IMPLEMENTATION
+#ifdef SVQC
+ #include "../../../../server/antilag.qh"
+#endif
+#include "../../../physics.qh"
+
+REGISTER_MUTATOR(doublejump, true);
+
+#define PHYS_DOUBLEJUMP(s) STAT(DOUBLEJUMP, s)
+
+
+MUTATOR_HOOKFUNCTION(doublejump, PlayerJump)
+{
+ if (PHYS_DOUBLEJUMP(self))
+ {
+ tracebox(self.origin + '0 0 0.01', self.mins, self.maxs, self.origin - '0 0 0.01', MOVE_NORMAL, self);
+ if (trace_fraction < 1 && trace_plane_normal_z > 0.7)
+ {
+ player_multijump = true;
+
+ // we MUST clip velocity here!
+ float f = self.velocity * trace_plane_normal;
+ if (f < 0)
+ self.velocity -= f * trace_plane_normal;
+ }
+ }
+ return false;
+}
+
+#ifdef SVQC
+
+MUTATOR_HOOKFUNCTION(doublejump, BuildMutatorsString)
+{
+ ret_string = strcat(ret_string, ":doublejump");
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(doublejump, BuildMutatorsPrettyString)
+{
+ ret_string = strcat(ret_string, ", Double jump");
+ return false;
+}
+
+#endif
+#endif
--- /dev/null
+#ifndef MENUQC
+#include "doublejump.qc"
+#endif
#endif
#include "../../../physics.qh"
-.int multijump_count;
-.bool multijump_ready;
-.bool cvar_cl_multijump;
+
+#if defined(SVQC)
+REGISTER_MUTATOR(multijump, cvar("g_multijump"))
+{
+ MUTATOR_ONADD
+ {
+ addstat(STAT_MULTIJUMP_COUNT.m_id, AS_INT, multijump_count);
+ }
+}
+#elif defined(CSQC)
+REGISTER_MUTATOR(multijump, true);
+#endif
#define PHYS_MULTIJUMP STAT(MULTIJUMP, self)
#define PHYS_MULTIJUMP_SPEED STAT(MULTIJUMP_SPEED, self)
#define PHYS_MULTIJUMP_ADD STAT(MULTIJUMP_ADD, self)
#define PHYS_MULTIJUMP_MAXSPEED STAT(MULTIJUMP_MAXSPEED, self)
#define PHYS_MULTIJUMP_DODGING STAT(MULTIJUMP_DODGING, self)
+#define PHYS_MULTIJUMP_COUNT(s) STAT(MULTIJUMP_COUNT, s)
-void PM_multijump()
-{SELFPARAM();
- if(!PHYS_MULTIJUMP) { return; }
+.bool multijump_ready;
- if(IS_ONGROUND(self))
- {
- self.multijump_count = 0;
- }
-}
+#ifdef CSQC
+bool autocvar_cl_multijump = false;
-bool PM_multijump_checkjump()
-{SELFPARAM();
- if(!PHYS_MULTIJUMP) { return false; }
+ #define PHYS_MULTIJUMP_CLIENT(s) autocvar_cl_multijump
+#elif defined(SVQC)
+.bool cvar_cl_multijump;
-#ifdef SVQC
- bool client_multijump = self.cvar_cl_multijump;
-#elif defined(CSQC)
- bool client_multijump = cvar("cl_multijump");
+ #define PHYS_MULTIJUMP_CLIENT(s) (s).cvar_cl_multijump
+#endif
+
+bool PM_multijump_checkjump(entity this)
+{
+ if(!PHYS_MULTIJUMP) { return false; }
- if(cvar("cl_multijump") > 1)
+ int client_multijump = PHYS_MULTIJUMP_CLIENT(this);
+ if(client_multijump > 1)
return false; // nope
-#endif
- if (!IS_JUMP_HELD(self) && !IS_ONGROUND(self) && client_multijump) // jump button pressed this frame and we are in midair
- self.multijump_ready = true; // this is necessary to check that we released the jump button and pressed it again
+ if (!IS_JUMP_HELD(this) && !IS_ONGROUND(this) && client_multijump) // jump button pressed this frame and we are in midair
+ this.multijump_ready = true; // this is necessary to check that we released the jump button and pressed it again
else
- self.multijump_ready = false;
+ this.multijump_ready = false;
int phys_multijump = PHYS_MULTIJUMP;
-#ifdef CSQC
- phys_multijump = (PHYS_MULTIJUMP) ? -1 : 0;
-#endif
-
- if(!player_multijump && self.multijump_ready && (self.multijump_count < phys_multijump || phys_multijump == -1) && self.velocity_z > PHYS_MULTIJUMP_SPEED && (!PHYS_MULTIJUMP_MAXSPEED || vlen(self.velocity) <= PHYS_MULTIJUMP_MAXSPEED))
+ if(!player_multijump && this.multijump_ready && (PHYS_MULTIJUMP_COUNT(this) < phys_multijump || phys_multijump == -1) && this.velocity_z > PHYS_MULTIJUMP_SPEED && (!PHYS_MULTIJUMP_MAXSPEED || vlen(this.velocity) <= PHYS_MULTIJUMP_MAXSPEED))
{
if (PHYS_MULTIJUMP)
{
if (!PHYS_MULTIJUMP_ADD) // in this case we make the z velocity == jumpvelocity
{
- if (self.velocity_z < PHYS_JUMPVELOCITY)
+ if (this.velocity_z < PHYS_JUMPVELOCITY(this))
{
player_multijump = true;
- self.velocity_z = 0;
+ this.velocity_z = 0;
}
}
else
if(player_multijump)
{
if(PHYS_MULTIJUMP_DODGING)
- if(self.movement_x != 0 || self.movement_y != 0) // don't remove all speed if player isnt pressing any movement keys
+ if(this.movement_x != 0 || this.movement_y != 0) // don't remove all speed if player isnt pressing any movement keys
{
float curspeed;
vector wishvel, wishdir;
/*#ifdef SVQC
curspeed = max(
- vlen(vec2(self.velocity)), // current xy speed
- vlen(vec2(antilag_takebackavgvelocity(self, max(self.lastteleporttime + sys_frametime, time - 0.25), time))) // average xy topspeed over the last 0.25 secs
+ vlen(vec2(this.velocity)), // current xy speed
+ vlen(vec2(antilag_takebackavgvelocity(this, max(this.lastteleporttime + sys_frametime, time - 0.25), time))) // average xy topspeed over the last 0.25 secs
);
#elif defined(CSQC)*/
- curspeed = vlen(vec2(self.velocity));
+ curspeed = vlen(vec2(this.velocity));
//#endif
- makevectors(self.v_angle_y * '0 1 0');
- wishvel = v_forward * self.movement_x + v_right * self.movement_y;
+ makevectors(this.v_angle_y * '0 1 0');
+ wishvel = v_forward * this.movement_x + v_right * this.movement_y;
wishdir = normalize(wishvel);
- self.velocity_x = wishdir_x * curspeed; // allow "dodging" at a multijump
- self.velocity_y = wishdir_y * curspeed;
+ this.velocity_x = wishdir_x * curspeed; // allow "dodging" at a multijump
+ this.velocity_y = wishdir_y * curspeed;
// keep velocity_z unchanged!
}
if (PHYS_MULTIJUMP > 0)
{
- self.multijump_count += 1;
+ this.multijump_count += 1;
}
}
}
- self.multijump_ready = false; // require releasing and pressing the jump button again for the next jump
+ this.multijump_ready = false; // require releasing and pressing the jump button again for the next jump
}
return false;
}
-#ifdef SVQC
-REGISTER_MUTATOR(multijump, cvar("g_multijump"));
-
MUTATOR_HOOKFUNCTION(multijump, PlayerPhysics)
{
- PM_multijump();
+#ifdef CSQC
+ self.multijump_count = PHYS_MULTIJUMP_COUNT(self);
+#endif
+ if(!PHYS_MULTIJUMP) { return; }
+ if(IS_ONGROUND(self))
+ self.multijump_count = 0;
return false;
}
MUTATOR_HOOKFUNCTION(multijump, PlayerJump)
{
- return PM_multijump_checkjump();
+ return PM_multijump_checkjump(self);
}
+#ifdef SVQC
+
MUTATOR_HOOKFUNCTION(multijump, GetCvars)
{
GetCvars_handleFloat(get_cvars_s, get_cvars_f, cvar_cl_multijump, "cl_multijump");
ret_string = strcat(ret_string, ", Nades");
return false;
}
+
+MUTATOR_HOOKFUNCTION(nades, BuildGameplayTipsString)
+{
+ ret_string = strcat(ret_string, "\n\n^3nades^8 are enabled, press 'g' to use them\n");
+ return false;
+}
+
#endif
#endif
return autocvar_g_physics_clientselect && strhasword(autocvar_g_physics_clientselect_options, thecvar);
}
-float Physics_ClientOption(entity pl, string option)
+float Physics_ClientOption(entity this, string option)
{
- if(Physics_Valid(pl.cvar_cl_physics))
+ if(Physics_Valid(this.cvar_cl_physics))
{
- string s = sprintf("g_physics_%s_%s", pl.cvar_cl_physics, option);
+ string s = sprintf("g_physics_%s_%s", this.cvar_cl_physics, option);
if(cvar_type(s) & CVAR_TYPEFLAG_EXISTS)
return cvar(s);
}
pmove_waterjumptime = 0;
}
-void PM_ClientMovement_Move()
-{SELFPARAM();
+void PM_ClientMovement_Move(entity this)
+{
#ifdef CSQC
+
+ PM_ClientMovement_UpdateStatus(this, false);
+ if(autocvar_cl_movement == 3)
+ return;
+
int bump;
float t;
float f;
vector trace2_plane_normal = '0 0 0';
vector trace3_plane_normal = '0 0 0';
-
- PM_ClientMovement_UpdateStatus(this, false);
- primalvelocity = self.velocity;
- for(bump = 0, t = PHYS_INPUT_TIMELENGTH; bump < 8 && (self.velocity * self.velocity) > 0; bump++)
+ primalvelocity = this.velocity;
+ for(bump = 0, t = PHYS_INPUT_TIMELENGTH; bump < 8 && (this.velocity * this.velocity) > 0; bump++)
{
- neworigin = self.origin + t * self.velocity;
- tracebox(self.origin, self.mins, self.maxs, neworigin, MOVE_NORMAL, self);
+ neworigin = this.origin + t * this.velocity;
+ tracebox(this.origin, this.mins, this.maxs, neworigin, MOVE_NORMAL, this);
trace1_endpos = trace_endpos;
trace1_fraction = trace_fraction;
trace1_plane_normal = trace_plane_normal;
{
// may be a step or wall, try stepping up
// first move forward at a higher level
- currentorigin2 = self.origin;
+ currentorigin2 = this.origin;
currentorigin2_z += PHYS_STEPHEIGHT;
neworigin2 = neworigin;
neworigin2_z += PHYS_STEPHEIGHT;
- tracebox(currentorigin2, self.mins, self.maxs, neworigin2, MOVE_NORMAL, self);
+ tracebox(currentorigin2, this.mins, this.maxs, neworigin2, MOVE_NORMAL, this);
trace2_endpos = trace_endpos;
trace2_fraction = trace_fraction;
trace2_plane_normal = trace_plane_normal;
// then move down from there
currentorigin2 = trace2_endpos;
neworigin2 = trace2_endpos;
- neworigin2_z = self.origin_z;
- tracebox(currentorigin2, self.mins, self.maxs, neworigin2, MOVE_NORMAL, self);
+ neworigin2_z = this.origin_z;
+ tracebox(currentorigin2, this.mins, this.maxs, neworigin2, MOVE_NORMAL, this);
trace3_endpos = trace_endpos;
trace3_fraction = trace_fraction;
trace3_plane_normal = trace_plane_normal;
// check if it moved at all
if(trace1_fraction >= 0.001)
- setorigin(self, trace1_endpos);
+ setorigin(this, trace1_endpos);
// check if it moved all the way
if(trace1_fraction == 1)
// this got commented out in a change that supposedly makes the code match QW better
// so if this is broken, maybe put it in an if(cls.protocol != PROTOCOL_QUAKEWORLD) block
if(trace1_plane_normal_z > 0.7)
- SET_ONGROUND(self);
+ SET_ONGROUND(this);
t -= t * trace1_fraction;
- f = (self.velocity * trace1_plane_normal);
- self.velocity = self.velocity + -f * trace1_plane_normal;
+ f = (this.velocity * trace1_plane_normal);
+ this.velocity = this.velocity + -f * trace1_plane_normal;
}
if(pmove_waterjumptime > 0)
- self.velocity = primalvelocity;
+ this.velocity = primalvelocity;
#endif
}
-void CPM_PM_Aircontrol(vector wishdir, float wishspeed)
-{SELFPARAM();
- float k = 32 * (2 * IsMoveInDirection(self.movement, 0) - 1);
+void CPM_PM_Aircontrol(entity this, vector wishdir, float wishspeed)
+{
+ float k = 32 * (2 * IsMoveInDirection(this.movement, 0) - 1);
if (k <= 0)
return;
- k *= bound(0, wishspeed / PHYS_MAXAIRSPEED(self), 1);
+ k *= bound(0, wishspeed / PHYS_MAXAIRSPEED(this), 1);
- float zspeed = self.velocity_z;
- self.velocity_z = 0;
- float xyspeed = vlen(self.velocity);
- self.velocity = normalize(self.velocity);
+ float zspeed = this.velocity_z;
+ this.velocity_z = 0;
+ float xyspeed = vlen(this.velocity);
+ this.velocity = normalize(this.velocity);
- float dot = self.velocity * wishdir;
+ float dot = this.velocity * wishdir;
if (dot > 0) // we can't change direction while slowing down
{
- k *= pow(dot, PHYS_AIRCONTROL_POWER) * PHYS_INPUT_TIMELENGTH;
- xyspeed = max(0, xyspeed - PHYS_AIRCONTROL_PENALTY * sqrt(max(0, 1 - dot*dot)) * k/32);
- k *= PHYS_AIRCONTROL;
- self.velocity = normalize(self.velocity * xyspeed + wishdir * k);
+ k *= pow(dot, PHYS_AIRCONTROL_POWER(this)) * PHYS_INPUT_TIMELENGTH;
+ xyspeed = max(0, xyspeed - PHYS_AIRCONTROL_PENALTY(this) * sqrt(max(0, 1 - dot*dot)) * k/32);
+ k *= PHYS_AIRCONTROL(this);
+ this.velocity = normalize(this.velocity * xyspeed + wishdir * k);
}
- self.velocity = self.velocity * xyspeed;
- self.velocity_z = zspeed;
+ this.velocity = this.velocity * xyspeed;
+ this.velocity_z = zspeed;
}
float AdjustAirAccelQW(float accelqw, float factor)
// sv_airaccel_sideways_friction 0
// prvm_globalset server speedclamp_mode 1
// (or 2)
-void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit)
-{SELFPARAM();
+void PM_Accelerate(entity this, vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit)
+{
float speedclamp = stretchfactor > 0 ? stretchfactor
: accelqw < 0 ? 1 // full clamping, no stretch
: -1; // no clamping
if (GAMEPLAYFIX_Q2AIRACCELERATE)
wishspeed0 = wishspeed; // don't need to emulate this Q1 bug
- float vel_straight = self.velocity * wishdir;
- float vel_z = self.velocity_z;
- vector vel_xy = vec2(self.velocity);
+ float vel_straight = this.velocity * wishdir;
+ float vel_z = this.velocity_z;
+ vector vel_xy = vec2(this.velocity);
vector vel_perpend = vel_xy - vel_straight * wishdir;
float step = accel * PHYS_INPUT_TIMELENGTH * wishspeed0;
// negative: only apply so much sideways friction to stay below the speed you could get by "braking"
{
float f = max(0, 1 + PHYS_INPUT_TIMELENGTH * wishspeed * sidefric);
- float fmin = (vel_xy_backward * vel_xy_backward - vel_straight * vel_straight) / (vel_perpend * vel_perpend);
- // assume: fmin > 1
+ float themin = (vel_xy_backward * vel_xy_backward - vel_straight * vel_straight) / (vel_perpend * vel_perpend);
+ // assume: themin > 1
// vel_xy_backward*vel_xy_backward - vel_straight*vel_straight > vel_perpend*vel_perpend
// vel_xy_backward*vel_xy_backward > vel_straight*vel_straight + vel_perpend*vel_perpend
// vel_xy_backward*vel_xy_backward > vel_xy * vel_xy
// obviously, this cannot be
- if (fmin <= 0)
+ if (themin <= 0)
vel_perpend *= f;
else
{
- fmin = sqrt(fmin);
- vel_perpend *= max(fmin, f);
+ themin = sqrt(themin);
+ vel_perpend *= max(themin, f);
}
}
else
}
}
- self.velocity = vel_xy + vel_z * '0 0 1';
+ this.velocity = vel_xy + vel_z * '0 0 1';
}
-void PM_AirAccelerate(vector wishdir, float wishspeed)
-{SELFPARAM();
+void PM_AirAccelerate(entity this, vector wishdir, float wishspeed)
+{
if (wishspeed == 0)
return;
- vector curvel = self.velocity;
+ vector curvel = this.velocity;
curvel_z = 0;
float curspeed = vlen(curvel);
if (wishspeed > curspeed * 1.01)
- wishspeed = min(wishspeed, curspeed + PHYS_WARSOWBUNNY_AIRFORWARDACCEL * PHYS_MAXSPEED(self) * PHYS_INPUT_TIMELENGTH);
+ wishspeed = min(wishspeed, curspeed + PHYS_WARSOWBUNNY_AIRFORWARDACCEL(this) * PHYS_MAXSPEED(this) * PHYS_INPUT_TIMELENGTH);
else
{
- float f = max(0, (PHYS_WARSOWBUNNY_TOPSPEED - curspeed) / (PHYS_WARSOWBUNNY_TOPSPEED - PHYS_MAXSPEED(self)));
- wishspeed = max(curspeed, PHYS_MAXSPEED(self)) + PHYS_WARSOWBUNNY_ACCEL * f * PHYS_MAXSPEED(self) * PHYS_INPUT_TIMELENGTH;
+ float f = max(0, (PHYS_WARSOWBUNNY_TOPSPEED(this) - curspeed) / (PHYS_WARSOWBUNNY_TOPSPEED(this) - PHYS_MAXSPEED(this)));
+ wishspeed = max(curspeed, PHYS_MAXSPEED(this)) + PHYS_WARSOWBUNNY_ACCEL(this) * f * PHYS_MAXSPEED(this) * PHYS_INPUT_TIMELENGTH;
}
vector wishvel = wishdir * wishspeed;
vector acceldir = wishvel - curvel;
float addspeed = vlen(acceldir);
acceldir = normalize(acceldir);
- float accelspeed = min(addspeed, PHYS_WARSOWBUNNY_TURNACCEL * PHYS_MAXSPEED(self) * PHYS_INPUT_TIMELENGTH);
+ float accelspeed = min(addspeed, PHYS_WARSOWBUNNY_TURNACCEL(this) * PHYS_MAXSPEED(this) * PHYS_INPUT_TIMELENGTH);
- if (PHYS_WARSOWBUNNY_BACKTOSIDERATIO < 1)
+ if (PHYS_WARSOWBUNNY_BACKTOSIDERATIO(this) < 1)
{
vector curdir = normalize(curvel);
float dot = acceldir * curdir;
if (dot < 0)
- acceldir -= (1 - PHYS_WARSOWBUNNY_BACKTOSIDERATIO) * dot * curdir;
+ acceldir -= (1 - PHYS_WARSOWBUNNY_BACKTOSIDERATIO(this)) * dot * curdir;
}
- self.velocity += accelspeed * acceldir;
+ this.velocity += accelspeed * acceldir;
}
returns true if handled
=============
*/
-bool PlayerJump ()
-{SELFPARAM();
- if (PHYS_FROZEN(self))
+bool PlayerJump(entity this)
+{
+ if (PHYS_FROZEN(this))
return true; // no jumping in freezetag when frozen
#ifdef SVQC
- if (self.player_blocked)
+ if (this.player_blocked)
return true; // no jumping while blocked
#endif
bool doublejump = false;
- float mjumpheight = PHYS_JUMPVELOCITY;
-#ifdef CSQC
- player_multijump = doublejump;
- player_jumpheight = mjumpheight;
-#endif
+ float mjumpheight = PHYS_JUMPVELOCITY(this);
- if (MUTATOR_CALLHOOK(PlayerJump, doublejump, mjumpheight)
-#ifdef CSQC
- || PM_multijump_checkjump()
-#endif
- ) { return true; }
+ if (MUTATOR_CALLHOOK(PlayerJump, this, doublejump, mjumpheight))
+ return true;
doublejump = player_multijump;
mjumpheight = player_jumpheight;
- if (PHYS_DOUBLEJUMP)
- {
- tracebox(self.origin + '0 0 0.01', self.mins, self.maxs, self.origin - '0 0 0.01', MOVE_NORMAL, self);
- if (trace_fraction < 1 && trace_plane_normal_z > 0.7)
- {
- doublejump = true;
-
- // we MUST clip velocity here!
- float f;
- f = self.velocity * trace_plane_normal;
- if (f < 0)
- self.velocity -= f * trace_plane_normal;
- }
- }
-
- if (self.waterlevel >= WATERLEVEL_SWIMMING)
+ if (this.waterlevel >= WATERLEVEL_SWIMMING)
{
- self.velocity_z = PHYS_MAXSPEED(self) * 0.7;
+ this.velocity_z = PHYS_MAXSPEED(this) * 0.7;
return true;
}
if (!doublejump)
- if (!IS_ONGROUND(self))
- return IS_JUMP_HELD(self);
+ if (!IS_ONGROUND(this))
+ return IS_JUMP_HELD(this);
- bool track_jump = PHYS_CL_TRACK_CANJUMP(self);
- if(PHYS_TRACK_CANJUMP(self))
+ bool track_jump = PHYS_CL_TRACK_CANJUMP(this);
+ if(PHYS_TRACK_CANJUMP(this))
track_jump = true;
if (track_jump)
- if (IS_JUMP_HELD(self))
+ if (IS_JUMP_HELD(this))
return true;
// sv_jumpspeedcap_min/sv_jumpspeedcap_max act as baseline
{
float minjumpspeed = mjumpheight * stof(PHYS_JUMPSPEEDCAP_MIN);
- if (self.velocity_z < minjumpspeed)
- mjumpheight += minjumpspeed - self.velocity_z;
+ if (this.velocity_z < minjumpspeed)
+ mjumpheight += minjumpspeed - this.velocity_z;
}
if(PHYS_JUMPSPEEDCAP_MAX != "")
{
// don't do jump speedcaps on ramps to preserve old xonotic ramjump style
- tracebox(self.origin + '0 0 0.01', self.mins, self.maxs, self.origin - '0 0 0.01', MOVE_NORMAL, self);
+ tracebox(this.origin + '0 0 0.01', this.mins, this.maxs, this.origin - '0 0 0.01', MOVE_NORMAL, this);
if (!(trace_fraction < 1 && trace_plane_normal_z < 0.98 && PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS))
{
float maxjumpspeed = mjumpheight * stof(PHYS_JUMPSPEEDCAP_MAX);
- if (self.velocity_z > maxjumpspeed)
- mjumpheight -= self.velocity_z - maxjumpspeed;
+ if (this.velocity_z > maxjumpspeed)
+ mjumpheight -= this.velocity_z - maxjumpspeed;
}
}
- if (!WAS_ONGROUND(self))
+ if (!WAS_ONGROUND(this))
{
#ifdef SVQC
if(autocvar_speedmeter)
- LOG_TRACE(strcat("landing velocity: ", vtos(self.velocity), " (abs: ", ftos(vlen(self.velocity)), ")\n"));
+ LOG_TRACE(strcat("landing velocity: ", vtos(this.velocity), " (abs: ", ftos(vlen(this.velocity)), ")\n"));
#endif
- if(self.lastground < time - 0.3)
+ if(this.lastground < time - 0.3)
{
- self.velocity_x *= (1 - PHYS_FRICTION_ONLAND);
- self.velocity_y *= (1 - PHYS_FRICTION_ONLAND);
+ this.velocity_x *= (1 - PHYS_FRICTION_ONLAND);
+ this.velocity_y *= (1 - PHYS_FRICTION_ONLAND);
}
#ifdef SVQC
- if(self.jumppadcount > 1)
- LOG_TRACE(strcat(ftos(self.jumppadcount), "x jumppad combo\n"));
- self.jumppadcount = 0;
+ if(this.jumppadcount > 1)
+ LOG_TRACE(strcat(ftos(this.jumppadcount), "x jumppad combo\n"));
+ this.jumppadcount = 0;
#endif
}
- self.velocity_z += mjumpheight;
+ this.velocity_z += mjumpheight;
- UNSET_ONGROUND(self);
- SET_JUMP_HELD(self);
+ UNSET_ONGROUND(this);
+ SET_JUMP_HELD(this);
#ifdef SVQC
- self.oldvelocity_z = self.velocity_z;
+ this.oldvelocity_z = this.velocity_z;
- animdecide_setaction(self, ANIMACTION_JUMP, true);
+ animdecide_setaction(this, ANIMACTION_JUMP, true);
if (autocvar_g_jump_grunt)
- PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+ WITH(entity, this, this, PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND));
#endif
return true;
}
-void CheckWaterJump()
-{SELFPARAM();
+void CheckWaterJump(entity this)
+{
// check for a jump-out-of-water
- makevectors(self.v_angle);
- vector start = self.origin;
+ makevectors(this.v_angle);
+ vector start = this.origin;
start_z += 8;
v_forward_z = 0;
normalize(v_forward);
vector end = start + v_forward*24;
- traceline (start, end, true, self);
+ traceline (start, end, true, this);
if (trace_fraction < 1)
{ // solid at waist
- start_z = start_z + self.maxs_z - 8;
+ start_z = start_z + this.maxs_z - 8;
end = start + v_forward*24;
- self.movedir = trace_plane_normal * -50;
- traceline(start, end, true, self);
+ this.movedir = trace_plane_normal * -50;
+ traceline(start, end, true, this);
if (trace_fraction == 1)
{ // open at eye level
- self.velocity_z = 225;
- self.flags |= FL_WATERJUMP;
- SET_JUMP_HELD(self);
+ this.velocity_z = 225;
+ this.flags |= FL_WATERJUMP;
+ SET_JUMP_HELD(this);
#ifdef SVQC
- self.teleport_time = time + 2; // safety net
+ this.teleport_time = time + 2; // safety net
#elif defined(CSQC)
pmove_waterjumptime = time + 2;
#endif
#define JETPACK_JUMP(s) autocvar_cl_jetpack_jump
#endif
.float jetpack_stopped;
-// Hack: shouldn't need to know about this
-.float multijump_count;
-void CheckPlayerJump()
-{SELFPARAM();
+void CheckPlayerJump(entity this)
+{
#ifdef SVQC
- float was_flying = ITEMS_STAT(self) & IT_USING_JETPACK;
+ float was_flying = ITEMS_STAT(this) & IT_USING_JETPACK;
#endif
- if (JETPACK_JUMP(self) < 2)
- ITEMS_STAT(self) &= ~IT_USING_JETPACK;
+ if (JETPACK_JUMP(this) < 2)
+ ITEMS_STAT(this) &= ~IT_USING_JETPACK;
- if(PHYS_INPUT_BUTTON_JUMP(self) || PHYS_INPUT_BUTTON_JETPACK(self))
+ if(PHYS_INPUT_BUTTON_JUMP(this) || PHYS_INPUT_BUTTON_JETPACK(this))
{
- float air_jump = !PlayerJump() || self.multijump_count > 0; // PlayerJump() has important side effects
- float activate = JETPACK_JUMP(self) && air_jump && PHYS_INPUT_BUTTON_JUMP(self) || PHYS_INPUT_BUTTON_JETPACK(self);
- float has_fuel = !PHYS_JETPACK_FUEL || PHYS_AMMO_FUEL(self) || ITEMS_STAT(self) & IT_UNLIMITED_WEAPON_AMMO;
+ float air_jump = !PlayerJump(this) || player_multijump; // PlayerJump() has important side effects
+ float activate = JETPACK_JUMP(this) && air_jump && PHYS_INPUT_BUTTON_JUMP(this) || PHYS_INPUT_BUTTON_JETPACK(this);
+ float has_fuel = !PHYS_JETPACK_FUEL || PHYS_AMMO_FUEL(this) || ITEMS_STAT(this) & IT_UNLIMITED_WEAPON_AMMO;
- if (!(ITEMS_STAT(self) & ITEM_Jetpack.m_itemid)) { }
- else if (self.jetpack_stopped) { }
+ if (!(ITEMS_STAT(this) & ITEM_Jetpack.m_itemid)) { }
+ else if (this.jetpack_stopped) { }
else if (!has_fuel)
{
#ifdef SVQC
if (was_flying) // TODO: ran out of fuel message
- Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_JETPACK_NOFUEL);
+ Send_Notification(NOTIF_ONE, this, MSG_INFO, INFO_JETPACK_NOFUEL);
else if (activate)
- Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_JETPACK_NOFUEL);
+ Send_Notification(NOTIF_ONE, this, MSG_INFO, INFO_JETPACK_NOFUEL);
#endif
- self.jetpack_stopped = true;
- ITEMS_STAT(self) &= ~IT_USING_JETPACK;
+ this.jetpack_stopped = true;
+ ITEMS_STAT(this) &= ~IT_USING_JETPACK;
}
- else if (activate && !PHYS_FROZEN(self))
- ITEMS_STAT(self) |= IT_USING_JETPACK;
+ else if (activate && !PHYS_FROZEN(this))
+ ITEMS_STAT(this) |= IT_USING_JETPACK;
}
else
{
- self.jetpack_stopped = false;
- ITEMS_STAT(self) &= ~IT_USING_JETPACK;
+ this.jetpack_stopped = false;
+ ITEMS_STAT(this) &= ~IT_USING_JETPACK;
}
- if (!PHYS_INPUT_BUTTON_JUMP(self))
- UNSET_JUMP_HELD(self);
+ if (!PHYS_INPUT_BUTTON_JUMP(this))
+ UNSET_JUMP_HELD(this);
- if (self.waterlevel == WATERLEVEL_SWIMMING)
- CheckWaterJump();
+ if (this.waterlevel == WATERLEVEL_SWIMMING)
+ CheckWaterJump(this);
}
float racecar_angle(float forward, float down)
return ret * angle_mult;
}
-void RaceCarPhysics()
-{SELFPARAM();
-#ifdef SVQC
- // using this move type for "big rigs"
- // the engine does not push the entity!
-
- vector rigvel;
-
- vector angles_save = self.angles;
- float accel = bound(-1, self.movement.x / PHYS_MAXSPEED(self), 1);
- float steer = bound(-1, self.movement.y / PHYS_MAXSPEED(self), 1);
-
- if (g_bugrigs_reverse_speeding)
- {
- if (accel < 0)
- {
- // back accel is DIGITAL
- // to prevent speedhack
- if (accel < -0.5)
- accel = -1;
- else
- accel = 0;
- }
- }
-
- self.angles_x = 0;
- self.angles_z = 0;
- makevectors(self.angles); // new forward direction!
-
- if (IS_ONGROUND(self) || g_bugrigs_air_steering)
- {
- float myspeed = self.velocity * v_forward;
- float upspeed = self.velocity * v_up;
-
- // responsiveness factor for steering and acceleration
- float f = 1 / (1 + pow(max(-myspeed, myspeed) / g_bugrigs_speed_ref, g_bugrigs_speed_pow));
- //MAXIMA: f(v) := 1 / (1 + (v / g_bugrigs_speed_ref) ^ g_bugrigs_speed_pow);
-
- float steerfactor;
- if (myspeed < 0 && g_bugrigs_reverse_spinning)
- steerfactor = -myspeed * g_bugrigs_steer;
- else
- steerfactor = -myspeed * f * g_bugrigs_steer;
-
- float accelfactor;
- if (myspeed < 0 && g_bugrigs_reverse_speeding)
- accelfactor = g_bugrigs_accel;
- else
- accelfactor = f * g_bugrigs_accel;
- //MAXIMA: accel(v) := f(v) * g_bugrigs_accel;
-
- if (accel < 0)
- {
- if (myspeed > 0)
- {
- myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * (g_bugrigs_friction_floor - g_bugrigs_friction_brake * accel));
- }
- else
- {
- if (!g_bugrigs_reverse_speeding)
- myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * g_bugrigs_friction_floor);
- }
- }
- else
- {
- if (myspeed >= 0)
- {
- myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * g_bugrigs_friction_floor);
- }
- else
- {
- if (g_bugrigs_reverse_stopping)
- myspeed = 0;
- else
- myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * (g_bugrigs_friction_floor + g_bugrigs_friction_brake * accel));
- }
- }
- // terminal velocity = velocity at which 50 == accelfactor, that is, 1549 units/sec
- //MAXIMA: friction(v) := g_bugrigs_friction_floor;
-
- self.angles_y += steer * PHYS_INPUT_TIMELENGTH * steerfactor; // apply steering
- makevectors(self.angles); // new forward direction!
-
- myspeed += accel * accelfactor * PHYS_INPUT_TIMELENGTH;
-
- rigvel = myspeed * v_forward + '0 0 1' * upspeed;
- }
- else
- {
- float myspeed = vlen(self.velocity);
-
- // responsiveness factor for steering and acceleration
- float f = 1 / (1 + pow(max(0, myspeed / g_bugrigs_speed_ref), g_bugrigs_speed_pow));
- float steerfactor = -myspeed * f;
- self.angles_y += steer * PHYS_INPUT_TIMELENGTH * steerfactor; // apply steering
-
- rigvel = self.velocity;
- makevectors(self.angles); // new forward direction!
- }
-
- rigvel *= max(0, 1 - vlen(rigvel) * g_bugrigs_friction_air * PHYS_INPUT_TIMELENGTH);
- //MAXIMA: airfriction(v) := v * v * g_bugrigs_friction_air;
- //MAXIMA: total_acceleration(v) := accel(v) - friction(v) - airfriction(v);
- //MAXIMA: solve(total_acceleration(v) = 0, v);
-
- if (g_bugrigs_planar_movement)
- {
- vector rigvel_xy, neworigin, up;
- float mt;
-
- rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY(this); // 4x gravity plays better
- rigvel_xy = vec2(rigvel);
-
- if (g_bugrigs_planar_movement_car_jumping)
- mt = MOVE_NORMAL;
- else
- mt = MOVE_NOMONSTERS;
-
- tracebox(self.origin, self.mins, self.maxs, self.origin + '0 0 1024', mt, self);
- up = trace_endpos - self.origin;
-
- // BUG RIGS: align the move to the surface instead of doing collision testing
- // can we move?
- tracebox(trace_endpos, self.mins, self.maxs, trace_endpos + rigvel_xy * PHYS_INPUT_TIMELENGTH, mt, self);
-
- // align to surface
- tracebox(trace_endpos, self.mins, self.maxs, trace_endpos - up + '0 0 1' * rigvel_z * PHYS_INPUT_TIMELENGTH, mt, self);
-
- if (trace_fraction < 0.5)
- {
- trace_fraction = 1;
- neworigin = self.origin;
- }
- else
- neworigin = trace_endpos;
-
- if (trace_fraction < 1)
- {
- // now set angles_x so that the car points parallel to the surface
- self.angles = vectoangles(
- '1 0 0' * v_forward_x * trace_plane_normal_z
- +
- '0 1 0' * v_forward_y * trace_plane_normal_z
- +
- '0 0 1' * -(v_forward_x * trace_plane_normal_x + v_forward_y * trace_plane_normal_y)
- );
- SET_ONGROUND(self);
- }
- else
- {
- // now set angles_x so that the car points forward, but is tilted in velocity direction
- UNSET_ONGROUND(self);
- }
-
- self.velocity = (neworigin - self.origin) * (1.0 / PHYS_INPUT_TIMELENGTH);
- self.movetype = MOVETYPE_NOCLIP;
- }
- else
- {
- rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY(this); // 4x gravity plays better
- self.velocity = rigvel;
- self.movetype = MOVETYPE_FLY;
- }
-
- trace_fraction = 1;
- tracebox(self.origin, self.mins, self.maxs, self.origin - '0 0 4', MOVE_NORMAL, self);
- if (trace_fraction != 1)
- {
- self.angles = vectoangles2(
- '1 0 0' * v_forward_x * trace_plane_normal_z
- +
- '0 1 0' * v_forward_y * trace_plane_normal_z
- +
- '0 0 1' * -(v_forward_x * trace_plane_normal_x + v_forward_y * trace_plane_normal_y),
- trace_plane_normal
- );
- }
- else
- {
- vector vel_local;
-
- vel_local_x = v_forward * self.velocity;
- vel_local_y = v_right * self.velocity;
- vel_local_z = v_up * self.velocity;
-
- self.angles_x = racecar_angle(vel_local_x, vel_local_z);
- self.angles_z = racecar_angle(-vel_local_y, vel_local_z);
- }
-
- // smooth the angles
- vector vf1, vu1, smoothangles;
- makevectors(self.angles);
- float f = bound(0, PHYS_INPUT_TIMELENGTH * g_bugrigs_angle_smoothing, 1);
- if (f == 0)
- f = 1;
- vf1 = v_forward * f;
- vu1 = v_up * f;
- makevectors(angles_save);
- vf1 = vf1 + v_forward * (1 - f);
- vu1 = vu1 + v_up * (1 - f);
- smoothangles = vectoangles2(vf1, vu1);
- self.angles_x = -smoothangles_x;
- self.angles_z = smoothangles_z;
-#endif
-}
-
string specialcommand = "xwxwxsxsxaxdxaxdx1x ";
.float specialcommand_pos;
void SpecialCommand()
{
#ifdef SVQC
-#ifdef TETRIS
- TetrisImpulse();
-#else
if (!CheatImpulse(99))
LOG_INFO("A hollow voice says \"Plugh\".\n");
#endif
-#endif
}
-float PM_check_specialcommand(float buttons)
-{SELFPARAM();
+float PM_check_specialcommand(entity this, float buttons)
+{
#ifdef SVQC
string c;
if (!buttons)
else
c = "?";
- if (c == substring(specialcommand, self.specialcommand_pos, 1))
+ if (c == substring(specialcommand, this.specialcommand_pos, 1))
{
- self.specialcommand_pos += 1;
- if (self.specialcommand_pos >= strlen(specialcommand))
+ this.specialcommand_pos += 1;
+ if (this.specialcommand_pos >= strlen(specialcommand))
{
- self.specialcommand_pos = 0;
+ this.specialcommand_pos = 0;
SpecialCommand();
return true;
}
}
- else if (self.specialcommand_pos && (c != substring(specialcommand, self.specialcommand_pos - 1, 1)))
- self.specialcommand_pos = 0;
+ else if (this.specialcommand_pos && (c != substring(specialcommand, this.specialcommand_pos - 1, 1)))
+ this.specialcommand_pos = 0;
#endif
return false;
}
-void PM_check_nickspam()
-{SELFPARAM();
+void PM_check_nickspam(entity this)
+{
#ifdef SVQC
- if (time >= self.nickspamtime)
+ if (time >= this.nickspamtime)
return;
- if (self.nickspamcount >= autocvar_g_nick_flood_penalty_yellow)
+ if (this.nickspamcount >= autocvar_g_nick_flood_penalty_yellow)
{
// slight annoyance for nick change scripts
- self.movement = -1 * self.movement;
- self.BUTTON_ATCK = self.BUTTON_JUMP = self.BUTTON_ATCK2 = self.BUTTON_ZOOM = self.BUTTON_CROUCH = self.BUTTON_HOOK = self.BUTTON_USE = 0;
+ this.movement = -1 * this.movement;
+ this.BUTTON_ATCK = this.BUTTON_JUMP = this.BUTTON_ATCK2 = this.BUTTON_ZOOM = this.BUTTON_CROUCH = this.BUTTON_HOOK = this.BUTTON_USE = 0;
- if (self.nickspamcount >= autocvar_g_nick_flood_penalty_red) // if you are persistent and the slight annoyance above does not stop you, I'll show you!
+ if (this.nickspamcount >= autocvar_g_nick_flood_penalty_red) // if you are persistent and the slight annoyance above does not stop you, I'll show you!
{
- self.v_angle_x = random() * 360;
- self.v_angle_y = random() * 360;
+ this.v_angle_x = random() * 360;
+ this.v_angle_y = random() * 360;
// at least I'm not forcing retardedview by also assigning to angles_z
- self.fixangle = true;
+ this.fixangle = true;
}
}
#endif
}
-void PM_check_punch()
-{SELFPARAM();
+void PM_check_punch(entity this)
+{
#ifdef SVQC
- if (self.punchangle != '0 0 0')
+ if (this.punchangle != '0 0 0')
{
- float f = vlen(self.punchangle) - 10 * PHYS_INPUT_TIMELENGTH;
+ float f = vlen(this.punchangle) - 10 * PHYS_INPUT_TIMELENGTH;
if (f > 0)
- self.punchangle = normalize(self.punchangle) * f;
+ this.punchangle = normalize(this.punchangle) * f;
else
- self.punchangle = '0 0 0';
+ this.punchangle = '0 0 0';
}
- if (self.punchvector != '0 0 0')
+ if (this.punchvector != '0 0 0')
{
- float f = vlen(self.punchvector) - 30 * PHYS_INPUT_TIMELENGTH;
+ float f = vlen(this.punchvector) - 30 * PHYS_INPUT_TIMELENGTH;
if (f > 0)
- self.punchvector = normalize(self.punchvector) * f;
+ this.punchvector = normalize(this.punchvector) * f;
else
- self.punchvector = '0 0 0';
+ this.punchvector = '0 0 0';
}
#endif
}
-void PM_check_spider()
-{SELFPARAM();
-#ifdef SVQC
- if (time >= self.spider_slowness)
- return;
- PHYS_MAXSPEED(self) *= 0.5; // half speed while slow from spider
- PHYS_MAXAIRSPEED(self) *= 0.5;
- PHYS_AIRSPEEDLIMIT_NONQW(self) *= 0.5;
- PHYS_AIRSTRAFEACCELERATE(self) *= 0.5;
-#endif
-}
-
// predict frozen movement, as frozen players CAN move in some cases
-void PM_check_frozen()
-{SELFPARAM();
- if (!PHYS_FROZEN(self))
+void PM_check_frozen(entity this)
+{
+ if (!PHYS_FROZEN(this))
return;
if (PHYS_DODGING_FROZEN
#ifdef SVQC
- && IS_REAL_CLIENT(self)
+ && IS_REAL_CLIENT(this)
#endif
)
{
- self.movement_x = bound(-5, self.movement.x, 5);
- self.movement_y = bound(-5, self.movement.y, 5);
- self.movement_z = bound(-5, self.movement.z, 5);
+ this.movement_x = bound(-5, this.movement.x, 5);
+ this.movement_y = bound(-5, this.movement.y, 5);
+ this.movement_z = bound(-5, this.movement.z, 5);
}
else
- self.movement = '0 0 0';
+ this.movement = '0 0 0';
- vector midpoint = ((self.absmin + self.absmax) * 0.5);
+ vector midpoint = ((this.absmin + this.absmax) * 0.5);
if (pointcontents(midpoint) == CONTENT_WATER)
{
- self.velocity = self.velocity * 0.5;
+ this.velocity = this.velocity * 0.5;
if (pointcontents(midpoint + '0 0 16') == CONTENT_WATER)
- self.velocity_z = 200;
+ this.velocity_z = 200;
}
}
-void PM_check_hitground()
-{SELFPARAM();
+void PM_check_hitground(entity this)
+{
#ifdef SVQC
if (!IS_PLAYER(this)) return; // no fall sounds for observers thank you very much
if (!IS_ONGROUND(this)) return;
tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
if ((trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS)) return;
entity fall = (trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS) ? GS_FALL_METAL : GS_FALL;
- GlobalSound(fall, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+ WITH(entity, self, this, GlobalSound(fall, CH_PLAYER, VOICETYPE_PLAYERSOUND));
#endif
}
-void PM_check_blocked()
-{SELFPARAM();
+void PM_check_blocked(entity this)
+{
#ifdef SVQC
- if (!self.player_blocked)
+ if (!this.player_blocked)
return;
- self.movement = '0 0 0';
- self.disableclientprediction = 1;
-#endif
-}
-
-void PM_check_vortex()
-{SELFPARAM();
-#ifdef SVQC
- // WEAPONTODO
- float xyspeed = vlen(vec2(self.velocity));
- if (self.weapon == WEP_VORTEX.m_id && WEP_CVAR(vortex, charge) && WEP_CVAR(vortex, charge_velocity_rate) && xyspeed > WEP_CVAR(vortex, charge_minspeed))
- {
- // add a maximum of charge_velocity_rate when going fast (f = 1), gradually increasing from minspeed (f = 0) to maxspeed
- xyspeed = min(xyspeed, WEP_CVAR(vortex, charge_maxspeed));
- float f = (xyspeed - WEP_CVAR(vortex, charge_minspeed)) / (WEP_CVAR(vortex, charge_maxspeed) - WEP_CVAR(vortex, charge_minspeed));
- // add the extra charge
- self.vortex_charge = min(1, self.vortex_charge + WEP_CVAR(vortex, charge_velocity_rate) * f * PHYS_INPUT_TIMELENGTH);
- }
+ this.movement = '0 0 0';
+ this.disableclientprediction = 1;
#endif
}
-void PM_fly(float maxspd_mod)
-{SELFPARAM();
+void PM_fly(entity this, float maxspd_mod)
+{
// noclipping or flying
- UNSET_ONGROUND(self);
-
- self.velocity = self.velocity * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION);
- makevectors(self.v_angle);
- //wishvel = v_forward * self.movement.x + v_right * self.movement.y + v_up * self.movement.z;
- vector wishvel = v_forward * self.movement.x
- + v_right * self.movement.y
- + '0 0 1' * self.movement.z;
+ UNSET_ONGROUND(this);
+
+ this.velocity = this.velocity * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this));
+ makevectors(this.v_angle);
+ //wishvel = v_forward * this.movement.x + v_right * this.movement.y + v_up * this.movement.z;
+ vector wishvel = v_forward * this.movement.x
+ + v_right * this.movement.y
+ + '0 0 1' * this.movement.z;
// acceleration
vector wishdir = normalize(wishvel);
- float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(self) * maxspd_mod);
+ float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(this) * maxspd_mod);
#ifdef SVQC
- if (time >= self.teleport_time)
+ if (time >= this.teleport_time)
#endif
- PM_Accelerate(wishdir, wishspeed, wishspeed, PHYS_ACCELERATE * maxspd_mod, 1, 0, 0, 0);
- PM_ClientMovement_Move();
+ PM_Accelerate(this, wishdir, wishspeed, wishspeed, PHYS_ACCELERATE(this) * maxspd_mod, 1, 0, 0, 0);
+ PM_ClientMovement_Move(this);
}
-void PM_swim(float maxspd_mod)
-{SELFPARAM();
+void PM_swim(entity this, float maxspd_mod)
+{
// swimming
- UNSET_ONGROUND(self);
+ UNSET_ONGROUND(this);
- float jump = PHYS_INPUT_BUTTON_JUMP(self);
+ float jump = PHYS_INPUT_BUTTON_JUMP(this);
// water jump only in certain situations
// this mimics quakeworld code
- if (jump && self.waterlevel == WATERLEVEL_SWIMMING && self.velocity_z >= -180)
+ if (jump && this.waterlevel == WATERLEVEL_SWIMMING && this.velocity_z >= -180)
{
- vector yawangles = '0 1 0' * self.v_angle.y;
+ vector yawangles = '0 1 0' * this.v_angle.y;
makevectors(yawangles);
vector forward = v_forward;
- vector spot = self.origin + 24 * forward;
+ vector spot = this.origin + 24 * forward;
spot_z += 8;
- traceline(spot, spot, MOVE_NOMONSTERS, self);
+ traceline(spot, spot, MOVE_NOMONSTERS, this);
if (trace_startsolid)
{
spot_z += 24;
- traceline(spot, spot, MOVE_NOMONSTERS, self);
+ traceline(spot, spot, MOVE_NOMONSTERS, this);
if (!trace_startsolid)
{
- self.velocity = forward * 50;
- self.velocity_z = 310;
+ this.velocity = forward * 50;
+ this.velocity_z = 310;
pmove_waterjumptime = 2;
- UNSET_ONGROUND(self);
- SET_JUMP_HELD(self);
+ UNSET_ONGROUND(this);
+ SET_JUMP_HELD(this);
}
}
}
- makevectors(self.v_angle);
- //wishvel = v_forward * self.movement.x + v_right * self.movement.y + v_up * self.movement.z;
- vector wishvel = v_forward * self.movement.x
- + v_right * self.movement.y
- + '0 0 1' * self.movement.z;
+ makevectors(this.v_angle);
+ //wishvel = v_forward * this.movement.x + v_right * this.movement.y + v_up * this.movement.z;
+ vector wishvel = v_forward * this.movement.x
+ + v_right * this.movement.y
+ + '0 0 1' * this.movement.z;
if (wishvel == '0 0 0')
wishvel = '0 0 -60'; // drift towards bottom
vector wishdir = normalize(wishvel);
- float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(self) * maxspd_mod) * 0.7;
+ float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(this) * maxspd_mod) * 0.7;
- if (IS_DUCKED(self))
+ if (IS_DUCKED(this))
wishspeed *= 0.5;
// if (pmove_waterjumptime <= 0) // TODO: use
{
// water friction
- float f = 1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION;
+ float f = 1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this);
f = min(max(0, f), 1);
- self.velocity *= f;
+ this.velocity *= f;
- f = wishspeed - self.velocity * wishdir;
+ f = wishspeed - this.velocity * wishdir;
if (f > 0)
{
- float accelspeed = min(PHYS_ACCELERATE * PHYS_INPUT_TIMELENGTH * wishspeed, f);
- self.velocity += accelspeed * wishdir;
+ float accelspeed = min(PHYS_ACCELERATE(this) * PHYS_INPUT_TIMELENGTH * wishspeed, f);
+ this.velocity += accelspeed * wishdir;
}
// holding jump button swims upward slowly
if (jump)
{
#if 0
- if (self.watertype & CONTENT_LAVA)
- self.velocity_z = 50;
- else if (self.watertype & CONTENT_SLIME)
- self.velocity_z = 80;
+ if (this.watertype & CONTENT_LAVA)
+ this.velocity_z = 50;
+ else if (this.watertype & CONTENT_SLIME)
+ this.velocity_z = 80;
else
{
if (IS_NEXUIZ_DERIVED(gamemode))
#endif
- self.velocity_z = 200;
+ this.velocity_z = 200;
#if 0
else
- self.velocity_z = 100;
+ this.velocity_z = 100;
}
#endif
}
}
// water acceleration
- PM_Accelerate(wishdir, wishspeed, wishspeed, PHYS_ACCELERATE * maxspd_mod, 1, 0, 0, 0);
- PM_ClientMovement_Move();
+ PM_Accelerate(this, wishdir, wishspeed, wishspeed, PHYS_ACCELERATE(this) * maxspd_mod, 1, 0, 0, 0);
+ PM_ClientMovement_Move(this);
}
-void PM_ladder(float maxspd_mod)
-{SELFPARAM();
+void PM_ladder(entity this, float maxspd_mod)
+{
// on a spawnfunc_func_ladder or swimming in spawnfunc_func_water
- UNSET_ONGROUND(self);
+ UNSET_ONGROUND(this);
float g;
g = PHYS_GRAVITY(this) * PHYS_INPUT_TIMELENGTH;
- if (PHYS_ENTGRAVITY(self))
- g *= PHYS_ENTGRAVITY(self);
+ if (PHYS_ENTGRAVITY(this))
+ g *= PHYS_ENTGRAVITY(this);
if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
{
g *= 0.5;
- self.velocity_z += g;
+ this.velocity_z += g;
}
- self.velocity = self.velocity * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION);
- makevectors(self.v_angle);
- //wishvel = v_forward * self.movement.x + v_right * self.movement.y + v_up * self.movement.z;
- vector wishvel = v_forward * self.movement_x
- + v_right * self.movement_y
- + '0 0 1' * self.movement_z;
- self.velocity_z += g;
- if (self.ladder_entity.classname == "func_water")
+ this.velocity = this.velocity * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this));
+ makevectors(this.v_angle);
+ //wishvel = v_forward * this.movement.x + v_right * this.movement.y + v_up * this.movement.z;
+ vector wishvel = v_forward * this.movement_x
+ + v_right * this.movement_y
+ + '0 0 1' * this.movement_z;
+ this.velocity_z += g;
+ if (this.ladder_entity.classname == "func_water")
{
float f = vlen(wishvel);
- if (f > self.ladder_entity.speed)
- wishvel *= (self.ladder_entity.speed / f);
-
- self.watertype = self.ladder_entity.skin;
- f = self.ladder_entity.origin_z + self.ladder_entity.maxs_z;
- if ((self.origin_z + self.view_ofs_z) < f)
- self.waterlevel = WATERLEVEL_SUBMERGED;
- else if ((self.origin_z + (self.mins_z + self.maxs_z) * 0.5) < f)
- self.waterlevel = WATERLEVEL_SWIMMING;
- else if ((self.origin_z + self.mins_z + 1) < f)
- self.waterlevel = WATERLEVEL_WETFEET;
+ if (f > this.ladder_entity.speed)
+ wishvel *= (this.ladder_entity.speed / f);
+
+ this.watertype = this.ladder_entity.skin;
+ f = this.ladder_entity.origin_z + this.ladder_entity.maxs_z;
+ if ((this.origin_z + this.view_ofs_z) < f)
+ this.waterlevel = WATERLEVEL_SUBMERGED;
+ else if ((this.origin_z + (this.mins_z + this.maxs_z) * 0.5) < f)
+ this.waterlevel = WATERLEVEL_SWIMMING;
+ else if ((this.origin_z + this.mins_z + 1) < f)
+ this.waterlevel = WATERLEVEL_WETFEET;
else
{
- self.waterlevel = WATERLEVEL_NONE;
- self.watertype = CONTENT_EMPTY;
+ this.waterlevel = WATERLEVEL_NONE;
+ this.watertype = CONTENT_EMPTY;
}
}
// acceleration
vector wishdir = normalize(wishvel);
- float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(self) * maxspd_mod);
+ float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(this) * maxspd_mod);
#ifdef SVQC
- if (time >= self.teleport_time)
+ if (time >= this.teleport_time)
#endif
// water acceleration
- PM_Accelerate(wishdir, wishspeed, wishspeed, PHYS_ACCELERATE*maxspd_mod, 1, 0, 0, 0);
- PM_ClientMovement_Move();
+ PM_Accelerate(this, wishdir, wishspeed, wishspeed, PHYS_ACCELERATE(this)*maxspd_mod, 1, 0, 0, 0);
+ PM_ClientMovement_Move(this);
}
-void PM_jetpack(float maxspd_mod)
-{SELFPARAM();
- //makevectors(self.v_angle.y * '0 1 0');
- makevectors(self.v_angle);
- vector wishvel = v_forward * self.movement_x
- + v_right * self.movement_y;
+void PM_jetpack(entity this, float maxspd_mod)
+{
+ //makevectors(this.v_angle.y * '0 1 0');
+ makevectors(this.v_angle);
+ vector wishvel = v_forward * this.movement_x
+ + v_right * this.movement_y;
// add remaining speed as Z component
- float maxairspd = PHYS_MAXAIRSPEED(self) * max(1, maxspd_mod);
+ float maxairspd = PHYS_MAXAIRSPEED(this) * max(1, maxspd_mod);
// fix speedhacks :P
wishvel = normalize(wishvel) * min(1, vlen(wishvel) / maxairspd);
// add the unused velocity as up component
wishvel_z = 0;
- // if (self.BUTTON_JUMP)
+ // if (this.BUTTON_JUMP)
wishvel_z = sqrt(max(0, 1 - wishvel * wishvel));
// it is now normalized, so...
//print("best possible acceleration: ", ftos(best), "\n");
float fxy, fz;
- fxy = bound(0, 1 - (self.velocity * normalize(wishvel_x * '1 0 0' + wishvel_y * '0 1 0')) / PHYS_JETPACK_MAXSPEED_SIDE, 1);
+ fxy = bound(0, 1 - (this.velocity * normalize(wishvel_x * '1 0 0' + wishvel_y * '0 1 0')) / PHYS_JETPACK_MAXSPEED_SIDE, 1);
if (wishvel_z - PHYS_GRAVITY(this) > 0)
- fz = bound(0, 1 - self.velocity_z / PHYS_JETPACK_MAXSPEED_UP, 1);
+ fz = bound(0, 1 - this.velocity_z / PHYS_JETPACK_MAXSPEED_UP, 1);
else
- fz = bound(0, 1 + self.velocity_z / PHYS_JETPACK_MAXSPEED_UP, 1);
+ fz = bound(0, 1 + this.velocity_z / PHYS_JETPACK_MAXSPEED_UP, 1);
float fvel;
fvel = vlen(wishvel);
wishvel_z = (wishvel_z - PHYS_GRAVITY(this)) * fz + PHYS_GRAVITY(this);
fvel = min(1, vlen(wishvel) / best);
- if (PHYS_JETPACK_FUEL && !(ITEMS_STAT(self) & IT_UNLIMITED_WEAPON_AMMO))
- f = min(1, PHYS_AMMO_FUEL(self) / (PHYS_JETPACK_FUEL * PHYS_INPUT_TIMELENGTH * fvel));
+ if (PHYS_JETPACK_FUEL && !(ITEMS_STAT(this) & IT_UNLIMITED_WEAPON_AMMO))
+ f = min(1, PHYS_AMMO_FUEL(this) / (PHYS_JETPACK_FUEL * PHYS_INPUT_TIMELENGTH * fvel));
else
f = 1;
if (f > 0 && wishvel != '0 0 0')
{
- self.velocity = self.velocity + wishvel * f * PHYS_INPUT_TIMELENGTH;
- UNSET_ONGROUND(self);
+ this.velocity = this.velocity + wishvel * f * PHYS_INPUT_TIMELENGTH;
+ UNSET_ONGROUND(this);
#ifdef SVQC
- if (!(ITEMS_STAT(self) & IT_UNLIMITED_WEAPON_AMMO))
- self.ammo_fuel -= PHYS_JETPACK_FUEL * PHYS_INPUT_TIMELENGTH * fvel * f;
+ if (!(ITEMS_STAT(this) & IT_UNLIMITED_WEAPON_AMMO))
+ this.ammo_fuel -= PHYS_JETPACK_FUEL * PHYS_INPUT_TIMELENGTH * fvel * f;
- ITEMS_STAT(self) |= IT_USING_JETPACK;
+ ITEMS_STAT(this) |= IT_USING_JETPACK;
// jetpack also inhibits health regeneration, but only for 1 second
- self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen);
+ this.pauseregen_finished = max(this.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen);
#endif
}
#ifdef CSQC
- float g = PHYS_GRAVITY(this) * PHYS_ENTGRAVITY(self) * PHYS_INPUT_TIMELENGTH;
- if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
- self.velocity_z -= g * 0.5;
- else
- self.velocity_z -= g;
- PM_ClientMovement_Move();
- if (!IS_ONGROUND(self) || !(GAMEPLAYFIX_NOGRAVITYONGROUND))
+ float g = PHYS_GRAVITY(this) * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
+ if(autocvar_cl_movement != 3)
+ {
if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
- self.velocity_z -= g * 0.5;
+ this.velocity_z -= g * 0.5;
+ else
+ this.velocity_z -= g;
+ }
+ PM_ClientMovement_Move(this);
+ if(autocvar_cl_movement != 3)
+ {
+ if (!IS_ONGROUND(this) || !(GAMEPLAYFIX_NOGRAVITYONGROUND))
+ if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
+ this.velocity_z -= g * 0.5;
+ }
#endif
}
// apply ground friction
const int realfriction = (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK)
? PHYS_FRICTION_SLICK
- : PHYS_FRICTION;
+ : PHYS_FRICTION(this);
float f = sqrt(f2);
- f = 1 - PHYS_INPUT_TIMELENGTH * realfriction * ((f < PHYS_STOPSPEED) ? (PHYS_STOPSPEED / f) : 1);
+ f = 1 - PHYS_INPUT_TIMELENGTH * realfriction * ((f < PHYS_STOPSPEED(this)) ? (PHYS_STOPSPEED(this) / f) : 1);
f = max(0, f);
this.velocity *= f;
/*
Our goal is to invert this mess.
For the two cases we get:
- v = v0 * (1 - PHYS_INPUT_TIMELENGTH * (PHYS_STOPSPEED / v0) * PHYS_FRICTION)
- = v0 - PHYS_INPUT_TIMELENGTH * PHYS_STOPSPEED * PHYS_FRICTION
- v0 = v + PHYS_INPUT_TIMELENGTH * PHYS_STOPSPEED * PHYS_FRICTION
+ v = v0 * (1 - PHYS_INPUT_TIMELENGTH * (PHYS_STOPSPEED(this) / v0) * PHYS_FRICTION(this))
+ = v0 - PHYS_INPUT_TIMELENGTH * PHYS_STOPSPEED(this) * PHYS_FRICTION(this)
+ v0 = v + PHYS_INPUT_TIMELENGTH * PHYS_STOPSPEED(this) * PHYS_FRICTION(this)
and
- v = v0 * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION)
- v0 = v / (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION)
+ v = v0 * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this))
+ v0 = v / (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this))
These cases would be chosen ONLY if:
- v0 < PHYS_STOPSPEED
- v + PHYS_INPUT_TIMELENGTH * PHYS_STOPSPEED * PHYS_FRICTION < PHYS_STOPSPEED
- v < PHYS_STOPSPEED * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION)
+ v0 < PHYS_STOPSPEED(this)
+ v + PHYS_INPUT_TIMELENGTH * PHYS_STOPSPEED(this) * PHYS_FRICTION(this) < PHYS_STOPSPEED(this)
+ v < PHYS_STOPSPEED(this) * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this))
and, respectively:
- v0 >= PHYS_STOPSPEED
- v / (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION) >= PHYS_STOPSPEED
- v >= PHYS_STOPSPEED * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION)
+ v0 >= PHYS_STOPSPEED(this)
+ v / (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this)) >= PHYS_STOPSPEED(this)
+ v >= PHYS_STOPSPEED(this) * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this))
*/
}
const float addspeed = wishspeed - this.velocity * wishdir;
if (addspeed > 0)
{
- const float accelspeed = min(PHYS_ACCELERATE * PHYS_INPUT_TIMELENGTH * wishspeed, addspeed);
+ const float accelspeed = min(PHYS_ACCELERATE(this) * PHYS_INPUT_TIMELENGTH * wishspeed, addspeed);
this.velocity += accelspeed * wishdir;
}
- const float g = PHYS_GRAVITY(this) * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
- if (!(GAMEPLAYFIX_NOGRAVITYONGROUND))
- this.velocity_z -= g * (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1);
+#ifdef CSQC
+ float g = PHYS_GRAVITY(this) * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
+ if(autocvar_cl_movement != 3)
+ {
+ if (!(GAMEPLAYFIX_NOGRAVITYONGROUND))
+ this.velocity_z -= g * (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1);
+ }
if (vdist(this.velocity, >, 0))
- PM_ClientMovement_Move();
- if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
- if (!IS_ONGROUND(this) || !GAMEPLAYFIX_NOGRAVITYONGROUND)
- this.velocity_z -= g * 0.5;
+ PM_ClientMovement_Move(this);
+ if(autocvar_cl_movement != 3)
+ {
+ if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
+ if (!IS_ONGROUND(this) || !GAMEPLAYFIX_NOGRAVITYONGROUND)
+ this.velocity_z -= g * 0.5;
+ }
+#endif
}
-void PM_air(float buttons_prev, float maxspd_mod)
-{SELFPARAM();
- makevectors(self.v_angle.y * '0 1 0');
- vector wishvel = v_forward * self.movement.x
- + v_right * self.movement.y;
+void PM_air(entity this, float buttons_prev, float maxspd_mod)
+{
+ makevectors(this.v_angle.y * '0 1 0');
+ vector wishvel = v_forward * this.movement.x
+ + v_right * this.movement.y;
// acceleration
vector wishdir = normalize(wishvel);
float wishspeed = vlen(wishvel);
#ifdef SVQC
- if (time >= self.teleport_time)
+ if (time >= this.teleport_time)
#else
if (pmove_waterjumptime <= 0)
#endif
{
- float maxairspd = PHYS_MAXAIRSPEED(self) * min(maxspd_mod, 1);
+ float maxairspd = PHYS_MAXAIRSPEED(this) * min(maxspd_mod, 1);
// apply air speed limit
- float airaccelqw = PHYS_AIRACCEL_QW(self);
+ float airaccelqw = PHYS_AIRACCEL_QW(this);
float wishspeed0 = wishspeed;
wishspeed = min(wishspeed, maxairspd);
- if (IS_DUCKED(self))
+ if (IS_DUCKED(this))
wishspeed *= 0.5;
- float airaccel = PHYS_AIRACCELERATE * min(maxspd_mod, 1);
+ float airaccel = PHYS_AIRACCELERATE(this) * min(maxspd_mod, 1);
- float accelerating = (self.velocity * wishdir > 0);
+ float accelerating = (this.velocity * wishdir > 0);
float wishspeed2 = wishspeed;
// CPM: air control
- if (PHYS_AIRSTOPACCELERATE)
+ if (PHYS_AIRSTOPACCELERATE(this))
{
- vector curdir = normalize(vec2(self.velocity));
- airaccel += (PHYS_AIRSTOPACCELERATE*maxspd_mod - airaccel) * max(0, -(curdir * wishdir));
+ vector curdir = normalize(vec2(this.velocity));
+ airaccel += (PHYS_AIRSTOPACCELERATE(this)*maxspd_mod - airaccel) * max(0, -(curdir * wishdir));
}
// note that for straight forward jumping:
// step = accel * PHYS_INPUT_TIMELENGTH * wishspeed0;
// dv/dt = accel * maxspeed * (1 - accelqw) (when fast)
// log dv/dt = logaccel + logmaxspeed (when slow)
// log dv/dt = logaccel + logmaxspeed + log(1 - accelqw) (when fast)
- float strafity = IsMoveInDirection(self.movement, -90) + IsMoveInDirection(self.movement, +90); // if one is nonzero, other is always zero
- if (PHYS_MAXAIRSTRAFESPEED)
- wishspeed = min(wishspeed, GeomLerp(PHYS_MAXAIRSPEED(self)*maxspd_mod, strafity, PHYS_MAXAIRSTRAFESPEED*maxspd_mod));
- if (PHYS_AIRSTRAFEACCELERATE(self))
- airaccel = GeomLerp(airaccel, strafity, PHYS_AIRSTRAFEACCELERATE(self)*maxspd_mod);
- if (PHYS_AIRSTRAFEACCEL_QW(self))
+ float strafity = IsMoveInDirection(this.movement, -90) + IsMoveInDirection(this.movement, +90); // if one is nonzero, other is always zero
+ if (PHYS_MAXAIRSTRAFESPEED(this))
+ wishspeed = min(wishspeed, GeomLerp(PHYS_MAXAIRSPEED(this)*maxspd_mod, strafity, PHYS_MAXAIRSTRAFESPEED(this)*maxspd_mod));
+ if (PHYS_AIRSTRAFEACCELERATE(this))
+ airaccel = GeomLerp(airaccel, strafity, PHYS_AIRSTRAFEACCELERATE(this)*maxspd_mod);
+ if (PHYS_AIRSTRAFEACCEL_QW(this))
airaccelqw =
- (((strafity > 0.5 ? PHYS_AIRSTRAFEACCEL_QW(self) : PHYS_AIRACCEL_QW(self)) >= 0) ? +1 : -1)
+ (((strafity > 0.5 ? PHYS_AIRSTRAFEACCEL_QW(this) : PHYS_AIRACCEL_QW(this)) >= 0) ? +1 : -1)
*
- (1 - GeomLerp(1 - fabs(PHYS_AIRACCEL_QW(self)), strafity, 1 - fabs(PHYS_AIRSTRAFEACCEL_QW(self))));
+ (1 - GeomLerp(1 - fabs(PHYS_AIRACCEL_QW(this)), strafity, 1 - fabs(PHYS_AIRSTRAFEACCEL_QW(this))));
// !CPM
- if (PHYS_WARSOWBUNNY_TURNACCEL && accelerating && self.movement.y == 0 && self.movement.x != 0)
- PM_AirAccelerate(wishdir, wishspeed2);
+ if (PHYS_WARSOWBUNNY_TURNACCEL(this) && accelerating && this.movement.y == 0 && this.movement.x != 0)
+ PM_AirAccelerate(this, wishdir, wishspeed2);
else
- PM_Accelerate(wishdir, wishspeed, wishspeed0, airaccel, airaccelqw, PHYS_AIRACCEL_QW_STRETCHFACTOR(self), PHYS_AIRACCEL_SIDEWAYS_FRICTION / maxairspd, PHYS_AIRSPEEDLIMIT_NONQW(self));
+ PM_Accelerate(this, wishdir, wishspeed, wishspeed0, airaccel, airaccelqw, PHYS_AIRACCEL_QW_STRETCHFACTOR(this), PHYS_AIRACCEL_SIDEWAYS_FRICTION(this) / maxairspd, PHYS_AIRSPEEDLIMIT_NONQW(this));
- if (PHYS_AIRCONTROL)
- CPM_PM_Aircontrol(wishdir, wishspeed2);
+ if (PHYS_AIRCONTROL(this))
+ CPM_PM_Aircontrol(this, wishdir, wishspeed2);
}
- float g = PHYS_GRAVITY(this) * PHYS_ENTGRAVITY(self) * PHYS_INPUT_TIMELENGTH;
+#ifdef CSQC
+ float g = PHYS_GRAVITY(this) * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
+ if(autocvar_cl_movement != 3)
if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
- self.velocity_z -= g * 0.5;
+ this.velocity_z -= g * 0.5;
else
- self.velocity_z -= g;
- PM_ClientMovement_Move();
- if (!IS_ONGROUND(self) || !(GAMEPLAYFIX_NOGRAVITYONGROUND))
+ this.velocity_z -= g;
+#endif
+ PM_ClientMovement_Move(this);
+#ifdef CSQC
+ if(autocvar_cl_movement != 3)
+ if (!IS_ONGROUND(this) || !(GAMEPLAYFIX_NOGRAVITYONGROUND))
if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
- self.velocity_z -= g * 0.5;
+ this.velocity_z -= g * 0.5;
+#endif
}
// used for calculating airshots
-bool IsFlying(entity a)
+bool IsFlying(entity this)
{
- if(IS_ONGROUND(a))
+ if(IS_ONGROUND(this))
return false;
- if(a.waterlevel >= WATERLEVEL_SWIMMING)
+ if(this.waterlevel >= WATERLEVEL_SWIMMING)
return false;
- traceline(a.origin, a.origin - '0 0 48', MOVE_NORMAL, a);
+ traceline(this.origin, this.origin - '0 0 48', MOVE_NORMAL, this);
if(trace_fraction < 1)
return false;
return true;
#endif
#ifdef SVQC
- anticheat_physics();
+ anticheat_physics(this);
#endif
- if (PM_check_specialcommand(buttons))
+ if (PM_check_specialcommand(this, buttons))
return;
#ifdef SVQC
if (sv_maxidle > 0)
this.movement_old = this.movement;
this.v_angle_old = this.v_angle;
- PM_check_nickspam();
+ PM_check_nickspam(this);
- PM_check_punch();
+ PM_check_punch(this);
#ifdef SVQC
if (IS_BOT_CLIENT(this))
{
- if (playerdemo_read())
+ if (playerdemo_read(this))
return;
- bot_think();
+ WITH(entity, self, this, bot_think());
}
#endif
this.disableclientprediction = 0;
#endif
- viewloc_PlayerPhysics();
-
- PM_check_spider();
+ viewloc_PlayerPhysics(this);
- PM_check_frozen();
+ PM_check_frozen(this);
- PM_check_blocked();
+ PM_check_blocked(this);
maxspeed_mod = 1;
if (this.conveyor.state)
this.velocity -= this.conveyor.movedir;
-#ifdef SVQC
- MUTATOR_CALLHOOK(PlayerPhysics);
-#endif
-#ifdef CSQC
- PM_multijump();
-#endif
-
-// float forcedodge = 1;
-// if(forcedodge) {
-//#ifdef CSQC
-// PM_dodging_checkpressedkeys();
-//#endif
-// PM_dodging();
-// PM_ClientMovement_Move();
-// return;
-// }
+ MUTATOR_CALLHOOK(PlayerPhysics, this);
#ifdef SVQC
if (!IS_PLAYER(this))
}
#ifdef SVQC
- if (!this.fixangle && !g_bugrigs)
+ if (!this.fixangle)
this.angles = '0 1 0' * this.v_angle.y;
#endif
- PM_check_hitground();
+ PM_check_hitground(this);
if(IsFlying(this))
this.wasFlying = 1;
if (IS_PLAYER(this))
- CheckPlayerJump();
+ CheckPlayerJump(this);
if (this.flags & FL_WATERJUMP)
{
}
}
-#ifdef SVQC
- else if (g_bugrigs && IS_PLAYER(this))
- RaceCarPhysics();
-#endif
+ else if (MUTATOR_CALLHOOK(PM_Physics, this, maxspeed_mod))
+ { }
else if (this.movetype == MOVETYPE_NOCLIP || this.movetype == MOVETYPE_FLY || this.movetype == MOVETYPE_FLY_WORLDONLY || MUTATOR_CALLHOOK(IsFlying, this))
- PM_fly(maxspeed_mod);
+ PM_fly(this, maxspeed_mod);
else if (this.waterlevel >= WATERLEVEL_SWIMMING)
- PM_swim(maxspeed_mod);
+ PM_swim(this, maxspeed_mod);
else if (time < this.ladder_time)
- PM_ladder(maxspeed_mod);
+ PM_ladder(this, maxspeed_mod);
else if (ITEMS_STAT(this) & IT_USING_JETPACK)
- PM_jetpack(maxspeed_mod);
+ PM_jetpack(this, maxspeed_mod);
else if (IS_ONGROUND(this))
PM_walk(this, maxspeed_mod);
else
- PM_air(buttons_prev, maxspeed_mod);
-
- PM_check_vortex();
+ PM_air(this, buttons_prev, maxspeed_mod);
:end
if (IS_ONGROUND(this))
#define GAMEPLAYFIX_STEPMULTIPLETIMES STAT(GAMEPLAYFIX_STEPMULTIPLETIMES, this)
#define GAMEPLAYFIX_UNSTICKPLAYERS STAT(GAMEPLAYFIX_UNSTICKPLAYERS, this)
-#define PHYS_ACCELERATE STAT(MOVEVARS_ACCELERATE, this)
-#define PHYS_AIRACCELERATE STAT(MOVEVARS_AIRACCELERATE, this)
+#define PHYS_ACCELERATE(s) STAT(MOVEVARS_ACCELERATE, s)
+#define PHYS_AIRACCELERATE(s) STAT(MOVEVARS_AIRACCELERATE, s)
#define PHYS_AIRACCEL_QW(s) STAT(MOVEVARS_AIRACCEL_QW, s)
#define PHYS_AIRACCEL_QW_STRETCHFACTOR(s) STAT(MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, s)
-#define PHYS_AIRACCEL_SIDEWAYS_FRICTION STAT(MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, this)
-#define PHYS_AIRCONTROL STAT(MOVEVARS_AIRCONTROL, this)
-#define PHYS_AIRCONTROL_PENALTY STAT(MOVEVARS_AIRCONTROL_PENALTY, this)
-#define PHYS_AIRCONTROL_POWER STAT(MOVEVARS_AIRCONTROL_POWER, this)
+#define PHYS_AIRACCEL_SIDEWAYS_FRICTION(s) STAT(MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, s)
+#define PHYS_AIRCONTROL(s) STAT(MOVEVARS_AIRCONTROL, s)
+#define PHYS_AIRCONTROL_PENALTY(s) STAT(MOVEVARS_AIRCONTROL_PENALTY, s)
+#define PHYS_AIRCONTROL_POWER(s) STAT(MOVEVARS_AIRCONTROL_POWER, s)
#define PHYS_AIRSPEEDLIMIT_NONQW(s) STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, s)
-#define PHYS_AIRSTOPACCELERATE STAT(MOVEVARS_AIRSTOPACCELERATE, this)
-#define PHYS_AIRSTRAFEACCELERATE(s) STAT(MOVEVARS_AIRSTRAFEACCELERATE, this)
+#define PHYS_AIRSTOPACCELERATE(s) STAT(MOVEVARS_AIRSTOPACCELERATE, s)
+#define PHYS_AIRSTRAFEACCELERATE(s) STAT(MOVEVARS_AIRSTRAFEACCELERATE, s)
#define PHYS_AIRSTRAFEACCEL_QW(s) STAT(MOVEVARS_AIRSTRAFEACCEL_QW, s)
#define PHYS_AMMO_FUEL(s) STAT(FUEL, s)
-#define PHYS_BUGRIGS STAT(BUGRIGS, this)
-#define PHYS_BUGRIGS_ACCEL STAT(BUGRIGS_ACCEL, this)
-#define PHYS_BUGRIGS_AIR_STEERING STAT(BUGRIGS_AIR_STEERING, this)
-#define PHYS_BUGRIGS_ANGLE_SMOOTHING STAT(BUGRIGS_ANGLE_SMOOTHING, this)
-#define PHYS_BUGRIGS_CAR_JUMPING STAT(BUGRIGS_CAR_JUMPING, this)
-#define PHYS_BUGRIGS_FRICTION_AIR STAT(BUGRIGS_FRICTION_AIR, this)
-#define PHYS_BUGRIGS_FRICTION_BRAKE STAT(BUGRIGS_FRICTION_BRAKE, this)
-#define PHYS_BUGRIGS_FRICTION_FLOOR STAT(BUGRIGS_FRICTION_FLOOR, this)
-#define PHYS_BUGRIGS_PLANAR_MOVEMENT STAT(BUGRIGS_PLANAR_MOVEMENT, this)
-#define PHYS_BUGRIGS_REVERSE_SPEEDING STAT(BUGRIGS_REVERSE_SPEEDING, this)
-#define PHYS_BUGRIGS_REVERSE_SPINNING STAT(BUGRIGS_REVERSE_SPINNING, this)
-#define PHYS_BUGRIGS_REVERSE_STOPPING STAT(BUGRIGS_REVERSE_STOPPING, this)
-#define PHYS_BUGRIGS_SPEED_POW STAT(BUGRIGS_SPEED_POW, this)
-#define PHYS_BUGRIGS_SPEED_REF STAT(BUGRIGS_SPEED_REF, this)
-#define PHYS_BUGRIGS_STEER STAT(BUGRIGS_STEER, this)
-
#define PHYS_DODGING_FROZEN STAT(DODGING_FROZEN, this)
-#define PHYS_DOUBLEJUMP STAT(DOUBLEJUMP, this)
-
-#define PHYS_FRICTION STAT(MOVEVARS_FRICTION, this)
+#define PHYS_FRICTION(s) STAT(MOVEVARS_FRICTION, s)
#define PHYS_FRICTION_ONLAND STAT(MOVEVARS_FRICTION_ONLAND, this)
#define PHYS_FRICTION_SLICK STAT(MOVEVARS_FRICTION_SLICK, this)
#define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS STAT(MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS, this)
#define PHYS_JUMPSTEP STAT(MOVEVARS_JUMPSTEP, this)
-#define PHYS_JUMPVELOCITY STAT(MOVEVARS_JUMPVELOCITY, this)
+#define PHYS_JUMPVELOCITY(s) STAT(MOVEVARS_JUMPVELOCITY, s)
#define PHYS_MAXAIRSPEED(s) STAT(MOVEVARS_MAXAIRSPEED, s)
-#define PHYS_MAXAIRSTRAFESPEED STAT(MOVEVARS_MAXAIRSTRAFESPEED, this)
+#define PHYS_MAXAIRSTRAFESPEED(s) STAT(MOVEVARS_MAXAIRSTRAFESPEED, s)
#define PHYS_MAXSPEED(s) STAT(MOVEVARS_MAXSPEED, s)
#define PHYS_NOSTEP STAT(NOSTEP, this)
#define PHYS_STEPHEIGHT STAT(MOVEVARS_STEPHEIGHT, this)
-#define PHYS_STOPSPEED STAT(MOVEVARS_STOPSPEED, this)
+#define PHYS_STOPSPEED(s) STAT(MOVEVARS_STOPSPEED, s)
#define PHYS_TRACK_CANJUMP(s) STAT(MOVEVARS_TRACK_CANJUMP, s)
#define PHYS_WALLFRICTION STAT(MOVEVARS_WALLFRICTION, this)
-#define PHYS_WARSOWBUNNY_ACCEL STAT(MOVEVARS_WARSOWBUNNY_ACCEL, this)
-#define PHYS_WARSOWBUNNY_AIRFORWARDACCEL STAT(MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, this)
-#define PHYS_WARSOWBUNNY_BACKTOSIDERATIO STAT(MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, this)
-#define PHYS_WARSOWBUNNY_TOPSPEED STAT(MOVEVARS_WARSOWBUNNY_TOPSPEED, this)
-#define PHYS_WARSOWBUNNY_TURNACCEL STAT(MOVEVARS_WARSOWBUNNY_TURNACCEL, this)
+#define PHYS_WARSOWBUNNY_ACCEL(s) STAT(MOVEVARS_WARSOWBUNNY_ACCEL, s)
+#define PHYS_WARSOWBUNNY_AIRFORWARDACCEL(s) STAT(MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, s)
+#define PHYS_WARSOWBUNNY_BACKTOSIDERATIO(s) STAT(MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, s)
+#define PHYS_WARSOWBUNNY_TOPSPEED(s) STAT(MOVEVARS_WARSOWBUNNY_TOPSPEED, s)
+#define PHYS_WARSOWBUNNY_TURNACCEL(s) STAT(MOVEVARS_WARSOWBUNNY_TURNACCEL, s)
#define UPWARD_VELOCITY_CLEARS_ONGROUND STAT(GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND, this)
const int FL_WATERJUMP = 2048; // player jumping out of water
const int FL_JUMPRELEASED = 4096; // for jump debouncing
- float PM_multijump_checkjump();
- void PM_multijump();
-
.float watertype;
.float waterlevel;
.int items;
REGISTER_STAT(MULTIJUMP_MAXSPEED, float, autocvar_g_multijump_maxspeed)
REGISTER_STAT(MULTIJUMP_ADD, int, autocvar_g_multijump_add)
REGISTER_STAT(MULTIJUMP_SPEED, float, autocvar_g_multijump_speed)
+REGISTER_STAT(MULTIJUMP_COUNT, int /*doesn't matter*/)
REGISTER_STAT(MULTIJUMP, int, autocvar_g_multijump)
REGISTER_STAT(DOUBLEJUMP, int, autocvar_sv_doublejump)
#ifdef SVQC
-float g_bugrigs;
-float g_bugrigs_planar_movement;
-float g_bugrigs_planar_movement_car_jumping;
+bool g_bugrigs;
+bool g_bugrigs_planar_movement;
+bool g_bugrigs_planar_movement_car_jumping;
float g_bugrigs_reverse_spinning;
float g_bugrigs_reverse_speeding;
float g_bugrigs_reverse_stopping;
void door_draw(entity this)
{
- Movetype_Physics_NoMatchServer();
+ Movetype_Physics_NoMatchServer(this);
trigger_draw_generic(this);
}
#elif defined(CSQC)
void plat_draw(entity this)
{
- Movetype_Physics_NoMatchServer();
+ Movetype_Physics_NoMatchServer(this);
//Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
}
void train_draw(entity this)
{
//Movetype_Physics_NoMatchServer();
- Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
+ Movetype_Physics_MatchServer(this, autocvar_cl_projectiles_sloppy);
}
NET_HANDLE(ENT_CLIENT_TRAIN, bool isnew)
#elif defined(CSQC)
- void _Movetype_LinkEdict(float touch_triggers);
+ void _Movetype_LinkEdict(entity this, float touch_triggers);
#define SUB_ANGLES(s) (s).move_angles
#define SUB_VELOCITY move_velocity
void SUB_SETORIGIN(entity s, vector v)
{SELFPARAM();
s.move_origin = v;
- WITH(entity, self, s, _Movetype_LinkEdict(true));
+ _Movetype_LinkEdict(s, true);
}
#endif
void turret_gibboom();
void turret_gib_draw(entity this)
{
- Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
+ Movetype_Physics_MatchTicrate(self, autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
self.drawmask = MASK_NORMAL;
/* mins */ ATTRIB(EWheel, mins, vector, '-32 -32 0');
/* maxs */ ATTRIB(EWheel, maxs, vector, '32 32 48');
/* modelname */ ATTRIB(EWheel, mdl, string, "ewheel-base2.md3");
-/* model */ ATTRIB(EWheel, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(EWheel, head_model, string, strzone(strcat("models/turrets/", "ewheel-gun1.md3")));
+/* model */ ATTRIB_STRZONE(EWheel, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(EWheel, head_model, string, strcat("models/turrets/", "ewheel-gun1.md3"));
/* netname */ ATTRIB(EWheel, netname, string, "ewheel");
/* fullname */ ATTRIB(EWheel, turret_name, string, _("eWheel Turret"));
ATTRIB(EWheel, m_weapon, Weapon, WEP_EWHEEL);
/* mins */ ATTRIB(Flac, mins, vector, '-32 -32 0');
/* maxs */ ATTRIB(Flac, maxs, vector, '32 32 64');
/* modelname */ ATTRIB(Flac, mdl, string, "base.md3");
-/* model */ ATTRIB(Flac, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(Flac, head_model, string, strzone(strcat("models/turrets/", "flac.md3")));
+/* model */ ATTRIB_STRZONE(Flac, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(Flac, head_model, string, strcat("models/turrets/", "flac.md3"));
/* netname */ ATTRIB(Flac, netname, string, "flac");
/* fullname */ ATTRIB(Flac, turret_name, string, _("FLAC Cannon"));
ATTRIB(Flac, m_weapon, Weapon, WEP_FLAC);
/* mins */ ATTRIB(FusionReactor, mins, vector, '-34 -34 0');
/* maxs */ ATTRIB(FusionReactor, maxs, vector, '34 34 90');
/* modelname */ ATTRIB(FusionReactor, mdl, string, "base.md3");
-/* model */ ATTRIB(FusionReactor, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(FusionReactor, head_model, string, strzone(strcat("models/turrets/", "reactor.md3")));
+/* model */ ATTRIB_STRZONE(FusionReactor, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(FusionReactor, head_model, string, strcat("models/turrets/", "reactor.md3"));
/* netname */ ATTRIB(FusionReactor, netname, string, "fusionreactor");
/* fullname */ ATTRIB(FusionReactor, turret_name, string, _("Fusion Reactor"));
ENDCLASS(FusionReactor)
/* mins */ ATTRIB(Hellion, mins, vector, '-32 -32 0');
/* maxs */ ATTRIB(Hellion, maxs, vector, '32 32 64');
/* modelname */ ATTRIB(Hellion, mdl, string, "base.md3");
-/* model */ ATTRIB(Hellion, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(Hellion, head_model, string, strzone(strcat("models/turrets/", "hellion.md3")));
+/* model */ ATTRIB_STRZONE(Hellion, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(Hellion, head_model, string, strcat("models/turrets/", "hellion.md3"));
/* netname */ ATTRIB(Hellion, netname, string, "hellion");
/* fullname */ ATTRIB(Hellion, turret_name, string, _("Hellion Missile Turret"));
ATTRIB(Hellion, m_weapon, Weapon, WEP_HELLION);
/* mins */ ATTRIB(HunterKiller, mins, vector, '-32 -32 0');
/* maxs */ ATTRIB(HunterKiller, maxs, vector, '32 32 64');
/* modelname */ ATTRIB(HunterKiller, mdl, string, "base.md3");
-/* model */ ATTRIB(HunterKiller, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(HunterKiller, head_model, string, strzone(strcat("models/turrets/", "hk.md3")));
+/* model */ ATTRIB_STRZONE(HunterKiller, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(HunterKiller, head_model, string, strcat("models/turrets/", "hk.md3"));
/* netname */ ATTRIB(HunterKiller, netname, string, "hk");
/* fullname */ ATTRIB(HunterKiller, turret_name, string, _("Hunter-Killer Turret"));
ATTRIB(HunterKiller, m_weapon, Weapon, WEP_HK);
/* mins */ ATTRIB(MachineGunTurret, mins, vector, '-32 -32 0');
/* maxs */ ATTRIB(MachineGunTurret, maxs, vector, '32 32 64');
/* modelname */ ATTRIB(MachineGunTurret, mdl, string, "base.md3");
-/* model */ ATTRIB(MachineGunTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(MachineGunTurret, head_model, string, strzone(strcat("models/turrets/", "machinegun.md3")));
+/* model */ ATTRIB_STRZONE(MachineGunTurret, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(MachineGunTurret, head_model, string, strcat("models/turrets/", "machinegun.md3"));
/* netname */ ATTRIB(MachineGunTurret, netname, string, "machinegun");
/* fullname */ ATTRIB(MachineGunTurret, turret_name, string, _("Machinegun Turret"));
ATTRIB(MachineGunTurret, m_weapon, Weapon, WEP_TUR_MACHINEGUN);
/* mins */ ATTRIB(MLRSTurret, mins, vector, '-32 -32 0');
/* maxs */ ATTRIB(MLRSTurret, maxs, vector, '32 32 64');
/* modelname */ ATTRIB(MLRSTurret, mdl, string, "base.md3");
-/* model */ ATTRIB(MLRSTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(MLRSTurret, head_model, string, strzone(strcat("models/turrets/", "mlrs.md3")));
+/* model */ ATTRIB_STRZONE(MLRSTurret, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(MLRSTurret, head_model, string, strcat("models/turrets/", "mlrs.md3"));
/* netname */ ATTRIB(MLRSTurret, netname, string, "mlrs");
/* fullname */ ATTRIB(MLRSTurret, turret_name, string, _("MLRS Turret"));
ATTRIB(MLRSTurret, m_weapon, Weapon, WEP_TUR_MLRS);
/* mins */ ATTRIB(PhaserTurret, mins, vector, '-32 -32 0');
/* maxs */ ATTRIB(PhaserTurret, maxs, vector, '32 32 64');
/* modelname */ ATTRIB(PhaserTurret, mdl, string, "base.md3");
-/* model */ ATTRIB(PhaserTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(PhaserTurret, head_model, string, strzone(strcat("models/turrets/", "phaser.md3")));
+/* model */ ATTRIB_STRZONE(PhaserTurret, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(PhaserTurret, head_model, string, strcat("models/turrets/", "phaser.md3"));
/* netname */ ATTRIB(PhaserTurret, netname, string, "phaser");
/* fullname */ ATTRIB(PhaserTurret, turret_name, string, _("Phaser Cannon"));
ATTRIB(PhaserTurret, m_weapon, Weapon, WEP_PHASER);
/* mins */ ATTRIB(PlasmaTurret, mins, vector, '-32 -32 0');
/* maxs */ ATTRIB(PlasmaTurret, maxs, vector, '32 32 64');
/* modelname */ ATTRIB(PlasmaTurret, mdl, string, "base.md3");
-/* model */ ATTRIB(PlasmaTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(PlasmaTurret, head_model, string, strzone(strcat("models/turrets/", "plasma.md3")));
+/* model */ ATTRIB_STRZONE(PlasmaTurret, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(PlasmaTurret, head_model, string, strcat("models/turrets/", "plasma.md3"));
/* netname */ ATTRIB(PlasmaTurret, netname, string, "plasma");
/* fullname */ ATTRIB(PlasmaTurret, turret_name, string, _("Plasma Cannon"));
ATTRIB(PlasmaTurret, m_weapon, Weapon, WEP_PLASMA);
/* mins */ ATTRIB(DualPlasmaTurret, mins, vector, '-32 -32 0');
/* maxs */ ATTRIB(DualPlasmaTurret, maxs, vector, '32 32 64');
/* modelname */ ATTRIB(DualPlasmaTurret, mdl, string, "base.md3");
-/* model */ ATTRIB(DualPlasmaTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(DualPlasmaTurret, head_model, string, strzone(strcat("models/turrets/", "plasmad.md3")));
+/* model */ ATTRIB_STRZONE(DualPlasmaTurret, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(DualPlasmaTurret, head_model, string, strcat("models/turrets/", "plasmad.md3"));
/* netname */ ATTRIB(DualPlasmaTurret, netname, string, "plasma_dual");
/* fullname */ ATTRIB(DualPlasmaTurret, turret_name, string, _("Dual Plasma Cannon"));
ATTRIB(DualPlasmaTurret, m_weapon, Weapon, WEP_PLASMA_DUAL);
/* mins */ ATTRIB(TeslaCoil, mins, vector, '-60 -60 0');
/* maxs */ ATTRIB(TeslaCoil, maxs, vector, '60 60 128');
/* modelname */ ATTRIB(TeslaCoil, mdl, string, "tesla_base.md3");
-/* model */ ATTRIB(TeslaCoil, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(TeslaCoil, head_model, string, strzone(strcat("models/turrets/", "tesla_head.md3")));
+/* model */ ATTRIB_STRZONE(TeslaCoil, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(TeslaCoil, head_model, string, strcat("models/turrets/", "tesla_head.md3"));
/* netname */ ATTRIB(TeslaCoil, netname, string, "tesla");
/* fullname */ ATTRIB(TeslaCoil, turret_name, string, _("Tesla Coil"));
ATTRIB(TeslaCoil, m_weapon, Weapon, WEP_TESLA);
/* mins */ ATTRIB(WalkerTurret, mins, vector, '-70 -70 0');
/* maxs */ ATTRIB(WalkerTurret, maxs, vector, '70 70 95');
/* modelname */ ATTRIB(WalkerTurret, mdl, string, "walker_body.md3");
-/* model */ ATTRIB(WalkerTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
-/* head_model */ ATTRIB(WalkerTurret, head_model, string, strzone(strcat("models/turrets/", "walker_head_minigun.md3")));
+/* model */ ATTRIB_STRZONE(WalkerTurret, model, string, strcat("models/turrets/", this.mdl));
+/* head_model */ ATTRIB_STRZONE(WalkerTurret, head_model, string, strcat("models/turrets/", "walker_head_minigun.md3"));
/* netname */ ATTRIB(WalkerTurret, netname, string, "walker");
/* fullname */ ATTRIB(WalkerTurret, turret_name, string, _("Walker Turret"));
ATTRIB(WalkerTurret, m_weapon, Weapon, WEP_WALKER);
if(cvar_type(e.netname))
{
cvar_set(e.netname, e.message);
+ strunzone(e.netname);
+ strunzone(e.message);
remove(e);
++i;
}
{
shutdown_running = 1;
Shutdown();
+ shutdownhooks();
}
cvar_settemp_restore(); // this must be done LAST, but in any case
}
if(wasfreed(self))
return;
- Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
+ Movetype_Physics_MatchTicrate(self, autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
self.move_avelocity += randomvec() * 15;
self.renderflags = 0;
#endif
// client movement
-void viewloc_PlayerPhysics()
-{SELFPARAM();
- if(self.viewloc)
+void viewloc_PlayerPhysics(entity this)
+{
+ if(this.viewloc)
{
- vector oldmovement = self.movement;
- self.movement_x = oldmovement_y;
- self.movement_y = 0;
+ vector oldmovement = this.movement;
+ this.movement_x = oldmovement_y;
+ this.movement_y = 0;
- if(self.movement_x < 0)
- self.movement_x = -self.movement_x;
+ if(this.movement_x < 0)
+ this.movement_x = -this.movement_x;
vector level_start, level_end;
- level_start = self.viewloc.enemy.origin;
- level_end = self.viewloc.goalentity.origin;
+ level_start = this.viewloc.enemy.origin;
+ level_end = this.viewloc.goalentity.origin;
vector forward, backward;
forward = vectoangles(normalize(level_end - level_start));
backward = vectoangles(normalize(level_start - level_end));
- if(self.movement_x < 0) // left
- self.angles_y = backward_y;
- if(self.movement_x > 0) // right
- self.angles_y = forward_y;
+ if(this.movement_x < 0) // left
+ this.angles_y = backward_y;
+ if(this.movement_x > 0) // right
+ this.angles_y = forward_y;
if(oldmovement_x > 0)
#ifdef CSQC
input_angles_x =
#endif
- self.v_angle_x = self.angles_x = -50;
+ this.v_angle_x = this.angles_x = -50;
else if(oldmovement_x < 0)
#ifdef CSQC
input_angles_x =
#endif
- self.v_angle_x = self.angles_x = 50;
+ this.v_angle_x = this.angles_x = 50;
- //if(!PHYS_INPUT_BUTTON_CROUCH(self) && !IS_DUCKED(self))
+ //if(!PHYS_INPUT_BUTTON_CROUCH(this) && !IS_DUCKED(this))
#ifdef SVQC
- //self.BUTTON_CROUCH = (oldmovement_x < 0);
+ //this.BUTTON_CROUCH = (oldmovement_x < 0);
if (oldmovement.x < 0)
- self.BUTTON_CROUCH = true;
+ this.BUTTON_CROUCH = true;
#elif defined(CSQC)
if (oldmovement.x < 0)
{
input_buttons |= BIT(4);
- self.flags |= FL_DUCKED;
+ this.flags |= FL_DUCKED;
}
- //else { input_buttons &= ~16; self.flags &= ~FL_DUCKED; }
+ //else { input_buttons &= ~16; this.flags &= ~FL_DUCKED; }
#endif
}
}
vector old_camera_angle = '0 0 0';
void viewloc_SetViewLocation()
{
- entity view = CSQCModel_server2csqc(player_localentnum);
+ entity view = CSQCModel_server2csqc(player_localentnum - 1);
if (!view) return;
//NOTE: the "cam_" cvars sould probably be changed out with a spawnflag or an entity key. I have it like this for my testing -- Player_2
if(view.viewloc && !wasfreed(view.viewloc) && view.viewloc.enemy && view.viewloc.goalentity)
.entity viewloc;
-void viewloc_PlayerPhysics();
+void viewloc_PlayerPhysics(entity this);
#ifdef CSQC
if(a < ALPHA_MIN_VISIBLE) { remove(self); }
// WEAPONTODO: save this only once when creating the entity
- vector sw_color = getcsqcplayercolor(self.sv_entnum); // GetTeamRGB(GetPlayerColor(self.sv_entnum));
+ vector sw_color = getcsqcplayercolor(self.sv_entnum - 1); // GetTeamRGB(GetPlayerColor(self.sv_entnum));
// WEAPONTODO: trace to find what we actually hit
vector endpos = (self.sw_shotorg + (self.sw_shotdir * self.sw_distance));
string tex = "particles/lgbeam";
if(this.cnt)
tex = "particles/gauntletbeam";
- vector rgb = getcsqcplayercolor(this.sv_entnum);
+ vector rgb = getcsqcplayercolor(this.sv_entnum - 1);
rgb *= (1 + autocvar_cl_vaporizerbeam_colorboost);
float fail = (self.nextthink - time);
spawnfunc(weapon_vortex) { weapon_defaultspawnfunc(this, WEP_VORTEX); }
spawnfunc(weapon_nex) { spawnfunc_weapon_vortex(this); }
+REGISTER_MUTATOR(vortex_charge, true);
+
+MUTATOR_HOOKFUNCTION(vortex_charge, GetPressedKeys)
+{SELFPARAM();
+ // WEAPONTODO
+ float xyspeed = vlen(vec2(self.velocity));
+ if (self.weapon == WEP_VORTEX.m_id && WEP_CVAR(vortex, charge) && WEP_CVAR(vortex, charge_velocity_rate) && xyspeed > WEP_CVAR(vortex, charge_minspeed))
+ {
+ // add a maximum of charge_velocity_rate when going fast (f = 1), gradually increasing from minspeed (f = 0) to maxspeed
+ xyspeed = min(xyspeed, WEP_CVAR(vortex, charge_maxspeed));
+ float f = (xyspeed - WEP_CVAR(vortex, charge_minspeed)) / (WEP_CVAR(vortex, charge_maxspeed) - WEP_CVAR(vortex, charge_minspeed));
+ // add the extra charge
+ self.vortex_charge = min(1, self.vortex_charge + WEP_CVAR(vortex, charge_velocity_rate) * f * PHYS_INPUT_TIMELENGTH);
+ }
+}
+
void W_Vortex_Attack(Weapon thiswep, float issecondary)
{SELFPARAM();
float mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, myammo, charge;
#include "noise.qc"
#include "oo.qh"
#include "p2mathlib.qc"
-#include "player.qh"
#include "progname.qh"
#include "random.qc"
#include "registry.qh"
} \
} \
while (0)
+#define AL_delete(this) buf_del(this)
#define _AL_type__s() string
#define AL_gets(this, idx) bufstr_get(this, idx)
// Time processing and counting functions/macros
// ===============================================
-#define count_years_decs(time, decs) sprintf(ZCTX(_("CI_DEC^%s years")), ftos_decimals(time, decs))
+#define count_years_decs(time, decs) sprintf(CTX(_("CI_DEC^%s years")), ftos_decimals(time, decs))
#define count_years(time) \
count_fill(time, \
- ZCTX(_("CI_ZER^%d years")), /* zeroth */ \
- ZCTX(_("CI_FIR^%d year")), /* first */ \
- ZCTX(_("CI_SEC^%d years")), /* year */ \
- ZCTX(_("CI_THI^%d years")), /* third */ \
- ZCTX(_("CI_MUL^%d years"))) /* multi */
+ CTX(_("CI_ZER^%d years")), /* zeroth */ \
+ CTX(_("CI_FIR^%d year")), /* first */ \
+ CTX(_("CI_SEC^%d years")), /* year */ \
+ CTX(_("CI_THI^%d years")), /* third */ \
+ CTX(_("CI_MUL^%d years"))) /* multi */
-#define count_weeks_decs(time, decs) sprintf(ZCTX(_("CI_DEC^%s weeks")), ftos_decimals(time, decs))
+#define count_weeks_decs(time, decs) sprintf(CTX(_("CI_DEC^%s weeks")), ftos_decimals(time, decs))
#define count_weeks(time) \
count_fill(time, \
- ZCTX(_("CI_ZER^%d weeks")), /* zeroth */ \
- ZCTX(_("CI_FIR^%d week")), /* first */ \
- ZCTX(_("CI_SEC^%d weeks")), /* week */ \
- ZCTX(_("CI_THI^%d weeks")), /* third */ \
- ZCTX(_("CI_MUL^%d weeks"))) /* multi */
+ CTX(_("CI_ZER^%d weeks")), /* zeroth */ \
+ CTX(_("CI_FIR^%d week")), /* first */ \
+ CTX(_("CI_SEC^%d weeks")), /* week */ \
+ CTX(_("CI_THI^%d weeks")), /* third */ \
+ CTX(_("CI_MUL^%d weeks"))) /* multi */
-#define count_days_decs(time, decs) sprintf(ZCTX(_("CI_DEC^%s days")), ftos_decimals(time, decs))
+#define count_days_decs(time, decs) sprintf(CTX(_("CI_DEC^%s days")), ftos_decimals(time, decs))
#define count_days(time) \
count_fill(time, \
- ZCTX(_("CI_ZER^%d days")), /* zeroth */ \
- ZCTX(_("CI_FIR^%d day")), /* first */ \
- ZCTX(_("CI_SEC^%d days")), /* day */ \
- ZCTX(_("CI_THI^%d days")), /* third */ \
- ZCTX(_("CI_MUL^%d days"))) /* multi */
+ CTX(_("CI_ZER^%d days")), /* zeroth */ \
+ CTX(_("CI_FIR^%d day")), /* first */ \
+ CTX(_("CI_SEC^%d days")), /* day */ \
+ CTX(_("CI_THI^%d days")), /* third */ \
+ CTX(_("CI_MUL^%d days"))) /* multi */
-#define count_hours_decs(time, decs) sprintf(ZCTX(_("CI_DEC^%s hours")), ftos_decimals(time, decs))
+#define count_hours_decs(time, decs) sprintf(CTX(_("CI_DEC^%s hours")), ftos_decimals(time, decs))
#define count_hours(time) \
count_fill(time, \
- ZCTX(_("CI_ZER^%d hours")), /* zeroth */ \
- ZCTX(_("CI_FIR^%d hour")), /* first */ \
- ZCTX(_("CI_SEC^%d hours")), /* hour */ \
- ZCTX(_("CI_THI^%d hours")), /* third */ \
- ZCTX(_("CI_MUL^%d hours"))) /* multi */
+ CTX(_("CI_ZER^%d hours")), /* zeroth */ \
+ CTX(_("CI_FIR^%d hour")), /* first */ \
+ CTX(_("CI_SEC^%d hours")), /* hour */ \
+ CTX(_("CI_THI^%d hours")), /* third */ \
+ CTX(_("CI_MUL^%d hours"))) /* multi */
-#define count_minutes_decs(time, decs) sprintf(ZCTX(_("CI_DEC^%s minutes")), ftos_decimals(time, decs))
+#define count_minutes_decs(time, decs) sprintf(CTX(_("CI_DEC^%s minutes")), ftos_decimals(time, decs))
#define count_minutes(time) \
count_fill(time, \
- ZCTX(_("CI_ZER^%d minutes")), /* zeroth */ \
- ZCTX(_("CI_FIR^%d minute")), /* first */ \
- ZCTX(_("CI_SEC^%d minutes")), /* minute */ \
- ZCTX(_("CI_THI^%d minutes")), /* third */ \
- ZCTX(_("CI_MUL^%d minutes"))) /* multi */
+ CTX(_("CI_ZER^%d minutes")), /* zeroth */ \
+ CTX(_("CI_FIR^%d minute")), /* first */ \
+ CTX(_("CI_SEC^%d minutes")), /* minute */ \
+ CTX(_("CI_THI^%d minutes")), /* third */ \
+ CTX(_("CI_MUL^%d minutes"))) /* multi */
-#define count_seconds_decs(time, decs) sprintf(ZCTX(_("CI_DEC^%s seconds")), ftos_decimals(time, decs))
+#define count_seconds_decs(time, decs) sprintf(CTX(_("CI_DEC^%s seconds")), ftos_decimals(time, decs))
#define count_seconds(time) \
count_fill(time, \
- ZCTX(_("CI_ZER^%d seconds")), /* zeroth */ \
- ZCTX(_("CI_FIR^%d second")), /* first */ \
- ZCTX(_("CI_SEC^%d seconds")), /* second */ \
- ZCTX(_("CI_THI^%d seconds")), /* third */ \
- ZCTX(_("CI_MUL^%d seconds"))) /* multi */
+ CTX(_("CI_ZER^%d seconds")), /* zeroth */ \
+ CTX(_("CI_FIR^%d second")), /* first */ \
+ CTX(_("CI_SEC^%d seconds")), /* second */ \
+ CTX(_("CI_THI^%d seconds")), /* third */ \
+ CTX(_("CI_MUL^%d seconds"))) /* multi */
string count_ordinal(int interval)
{
return true;
}
-entity CSQCModel_server2csqc(int pl)
+/**
+ * @param i zero indexed player
+ */
+entity CSQCModel_server2csqc(int i)
{
- if (pl <= maxclients) return CSQCModel_players[pl - 1];
- LOG_WARNINGF("player out of bounds: %d\n", pl);
- return findfloat(NULL, entnum, pl);
+ if (i < maxclients) return CSQCModel_players[i];
+ ++i;
+ LOG_WARNINGF("player out of bounds: %d\n", i);
+ return findfloat(NULL, entnum, i);
}
#undef CSQCMODEL_ENDIF
#undef CSQCMODEL_IF
-entity CSQCModel_server2csqc(float pl);
+entity CSQCModel_server2csqc(int i);
.float csqcmodel_teleported;
// this is exported for custom frame animation code. Use with care.
#include "../../common/viewloc.qh"
float autocvar_cl_movement_errorcompensation = 0;
-int autocvar_cl_movement = 1;
// engine stuff
float pmove_onground; // weird engine flag we shouldn't really use but have to for now
}
void CSQC_ClientMovement_PlayerMove_Frame(entity this);
+void _Movetype_Physics_Frame(entity this, float movedt);
-void PM_Movement_Move(entity this)
+void Movetype_Physics_Spam(entity this) // optimized
{
- runstandardplayerphysics(this);
-#ifdef CSQC
- this.flags =
- ((this.pmove_flags & PMF_DUCKED) ? FL_DUCKED : 0) |
- (!(this.pmove_flags & PMF_JUMP_HELD) ? FL_JUMPRELEASED : 0) |
- ((this.pmove_flags & PMF_ONGROUND) ? FL_ONGROUND : 0);
-#endif
+ _Movetype_Physics_Frame(this, PHYS_INPUT_TIMELENGTH);
+ if(wasfreed(this))
+ return;
+
+ this.avelocity = this.move_avelocity;
+ this.velocity = this.move_velocity;
+ this.angles = this.move_angles;
+ setorigin(this, this.move_origin);
}
void CSQCPlayer_Physics(entity this)
{
- switch (autocvar_cl_movement)
+ if(autocvar_cl_movement)
{
- case 1: CSQC_ClientMovement_PlayerMove_Frame(this); break;
- case 2: PM_Movement_Move(this); break;
+ CSQC_ClientMovement_PlayerMove_Frame(this);
+
+ if(autocvar_cl_movement == 3)
+ {
+ this.move_origin = this.origin;
+ this.move_angles = this.angles;
+ this.move_movetype = MOVETYPE_WALK; // temp
+ this.move_velocity = this.velocity;
+ this.move_avelocity = this.avelocity;
+ Movetype_Physics_Spam(this);
+ }
}
}
setorigin(e, e.origin);
}
- const entity view = CSQCModel_server2csqc(player_localentnum);
+ const entity view = CSQCModel_server2csqc(player_localentnum - 1);
if (view)
{
if (view != csqcplayer)
#ifndef LIB_CSQCMODEL_CL_PLAYER_H
#define LIB_CSQCMODEL_CL_PLAYER_H
+int autocvar_cl_movement = 1;
+
entity csqcplayer;
float csqcplayer_status;
const int CSQCPLAYERSTATUS_UNPREDICTED = 0;
else return pow(e.(a) / e.(c), 1.0 / mean);
}
-#define MEAN_ACCUMULATE(prefix, v, w) mean_accumulate(self, prefix##_accumulator, prefix##_count, prefix##_mean, v, w)
-#define MEAN_EVALUATE(prefix) mean_evaluate(self, prefix##_accumulator, prefix##_count, prefix##_mean)
+#define MEAN_ACCUMULATE(s, prefix, v, w) mean_accumulate(s, prefix##_accumulator, prefix##_count, prefix##_mean, v, w)
+#define MEAN_EVALUATE(s, prefix) mean_evaluate(s, prefix##_accumulator, prefix##_count, prefix##_mean)
#define MEAN_DECLARE(prefix, m) float prefix##_mean = m; .float prefix##_count, prefix##_accumulator
/** Returns a random number between -1.0 and 1.0 */
class(cname).type name; \
INIT(cname) \
{ \
+ noref bool strzone; /* Error on strzone() calls. */ \
this.name = val; \
}
+#define ATTRIB_STRZONE(cname, name, type, val) \
+ class(cname).type name; \
+ INIT(cname) \
+ { \
+ if (this.name) \
+ strunzone(this.name); \
+ this.name = strzone(val); \
+ }
+
#define ATTRIBARRAY(cname, name, type, cnt) \
class(cname).type name[cnt];
+++ /dev/null
-#ifdef CSQC
-#ifndef PLAYER_H
- #define PLAYER_H
-
- #include "string.qh"
-
- #include "../client/main.qh"
- #include "../common/teams.qh"
-
- int GetPlayerColorForce(int i)
- {
- if (!teamplay) return 0;
- else return stof(getplayerkeyvalue(i, "colors")) & 15;
- }
-
- int GetPlayerColor(int i)
- {
- if (!playerslots[i].gotscores) // unconnected
- return NUM_SPECTATOR;
- else if (stof(getplayerkeyvalue(i, "frags")) == FRAGS_SPECTATOR) return NUM_SPECTATOR;
- else return GetPlayerColorForce(i);
- }
-
- string GetPlayerName(int i)
- {
- return ColorTranslateRGB(getplayerkeyvalue(i, "name"));
- }
-
-#endif
-#endif
#define _R_MAP(r, max) AL_declare(r); STATIC_INIT(r) { AL_init(r, max, NULL, e); }
#define _R_GET(r, i) AL_gete(r, i)
#define _R_SET(r, i, e) AL_sete(r, i, e)
+ #define _R_DEL(r) AL_delete(r)
#else
#define _R_MAP(r, max) entity r[max]
#define _R_GET(r, i) r[i]
#define _R_SET(r, i, e) r[i] = e
+ #define _R_DEL(r)
#endif
/**
const int id##_MAX = max; \
noref entity id##_first, id##_last; \
_R_MAP(_##id, id##_MAX); \
+ SHUTDOWN(id) { _R_DEL(_##id); } \
int id##_COUNT; \
entity _##id##_from(int i, entity null) { if (i >= 0 && i < id##_COUNT) { entity e = _R_GET(_##id, i); if (e) return e; } return null; }
#define static_init_late() CALL_ACCUMULATED_FUNCTION(__static_init_late)
void __static_init_precache() {}
#define static_init_precache() CALL_ACCUMULATED_FUNCTION(__static_init_precache)
+void __shutdown() {}
+#define shutdownhooks() CALL_ACCUMULATED_FUNCTION(__shutdown)
#define _STATIC_INIT(where, func) \
void _static_##func(); \
#define STATIC_INIT(func) _STATIC_INIT(__static_init, func)
#define STATIC_INIT_LATE(func) _STATIC_INIT(__static_init_late, func##_late)
#define PRECACHE(func) _STATIC_INIT(__static_init_precache, func##_precache)
+#define SHUTDOWN(func) _STATIC_INIT(__shutdown, func##_shutdown)
#endif
void XonoticPlayerModelSelector_showNotify(entity me)
{
+ // Reinitialize self.
+ me.destroy(me);
me.configureXonoticPlayerModelSelector(me);
}
#endif
int category_draw_count;
#define SLIST_CATEGORIES \
- SLIST_CATEGORY(CAT_FAVORITED, "", "", ZCTX(_("SLCAT^Favorites"))) \
- SLIST_CATEGORY(CAT_RECOMMENDED, "", "", ZCTX(_("SLCAT^Recommended"))) \
- SLIST_CATEGORY(CAT_NORMAL, "", "CAT_SERVERS", ZCTX(_("SLCAT^Normal Servers"))) \
- SLIST_CATEGORY(CAT_SERVERS, "CAT_NORMAL", "CAT_SERVERS", ZCTX(_("SLCAT^Servers"))) \
- SLIST_CATEGORY(CAT_XPM, "CAT_NORMAL", "CAT_SERVERS", ZCTX(_("SLCAT^Competitive Mode"))) \
- SLIST_CATEGORY(CAT_MODIFIED, "", "CAT_SERVERS", ZCTX(_("SLCAT^Modified Servers"))) \
- SLIST_CATEGORY(CAT_OVERKILL, "", "CAT_SERVERS", ZCTX(_("SLCAT^Overkill Mode"))) \
- SLIST_CATEGORY(CAT_INSTAGIB, "", "CAT_SERVERS", ZCTX(_("SLCAT^InstaGib Mode"))) \
- SLIST_CATEGORY(CAT_DEFRAG, "", "CAT_SERVERS", ZCTX(_("SLCAT^Defrag Mode")))
+ SLIST_CATEGORY(CAT_FAVORITED, "", "", CTX(_("SLCAT^Favorites"))) \
+ SLIST_CATEGORY(CAT_RECOMMENDED, "", "", CTX(_("SLCAT^Recommended"))) \
+ SLIST_CATEGORY(CAT_NORMAL, "", "CAT_SERVERS", CTX(_("SLCAT^Normal Servers"))) \
+ SLIST_CATEGORY(CAT_SERVERS, "CAT_NORMAL", "CAT_SERVERS", CTX(_("SLCAT^Servers"))) \
+ SLIST_CATEGORY(CAT_XPM, "CAT_NORMAL", "CAT_SERVERS", CTX(_("SLCAT^Competitive Mode"))) \
+ SLIST_CATEGORY(CAT_MODIFIED, "", "CAT_SERVERS", CTX(_("SLCAT^Modified Servers"))) \
+ SLIST_CATEGORY(CAT_OVERKILL, "", "CAT_SERVERS", CTX(_("SLCAT^Overkill Mode"))) \
+ SLIST_CATEGORY(CAT_INSTAGIB, "", "CAT_SERVERS", CTX(_("SLCAT^InstaGib Mode"))) \
+ SLIST_CATEGORY(CAT_DEFRAG, "", "CAT_SERVERS", CTX(_("SLCAT^Defrag Mode")))
#define SLIST_CATEGORY_AUTOCVAR(name) autocvar_menu_slist_categories_##name##_override
#define SLIST_CATEGORY(name,enoverride,dioverride,str) \
// returns 0 for: -1, -sqrt(0.5), 0 (angles that commonly happen with kbd)
}
-void anticheat_physics()
-{SELFPARAM();
+void anticheat_physics(entity this)
+{
float f;
// div0_evade -> SPECTATORS
- makevectors(self.v_angle);
- if(self.anticheat_div0_evade_offset == 0)
+ makevectors(this.v_angle);
+ if(this.anticheat_div0_evade_offset == 0)
{
f = fabs(anticheat_div0_evade_evasion_delta - floor(anticheat_div0_evade_evasion_delta) - 0.5) * 2; // triangle function
- self.anticheat_div0_evade_offset = servertime + sys_frametime * (3 * f - 1);
- self.anticheat_div0_evade_v_angle = self.v_angle;
- self.anticheat_div0_evade_forward_initial = v_forward;
- MEAN_ACCUMULATE(anticheat_div0_evade, 0, 1);
+ this.anticheat_div0_evade_offset = servertime + sys_frametime * (3 * f - 1);
+ this.anticheat_div0_evade_v_angle = this.v_angle;
+ this.anticheat_div0_evade_forward_initial = v_forward;
+ MEAN_ACCUMULATE(this, anticheat_div0_evade, 0, 1);
}
else
{
- if(time < self.anticheat_div0_evade_offset)
- self.anticheat_div0_evade_v_angle = self.v_angle;
- MEAN_ACCUMULATE(anticheat_div0_evade, 0.5 - 0.5 * (self.anticheat_div0_evade_forward_initial * v_forward), 1);
+ if(time < this.anticheat_div0_evade_offset)
+ this.anticheat_div0_evade_v_angle = this.v_angle;
+ MEAN_ACCUMULATE(this, anticheat_div0_evade, 0.5 - 0.5 * (this.anticheat_div0_evade_forward_initial * v_forward), 1);
}
- MEAN_ACCUMULATE(anticheat_div0_strafebot_old, movement_oddity(self.movement, self.anticheat_div0_strafebot_movement_prev), 1);
- self.anticheat_div0_strafebot_movement_prev = self.movement;
+ MEAN_ACCUMULATE(this, anticheat_div0_strafebot_old, movement_oddity(this.movement, this.anticheat_div0_strafebot_movement_prev), 1);
+ this.anticheat_div0_strafebot_movement_prev = this.movement;
// Note: this actually tries to detect snap-aim.
- if(vlen(self.anticheat_div0_strafebot_forward_prev) && time > self.anticheat_fixangle_endtime) {
- float cosangle = self.anticheat_div0_strafebot_forward_prev * v_forward;
+ if(vlen(this.anticheat_div0_strafebot_forward_prev) && time > this.anticheat_fixangle_endtime) {
+ float cosangle = this.anticheat_div0_strafebot_forward_prev * v_forward;
float angle = cosangle < -1 ? M_PI : cosangle > 1 ? 0 : acos(cosangle);
/*
if (angle >= 10 * M_PI / 180)
- printf("SNAP %s: %f for %f, %f since fixangle\n", self.netname, angle * 180 / M_PI, cosangle, time - self.anticheat_fixangle_endtime);
+ printf("SNAP %s: %f for %f, %f since fixangle\n", this.netname, angle * 180 / M_PI, cosangle, time - this.anticheat_fixangle_endtime);
*/
- MEAN_ACCUMULATE(anticheat_div0_strafebot_new, angle / M_PI, 1);
+ MEAN_ACCUMULATE(this, anticheat_div0_strafebot_new, angle / M_PI, 1);
if (autocvar_slowmo > 0) {
// Technically this is a NOP, as the engine should be ensuring
float dt = max(0.001, frametime) / autocvar_slowmo;
float anglespeed = angle / dt;
- MEAN_ACCUMULATE(anticheat_idle_snapaim_signal, anglespeed, dt);
- MEAN_ACCUMULATE(anticheat_idle_snapaim_noise, anglespeed, dt);
- MEAN_ACCUMULATE(anticheat_idle_snapaim_m2, anglespeed, dt);
- MEAN_ACCUMULATE(anticheat_idle_snapaim_m3, anglespeed, dt);
- MEAN_ACCUMULATE(anticheat_idle_snapaim_m4, anglespeed, dt);
- MEAN_ACCUMULATE(anticheat_idle_snapaim_m7, anglespeed, dt);
- MEAN_ACCUMULATE(anticheat_idle_snapaim_m10, anglespeed, dt);
+ MEAN_ACCUMULATE(this, anticheat_idle_snapaim_signal, anglespeed, dt);
+ MEAN_ACCUMULATE(this, anticheat_idle_snapaim_noise, anglespeed, dt);
+ MEAN_ACCUMULATE(this, anticheat_idle_snapaim_m2, anglespeed, dt);
+ MEAN_ACCUMULATE(this, anticheat_idle_snapaim_m3, anglespeed, dt);
+ MEAN_ACCUMULATE(this, anticheat_idle_snapaim_m4, anglespeed, dt);
+ MEAN_ACCUMULATE(this, anticheat_idle_snapaim_m7, anglespeed, dt);
+ MEAN_ACCUMULATE(this, anticheat_idle_snapaim_m10, anglespeed, dt);
}
}
- self.anticheat_div0_strafebot_forward_prev = v_forward;
+ this.anticheat_div0_strafebot_forward_prev = v_forward;
// generic speedhack detection: correlate anticheat_speedhack_movetime (UPDATED BEFORE THIS) and server time
- self.anticheat_speedhack_movetime_frac += frametime;
- f = floor(self.anticheat_speedhack_movetime_frac);
- self.anticheat_speedhack_movetime_frac -= f;
- self.anticheat_speedhack_movetime_count += f;
- self.anticheat_speedhack_movetime = self.anticheat_speedhack_movetime_frac + self.anticheat_speedhack_movetime_count;
- f = self.anticheat_speedhack_movetime - servertime;
- if(self.anticheat_speedhack_offset == 0)
- self.anticheat_speedhack_offset = f;
+ this.anticheat_speedhack_movetime_frac += frametime;
+ f = floor(this.anticheat_speedhack_movetime_frac);
+ this.anticheat_speedhack_movetime_frac -= f;
+ this.anticheat_speedhack_movetime_count += f;
+ this.anticheat_speedhack_movetime = this.anticheat_speedhack_movetime_frac + this.anticheat_speedhack_movetime_count;
+ f = this.anticheat_speedhack_movetime - servertime;
+ if(this.anticheat_speedhack_offset == 0)
+ this.anticheat_speedhack_offset = f;
else
{
- MEAN_ACCUMULATE(anticheat_speedhack, max(0, f - self.anticheat_speedhack_offset), 1);
- self.anticheat_speedhack_offset += (f - self.anticheat_speedhack_offset) * frametime * 0.1;
+ MEAN_ACCUMULATE(this, anticheat_speedhack, max(0, f - this.anticheat_speedhack_offset), 1);
+ this.anticheat_speedhack_offset += (f - this.anticheat_speedhack_offset) * frametime * 0.1;
}
// new generic speedhack detection
- if (self.anticheat_speedhack_lasttime > 0) {
- float dt = servertime - self.anticheat_speedhack_lasttime;
+ if (this.anticheat_speedhack_lasttime > 0) {
+ float dt = servertime - this.anticheat_speedhack_lasttime;
const float falloff = 0.2;
- self.anticheat_speedhack_accu *= exp(-dt * falloff);
- self.anticheat_speedhack_accu += frametime * falloff;
+ this.anticheat_speedhack_accu *= exp(-dt * falloff);
+ this.anticheat_speedhack_accu += frametime * falloff;
// NOTE: at cl_netfps x, this actually averages not to 1, but to 1/x * falloff / (1 - exp(-1/x * falloff))
// For 15 netfps (absolute minimum bearable), and 0.2 falloff, this is: 1.0067
- self.anticheat_speedhack_lasttime = servertime;
- MEAN_ACCUMULATE(anticheat_speedhack_m1, self.anticheat_speedhack_accu, frametime);
- MEAN_ACCUMULATE(anticheat_speedhack_m2, self.anticheat_speedhack_accu, frametime);
- MEAN_ACCUMULATE(anticheat_speedhack_m3, self.anticheat_speedhack_accu, frametime);
- MEAN_ACCUMULATE(anticheat_speedhack_m4, self.anticheat_speedhack_accu, frametime);
- MEAN_ACCUMULATE(anticheat_speedhack_m5, self.anticheat_speedhack_accu, frametime);
+ this.anticheat_speedhack_lasttime = servertime;
+ MEAN_ACCUMULATE(this, anticheat_speedhack_m1, this.anticheat_speedhack_accu, frametime);
+ MEAN_ACCUMULATE(this, anticheat_speedhack_m2, this.anticheat_speedhack_accu, frametime);
+ MEAN_ACCUMULATE(this, anticheat_speedhack_m3, this.anticheat_speedhack_accu, frametime);
+ MEAN_ACCUMULATE(this, anticheat_speedhack_m4, this.anticheat_speedhack_accu, frametime);
+ MEAN_ACCUMULATE(this, anticheat_speedhack_m5, this.anticheat_speedhack_accu, frametime);
} else {
- self.anticheat_speedhack_accu = 1;
- self.anticheat_speedhack_lasttime = servertime;
+ this.anticheat_speedhack_accu = 1;
+ this.anticheat_speedhack_lasttime = servertime;
}
}
return;
// TODO(divVerent): Use xonstat to acquire good thresholds.
GameLogEcho(strcat(":anticheat:_time:", ftos(self.playerid), ":", ftos(servertime - self.anticheat_jointime)));
- GameLogEcho(strcat(":anticheat:speedhack:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack), 240, 0, 9999))); // Actually this one seems broken.
- GameLogEcho(strcat(":anticheat:speedhack_m1:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack_m1), 240, 1.01, 1.25)));
- GameLogEcho(strcat(":anticheat:speedhack_m2:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack_m2), 240, 1.01, 1.25)));
- GameLogEcho(strcat(":anticheat:speedhack_m3:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack_m3), 240, 1.01, 1.25)));
- GameLogEcho(strcat(":anticheat:speedhack_m4:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack_m4), 240, 1.01, 1.25)));
- GameLogEcho(strcat(":anticheat:speedhack_m5:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack_m5), 240, 1.01, 1.25)));
- GameLogEcho(strcat(":anticheat:div0_strafebot_old:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_div0_strafebot_old), 120, 0.15, 0.4)));
- GameLogEcho(strcat(":anticheat:div0_strafebot_new:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_div0_strafebot_new), 120, 0.25, 0.8)));
- GameLogEcho(strcat(":anticheat:div0_evade:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_div0_evade), 120, 0.2, 0.5)));
- GameLogEcho(strcat(":anticheat:idle_snapaim:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_signal) - MEAN_EVALUATE(anticheat_idle_snapaim_noise), 120, 0, 9999)));
- GameLogEcho(strcat(":anticheat:idle_snapaim_signal:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_signal), 120, 0, 9999)));
- GameLogEcho(strcat(":anticheat:idle_snapaim_noise:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_noise), 120, 0, 9999)));
- GameLogEcho(strcat(":anticheat:idle_snapaim_m2:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_m2), 120, 0, 9999)));
- GameLogEcho(strcat(":anticheat:idle_snapaim_m3:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_m3), 120, 0, 9999)));
- GameLogEcho(strcat(":anticheat:idle_snapaim_m4:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_m4), 120, 0, 9999)));
- GameLogEcho(strcat(":anticheat:idle_snapaim_m7:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_m7), 120, 0, 9999)));
- GameLogEcho(strcat(":anticheat:idle_snapaim_m10:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_m10), 120, 0, 9999)));
+ GameLogEcho(strcat(":anticheat:speedhack:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_speedhack), 240, 0, 9999))); // Actually this one seems broken.
+ GameLogEcho(strcat(":anticheat:speedhack_m1:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_speedhack_m1), 240, 1.01, 1.25)));
+ GameLogEcho(strcat(":anticheat:speedhack_m2:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_speedhack_m2), 240, 1.01, 1.25)));
+ GameLogEcho(strcat(":anticheat:speedhack_m3:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_speedhack_m3), 240, 1.01, 1.25)));
+ GameLogEcho(strcat(":anticheat:speedhack_m4:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_speedhack_m4), 240, 1.01, 1.25)));
+ GameLogEcho(strcat(":anticheat:speedhack_m5:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_speedhack_m5), 240, 1.01, 1.25)));
+ GameLogEcho(strcat(":anticheat:div0_strafebot_old:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_div0_strafebot_old), 120, 0.15, 0.4)));
+ GameLogEcho(strcat(":anticheat:div0_strafebot_new:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_div0_strafebot_new), 120, 0.25, 0.8)));
+ GameLogEcho(strcat(":anticheat:div0_evade:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_div0_evade), 120, 0.2, 0.5)));
+ GameLogEcho(strcat(":anticheat:idle_snapaim:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_idle_snapaim_signal) - MEAN_EVALUATE(self, anticheat_idle_snapaim_noise), 120, 0, 9999)));
+ GameLogEcho(strcat(":anticheat:idle_snapaim_signal:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_idle_snapaim_signal), 120, 0, 9999)));
+ GameLogEcho(strcat(":anticheat:idle_snapaim_noise:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_idle_snapaim_noise), 120, 0, 9999)));
+ GameLogEcho(strcat(":anticheat:idle_snapaim_m2:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_idle_snapaim_m2), 120, 0, 9999)));
+ GameLogEcho(strcat(":anticheat:idle_snapaim_m3:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_idle_snapaim_m3), 120, 0, 9999)));
+ GameLogEcho(strcat(":anticheat:idle_snapaim_m4:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_idle_snapaim_m4), 120, 0, 9999)));
+ GameLogEcho(strcat(":anticheat:idle_snapaim_m7:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_idle_snapaim_m7), 120, 0, 9999)));
+ GameLogEcho(strcat(":anticheat:idle_snapaim_m10:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(self, anticheat_idle_snapaim_m10), 120, 0, 9999)));
}
float anticheat_getvalue(string id)
{SELFPARAM();
switch(id) {
case "_time": return servertime - self.anticheat_jointime;
- case "speedhack": return MEAN_EVALUATE(anticheat_speedhack);
- case "speedhack_m1": return MEAN_EVALUATE(anticheat_speedhack_m1);
- case "speedhack_m2": return MEAN_EVALUATE(anticheat_speedhack_m2);
- case "speedhack_m3": return MEAN_EVALUATE(anticheat_speedhack_m3);
- case "speedhack_m4": return MEAN_EVALUATE(anticheat_speedhack_m4);
- case "speedhack_m5": return MEAN_EVALUATE(anticheat_speedhack_m5);
- case "div0_strafebot_old": return MEAN_EVALUATE(anticheat_div0_strafebot_old);
- case "div0_strafebot_new": return MEAN_EVALUATE(anticheat_div0_strafebot_new);
- case "div0_evade": return MEAN_EVALUATE(anticheat_div0_evade);
- case "idle_snapaim": return MEAN_EVALUATE(anticheat_idle_snapaim_signal) - MEAN_EVALUATE(anticheat_idle_snapaim_noise);
- case "idle_snapaim_signal": return MEAN_EVALUATE(anticheat_idle_snapaim_signal);
- case "idle_snapaim_noise": return MEAN_EVALUATE(anticheat_idle_snapaim_noise);
- case "idle_snapaim_m2": return MEAN_EVALUATE(anticheat_idle_snapaim_m2);
- case "idle_snapaim_m3": return MEAN_EVALUATE(anticheat_idle_snapaim_m3);
- case "idle_snapaim_m4": return MEAN_EVALUATE(anticheat_idle_snapaim_m4);
- case "idle_snapaim_m7": return MEAN_EVALUATE(anticheat_idle_snapaim_m7);
- case "idle_snapaim_m10": return MEAN_EVALUATE(anticheat_idle_snapaim_m10);
+ case "speedhack": return MEAN_EVALUATE(self, anticheat_speedhack);
+ case "speedhack_m1": return MEAN_EVALUATE(self, anticheat_speedhack_m1);
+ case "speedhack_m2": return MEAN_EVALUATE(self, anticheat_speedhack_m2);
+ case "speedhack_m3": return MEAN_EVALUATE(self, anticheat_speedhack_m3);
+ case "speedhack_m4": return MEAN_EVALUATE(self, anticheat_speedhack_m4);
+ case "speedhack_m5": return MEAN_EVALUATE(self, anticheat_speedhack_m5);
+ case "div0_strafebot_old": return MEAN_EVALUATE(self, anticheat_div0_strafebot_old);
+ case "div0_strafebot_new": return MEAN_EVALUATE(self, anticheat_div0_strafebot_new);
+ case "div0_evade": return MEAN_EVALUATE(self, anticheat_div0_evade);
+ case "idle_snapaim": return MEAN_EVALUATE(self, anticheat_idle_snapaim_signal) - MEAN_EVALUATE(self, anticheat_idle_snapaim_noise);
+ case "idle_snapaim_signal": return MEAN_EVALUATE(self, anticheat_idle_snapaim_signal);
+ case "idle_snapaim_noise": return MEAN_EVALUATE(self, anticheat_idle_snapaim_noise);
+ case "idle_snapaim_m2": return MEAN_EVALUATE(self, anticheat_idle_snapaim_m2);
+ case "idle_snapaim_m3": return MEAN_EVALUATE(self, anticheat_idle_snapaim_m3);
+ case "idle_snapaim_m4": return MEAN_EVALUATE(self, anticheat_idle_snapaim_m4);
+ case "idle_snapaim_m7": return MEAN_EVALUATE(self, anticheat_idle_snapaim_m7);
+ case "idle_snapaim_m10": return MEAN_EVALUATE(self, anticheat_idle_snapaim_m10);
}
return -1;
}
void anticheat_report();
void anticheat_shutdown();
-void anticheat_physics();
+void anticheat_physics(entity this);
void anticheat_spectatecopy(entity spectatee);
void anticheat_prethink();
float autocvar_g_balance_contents_drowndelay;
int autocvar_g_balance_contents_playerdamage_drowning;
int autocvar_g_balance_contents_playerdamage_lava;
+int autocvar_g_balance_contents_playerdamage_lava_burn; // 10 is a nice value
+float autocvar_g_balance_contents_playerdamage_lava_burn_time = 2.5; // note: damage is total across this time (not by dps)
int autocvar_g_balance_contents_playerdamage_slime;
int autocvar_g_balance_contents_projectiledamage;
float autocvar_g_balance_damagepush_speedfactor;
string autocvar_g_banned_list;
bool autocvar_g_banned_list_idmode;
bool autocvar_g_botclip_collisions;
-bool autocvar_g_bugrigs;
bool autocvar_g_campaign;
#define autocvar_g_campaign_forceteam cvar("g_campaign_forceteam")
int autocvar_g_campaign_skill;
this.bot_attack = true;
this.monster_attack = true;
- this.spider_slowness = 0;
-
this.BUTTON_ATCK = this.BUTTON_JUMP = this.BUTTON_ATCK2 = false;
if (this.killcount == FRAGS_SPECTATOR) {
Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MOTD, getwelcomemessage());
}
- if(autocvar_g_bugrigs || (g_weaponarena_weapons == WEPSET(TUBA)))
+ if(g_weaponarena_weapons == WEPSET(TUBA))
stuffcmd(self, "cl_cmd settemp chase_active 1\n");
}
MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
}
+void __init_dedicated_server_shutdown() {
+ MapInfo_Shutdown();
+}
+
void Map_MarkAsRecent(string m);
float world_already_spawned;
void Nagger_Init();
);
}
-float WinningCondition_Race(float fraglimit)
-{
- float wc;
- entity p;
- float n, c;
-
- n = 0;
- c = 0;
- FOR_EACH_PLAYER(p)
- {
- ++n;
- if(p.race_completed)
- ++c;
- }
- if(n && (n == c))
- return WINNING_YES;
- wc = WinningCondition_Scores(fraglimit, 0);
-
- // ALWAYS initiate overtime, unless EVERYONE has finished the race!
- if(wc == WINNING_YES || wc == WINNING_STARTSUDDENDEATHOVERTIME)
- // do NOT support equality when the laps are all raced!
- return WINNING_STARTSUDDENDEATHOVERTIME;
- else
- return WINNING_NEVER;
-}
-
-float WinningCondition_QualifyingThenRace(float limit)
-{
- float wc;
- wc = WinningCondition_Scores(limit, 0);
-
- // NEVER initiate overtime
- if(wc == WINNING_YES || wc == WINNING_STARTSUDDENDEATHOVERTIME)
- {
- return WINNING_YES;
- }
-
- return wc;
-}
-
float WinningCondition_RanOutOfSpawns()
{
entity head;
{
LOG_INFO("NOTE: crashed before even initializing the world, not saving persistent data\n");
}
+ else
+ {
+ __init_dedicated_server_shutdown();
+ }
}
if(cvar("sv_allow_fullbright"))
serverflags |= SERVERFLAG_ALLOW_FULLBRIGHT;
- g_bugrigs = cvar("g_bugrigs");
- g_bugrigs_planar_movement = cvar("g_bugrigs_planar_movement");
- g_bugrigs_planar_movement_car_jumping = cvar("g_bugrigs_planar_movement_car_jumping");
- g_bugrigs_reverse_spinning = cvar("g_bugrigs_reverse_spinning");
- g_bugrigs_reverse_speeding = cvar("g_bugrigs_reverse_speeding");
- g_bugrigs_reverse_stopping = cvar("g_bugrigs_reverse_stopping");
- g_bugrigs_air_steering = cvar("g_bugrigs_air_steering");
- g_bugrigs_angle_smoothing = cvar("g_bugrigs_angle_smoothing");
- g_bugrigs_friction_floor = cvar("g_bugrigs_friction_floor");
- g_bugrigs_friction_brake = cvar("g_bugrigs_friction_brake");
- g_bugrigs_friction_air = cvar("g_bugrigs_friction_air");
- g_bugrigs_accel = cvar("g_bugrigs_accel");
- g_bugrigs_speed_ref = cvar("g_bugrigs_speed_ref");
- g_bugrigs_speed_pow = cvar("g_bugrigs_speed_pow");
- g_bugrigs_steer = cvar("g_bugrigs_steer");
-
g_instagib = cvar("g_instagib");
sv_clones = cvar("sv_clones");
string item_model_output;
MUTATOR_HOOKABLE(ItemModel, EV_ItemModel);
-/** called when a player presses the jump key */
-#define EV_PlayerJump(i, o) \
- /**/ i(float, player_multijump) \
- /**/ i(float, player_jumpheight) \
- /**/ o(float, player_multijump) \
- /**/ o(float, player_jumpheight) \
- /**/
-float player_multijump;
-float player_jumpheight;
-MUTATOR_HOOKABLE(PlayerJump, EV_PlayerJump);
-
/** called when someone was fragged by "self", and is expected to change frag_score to adjust scoring for the kill */
#define EV_GiveFragsForKill(i, o) \
/**/ i(entity, __self) \
/** TODO change this into a general PlayerPostThink hook? */
MUTATOR_HOOKABLE(GetPressedKeys, EV_NO_ARGS);
-/**
- * called before any player physics, may adjust variables for movement,
- * is run AFTER bot code and idle checking
- */
-MUTATOR_HOOKABLE(PlayerPhysics, EV_NO_ARGS);
-
/** is meant to call GetCvars_handle*(get_cvars_s, get_cvars_f, cvarfield, "cvarname") for cvars this mutator needs from the client */
#define EV_GetCvars(i, o) \
/**/ i(float, get_cvars_f) \
}
else if(CTF_SAMETEAM(toucher, flag) && (toucher.flagcarried) && DIFF_TEAM(toucher.flagcarried, flag) && is_not_monster)
ctf_Handle_Capture(flag, toucher, CAPTURE_NORMAL); // toucher just captured the enemies flag to his base
+ else if(CTF_DIFFTEAM(toucher, flag) && (toucher.flagcarried) && CTF_SAMETEAM(toucher.flagcarried, toucher) && (!toucher.ctf_captureshielded) && autocvar_g_ctf_flag_return_carrying && (time > toucher.next_take_time) && is_not_monster)
+ {
+ ctf_Handle_Return(toucher.flagcarried, toucher); // return their current flag
+ ctf_Handle_Pickup(flag, toucher, PICKUP_BASE); // now pickup the flag
+ }
else if(CTF_DIFFTEAM(toucher, flag) && (!toucher.flagcarried) && (!toucher.ctf_captureshielded) && (time > toucher.next_take_time) && is_not_monster)
ctf_Handle_Pickup(flag, toucher, PICKUP_BASE); // toucher just stole the enemies flag
break;
GameLogEcho(strcat(":race:", mode, ":", ((actor != world) ? (strcat(":", ftos(actor.playerid))) : "")));
}
+float WinningCondition_Race(float fraglimit)
+{
+ float wc;
+ entity p;
+ float n, c;
+
+ n = 0;
+ c = 0;
+ FOR_EACH_PLAYER(p)
+ {
+ ++n;
+ if(p.race_completed)
+ ++c;
+ }
+ if(n && (n == c))
+ return WINNING_YES;
+ wc = WinningCondition_Scores(fraglimit, 0);
+
+ // ALWAYS initiate overtime, unless EVERYONE has finished the race!
+ if(wc == WINNING_YES || wc == WINNING_STARTSUDDENDEATHOVERTIME)
+ // do NOT support equality when the laps are all raced!
+ return WINNING_STARTSUDDENDEATHOVERTIME;
+ else
+ return WINNING_NEVER;
+}
+
+float WinningCondition_QualifyingThenRace(float limit)
+{
+ float wc;
+ wc = WinningCondition_Scores(limit, 0);
+
+ // NEVER initiate overtime
+ if(wc == WINNING_YES || wc == WINNING_STARTSUDDENDEATHOVERTIME)
+ {
+ return WINNING_YES;
+ }
+
+ return wc;
+}
+
MUTATOR_HOOKFUNCTION(rc, PlayerPhysics)
{SELFPARAM();
self.race_movetime_frac += PHYS_INPUT_TIMELENGTH;
MUTATOR_HOOKFUNCTION(rc, CheckRules_World)
{
- if(g_race_qualifying == 2 && checkrules_timelimit >= 0)
+ if(checkrules_timelimit >= 0)
{
- ret_float = WinningCondition_QualifyingThenRace(checkrules_fraglimit);
- return true;
+ if(!g_race_qualifying)
+ {
+ ret_float = WinningCondition_QualifyingThenRace(checkrules_fraglimit);
+ return true;
+ }
+ else if(g_race_qualifying == 2)
+ {
+ ret_float = WinningCondition_QualifyingThenRace(checkrules_fraglimit);
+ return true;
+ }
}
return false;
{SELFPARAM();
self.(f) = stof(fgets(self.playerdemo_fh));
}
-float playerdemo_read()
-{SELFPARAM();
- if(self.playerdemo_mode != PLAYERDEMO_MODE_READING)
+float playerdemo_read(entity this)
+{
+ if(this.playerdemo_mode != PLAYERDEMO_MODE_READING)
return 0;
- if(self.playerdemo_time < 0)
+ if(this.playerdemo_time < 0)
return 1;
float t;
t = time;
- while(time >= self.playerdemo_time)
+ while(time >= this.playerdemo_time)
{
PLAYERDEMO_FIELDS(playerdemo_read_)
{
- time = self.playerdemo_time;
- PlayerPreThink();
+ time = this.playerdemo_time;
+ WITH(entity, this, this, PlayerPreThink());
// not running physics though... this is just so we can run weapon stuff
- PlayerPostThink();
+ WITH(entity, this, this, PlayerPostThink());
}
- self.playerdemo_time = stof(fgets(self.playerdemo_fh));
- if(self.playerdemo_time == 0)
+ this.playerdemo_time = stof(fgets(this.playerdemo_fh));
+ if(this.playerdemo_time == 0)
{
- self.playerdemo_time = -1;
+ this.playerdemo_time = -1;
return 1;
}
- self.playerdemo_time += self.playerdemo_starttime;
+ this.playerdemo_time += this.playerdemo_starttime;
}
- self.velocity = '0 0 0';
+ this.velocity = '0 0 0';
time = t;
return 1;
}
void playerdemo_init();
void playerdemo_shutdown();
void playerdemo_write();
-float playerdemo_read();
+float playerdemo_read(entity this);
void playerdemo_open_read(string f);
void playerdemo_open_write(string f);
sound (self, CH_PLAYER_SINGLE, SND_LAVA, VOL_BASE, ATTEN_NORM);
}
Damage (self, world, world, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_LAVA.m_id, self.origin, '0 0 0');
+ if(autocvar_g_balance_contents_playerdamage_lava_burn)
+ Fire_AddDamage(self, world, autocvar_g_balance_contents_playerdamage_lava_burn * self.waterlevel, autocvar_g_balance_contents_playerdamage_lava_burn_time * self.waterlevel, DEATH_LAVA.m_id);
}
else if (self.watertype == CONTENT_SLIME)
{
{
if(self.gravity)
{
- Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
+ Movetype_Physics_MatchServer(self, autocvar_cl_projectiles_sloppy);
if(self.move_flags & FL_ONGROUND)
{ // For some reason move_avelocity gets set to '0 0 0' here ...
self.oldorigin = self.origin;
{
if(self.gravity)
{
- Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
+ Movetype_Physics_MatchServer(self, autocvar_cl_projectiles_sloppy);
if(self.move_flags & FL_ONGROUND)
self.gravity = 0;
self.drawmask = MASK_NORMAL;
}
+void ItemRemove()
+{SELFPARAM();
+ if (self.mdl)
+ strunzone(self.mdl);
+}
+
NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
{
int sf = ReadByte();
if(self.ItemStatus & ITS_ANIMATE2)
self.move_avelocity = '0 -90 0';
}
+
+ self.entremove = ItemRemove;
+
return true;
}
if(modifications != "")
s = strcat(s, "^8\nactive modifications: ^3", modifications, "^8\n");
- if (cvar("g_nades"))
- s = strcat(s, "\n\n^3nades^8 are enabled, press 'g' to use them\n");
-
if(cache_lastmutatormsg != autocvar_g_mutatormsg)
{
if(cache_lastmutatormsg)