break;
}
- vector traceorigin = getplayerorigin(player_localentnum-1) + (eZ * getstati(STAT_VIEWHEIGHT));
+ vector traceorigin = entcs_receiver(player_localentnum - 1).origin + (eZ * getstati(STAT_VIEWHEIGHT));
- vecs = decompressShotOrigin(getstati(STAT_SHOTORG));
+ vecs = decompressShotOrigin(STAT(SHOTORG));
traceline(traceorigin, traceorigin + view_forward * MAX_SHOT_DISTANCE, mv, ta);
trueaimpoint = trace_endpos;
void HUD_Draw()
{
- if(STAT(FROZEN))
- drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, ((STAT(REVIVE_PROGRESS)) ? ('0.25 0.90 1' + ('1 0 0' * STAT(REVIVE_PROGRESS)) + ('0 1 1' * STAT(REVIVE_PROGRESS) * -1)) : '0.25 0.90 1'), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
- else if (STAT(HEALING_ORB)>time)
- drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, NADE_TYPE_HEAL.m_color, autocvar_hud_colorflash_alpha*STAT(HEALING_ORB_ALPHA), DRAWFLAG_ADDITIVE);
+ vector rgb = '0 0 0';
+ float a = 1;
+ if (MUTATOR_CALLHOOK(HUD_Draw_overlay))
+ {
+ rgb = MUTATOR_ARGV(0, vector);
+ a = MUTATOR_ARGV(0, float);
+ }
- else if(getstati(STAT_FROZEN))
++ else if(STAT(FROZEN))
+ {
- rgb = ((getstatf(STAT_REVIVE_PROGRESS)) ? ('0.25 0.90 1' + ('1 0 0' * getstatf(STAT_REVIVE_PROGRESS)) + ('0 1 1' * getstatf(STAT_REVIVE_PROGRESS) * -1)) : '0.25 0.90 1');
++ rgb = ((STAT(REVIVE_PROGRESS)) ? ('0.25 0.90 1' + ('1 0 0' * STAT(REVIVE_PROGRESS)) + ('0 1 1' * STAT(REVIVE_PROGRESS) * -1)) : '0.25 0.90 1');
+ }
+ drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, rgb, autocvar_hud_colorflash_alpha * a, DRAWFLAG_ADDITIVE);
if(!intermission)
- if(getstatf(STAT_NADE_TIMER) && autocvar_cl_nade_timer) // give nade top priority, as it's a matter of life and death
+ if(STAT(NADE_TIMER) && autocvar_cl_nade_timer) // give nade top priority, as it's a matter of life and death
{
- DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", getstatf(STAT_NADE_TIMER), '0.25 0.90 1' + ('1 0 0' * getstatf(STAT_NADE_TIMER)) - ('0 1 1' * getstatf(STAT_NADE_TIMER)), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
+ DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", STAT(NADE_TIMER), '0.25 0.90 1' + ('1 0 0' * STAT(NADE_TIMER)) - ('0 1 1' * STAT(NADE_TIMER)), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
drawstring_aspect(eY * 0.64 * vid_conheight, ((autocvar_cl_nade_timer == 2) ? _("Nade timer") : ""), eX * vid_conwidth + eY * 0.025 * vid_conheight, '1 1 1', 1, DRAWFLAG_NORMAL);
}
- else if(getstatf(STAT_REVIVE_PROGRESS))
+ else if(STAT(REVIVE_PROGRESS))
{
- DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", getstatf(STAT_REVIVE_PROGRESS), '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
+ DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", STAT(REVIVE_PROGRESS), '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
drawstring_aspect(eY * 0.64 * vid_conheight, _("Revival progress"), eX * vid_conwidth + eY * 0.025 * vid_conheight, '1 1 1', 1, DRAWFLAG_NORMAL);
}
--- /dev/null
- .int buffs;
+ #ifndef BUFFS_ALL_H
+ #define BUFFS_ALL_H
+ // Welcome to the stuff behind the scenes
+ // Below, you will find the list of buffs
+ // Add new buffs here!
+ // Note: Buffs also need spawnfuncs, which are set below
+
+ #include "../../../teams.qh"
+ #include "../../../util.qh"
+
+ REGISTER_WAYPOINT(Buff, _("Buff"), '1 0.5 0', 1);
+ REGISTER_RADARICON(Buff, 1);
+
+ REGISTRY(Buffs, BITS(4))
+ #define Buffs_from(i) _Buffs_from(i, BUFF_Null)
+ REGISTER_REGISTRY(Buffs)
+ REGISTRY_CHECK(Buffs)
+
+ #define REGISTER_BUFF(id) \
+ REGISTER(Buffs, BUFF_##id, m_id, NEW(Buff)); \
+ REGISTER_INIT_POST(BUFF_##id) { \
+ this.netname = this.m_name; \
+ this.m_itemid = BIT(this.m_id - 1); \
+ this.m_sprite = strzone(strcat("buff-", this.m_name)); \
+ } \
+ REGISTER_INIT(BUFF_##id)
+
+ #include "../../../items/item/pickup.qh"
+ CLASS(Buff, Pickup)
+ /** bit index */
+ ATTRIB(Buff, m_itemid, int, 0)
+ ATTRIB(Buff, m_name, string, "buff")
+ ATTRIB(Buff, m_color, vector, '1 1 1')
+ ATTRIB(Buff, m_prettyName, string, "Buff")
+ ATTRIB(Buff, m_skin, int, 0)
+ ATTRIB(Buff, m_sprite, string, "")
+ METHOD(Buff, display, void(entity this, void(string name, string icon) returns)) {
+ returns(this.m_prettyName, sprintf("/gfx/hud/%s/buff_%s", cvar_string("menu_skin"), this.m_name));
+ }
+ #ifdef SVQC
+ METHOD(Buff, m_time, float(Buff this))
+ { return cvar(strcat("g_buffs_", this.netname, "_time")); }
+ #endif
+ ENDCLASS(Buff)
+
+ #ifdef SVQC
++ // .int buffs = _STAT(BUFFS);
+ void buff_Init(entity ent);
+ void buff_Init_Compat(entity ent, entity replacement);
+ #define BUFF_SPAWNFUNC(e, b, t) spawnfunc(item_buff_##e) { \
+ self.buffs = b.m_itemid; \
+ self.team = t; \
+ buff_Init(self); \
+ }
+ #define BUFF_SPAWNFUNCS(e, b) \
+ BUFF_SPAWNFUNC(e, b, 0) \
+ BUFF_SPAWNFUNC(e##_team1, b, NUM_TEAM_1) \
+ BUFF_SPAWNFUNC(e##_team2, b, NUM_TEAM_2) \
+ BUFF_SPAWNFUNC(e##_team3, b, NUM_TEAM_3) \
+ BUFF_SPAWNFUNC(e##_team4, b, NUM_TEAM_4)
+ #define BUFF_SPAWNFUNC_Q3TA_COMPAT(o, r) spawnfunc(item_##o) { buff_Init_Compat(self, r); }
+ #else
+ #define BUFF_SPAWNFUNC(e, b, t)
+ #define BUFF_SPAWNFUNCS(e, b)
+ #define BUFF_SPAWNFUNC_Q3TA_COMPAT(o, r)
+ #endif
+
+ REGISTER_BUFF(Null);
+ BUFF_SPAWNFUNCS(random, BUFF_Null)
+
+ #include "all.inc"
+
+ #endif
#include "../../../triggers/target/music.qh"
#include "../../../gamemodes/all.qh"
- #include "../../../buffs/all.qh"
-.float buff_time;
+.float buff_time = _STAT(BUFF_TIME);
void buffs_DelayedInit();
REGISTER_MUTATOR(buffs, cvar("g_buffs"))
#ifdef SVQC
#include "buffs.qc"
#endif
- int allBuffs = getstati(STAT_BUFFS, 0, 24);
+
+ #ifdef IMPLEMENTATION
+
+ string BUFF_NAME(int i)
+ {
+ Buff b = Buffs_from(i);
+ return sprintf("%s%s", rgb_to_hexcolor(b.m_color), b.m_prettyName);
+ }
+
+ #ifndef MENUQC
+ REGISTER_MUTATOR(buffs_flight, true);
+ MUTATOR_HOOKFUNCTION(buffs_flight, IsFlying)
+ {
+ noref entity e = MUTATOR_ARGV(0, entity);
+ return BUFFS_STAT(e) & BUFF_FLIGHT.m_itemid;
+ }
+ #endif
+
+ #ifdef CSQC
+ REGISTER_MUTATOR(cl_buffs, true);
+ MUTATOR_HOOKFUNCTION(cl_buffs, HUD_Powerups_add)
+ {
- addPowerupItem(it.m_prettyName, strcat("buff_", it.m_name), it.m_color, bound(0, getstatf(STAT_BUFF_TIME) - time, 99), 60);
++ int allBuffs = STAT(BUFFS);
+ FOREACH(Buffs, it.m_itemid & allBuffs, LAMBDA(
++ addPowerupItem(it.m_prettyName, strcat("buff_", it.m_name), it.m_color, bound(0, STAT(BUFF_TIME) - time, 99), 60);
+ ));
+ }
+ MUTATOR_HOOKFUNCTION(cl_buffs, WP_Format)
+ {
+ entity this = MUTATOR_ARGV(0, entity);
+ string s = MUTATOR_ARGV(0, string);
+ if (s == WP_Buff.netname || s == RADARICON_Buff.netname)
+ {
+ Buff b = Buffs_from(this.wp_extra);
+ MUTATOR_ARGV(0, vector) = b.m_color;
+ MUTATOR_ARGV(0, string) = b.m_prettyName;
+ return true;
+ }
+ }
+
+ #endif
+ #endif
- #ifndef MUTATOR_NADES_H
- #define MUTATOR_NADES_H
+ #include "nades.qh"
- #ifdef SVQC
- #include "../../../../server/mutators/mutator/gamemode_freezetag.qc"
+ #ifdef IMPLEMENTATION
+
+ #ifndef MENUQC
+ entity Nade_TrailEffect(int proj, int nade_team)
+ {
+ switch (proj)
+ {
+ case PROJECTILE_NADE: return EFFECT_NADE_TRAIL(nade_team);
+ case PROJECTILE_NADE_BURN: return EFFECT_NADE_TRAIL_BURN(nade_team);
+ }
+
+ FOREACH(Nades, true, LAMBDA(
+ for (int j = 0; j < 2; j++)
+ {
+ if (it.m_projectile[j] == proj)
+ {
+ string trail = it.m_trail[j].eent_eff_name;
+ if (trail) return it.m_trail[j];
+ break;
+ }
+ }
+ ));
+
+ return EFFECT_Null;
+ }
#endif
- .entity nade;
- .entity fake_nade;
- .float nade_timer = _STAT(NADE_TIMER);
- .float nade_refire;
- .float bonus_nades = _STAT(NADE_BONUS);
- .float nade_special_time;
- .float bonus_nade_score = _STAT(NADE_BONUS_SCORE);
- .int nade_type = _STAT(NADE_BONUS_TYPE);
- .string pokenade_type;
- .entity nade_damage_target;
- .float cvar_cl_nade_type;
- .string cvar_cl_pokenade_type;
- .float toss_time;
- .float stat_healing_orb = _STAT(HEALING_ORB);
- .float stat_healing_orb_alpha = _STAT(HEALING_ORB_ALPHA);
- .float nade_show_particles;
-
- // Remove nades that are being thrown
- void nades_Clear(entity player);
-
- // Give a bonus grenade to a player
- void(entity player, float score) nades_GiveBonus;
-
- /**
- * called to adjust nade damage and force on hit
- */
- #define EV_Nade_Damage(i, o) \
- /** weapon */ i(entity, MUTATOR_ARGV_0_entity) \
- /** force */ i(vector, MUTATOR_ARGV_0_vector) \
- /**/ o(vector, MUTATOR_ARGV_0_vector) \
- /** damage */ i(float, MUTATOR_ARGV_0_float) \
- /**/ o(float, MUTATOR_ARGV_0_float) \
- /**/
- MUTATOR_HOOKABLE(Nade_Damage, EV_Nade_Damage);
+ #ifdef CSQC
+ REGISTER_MUTATOR(cl_nades, true);
+ MUTATOR_HOOKFUNCTION(cl_nades, HUD_Draw_overlay)
+ {
- if (getstatf(STAT_HEALING_ORB) <= time) return false;
++ if (STAT(HEALING_ORB) <= time) return false;
+ MUTATOR_ARGV(0, vector) = NADE_TYPE_HEAL.m_color;
- MUTATOR_ARGV(0, float) = getstatf(STAT_HEALING_ORB_ALPHA);
++ MUTATOR_ARGV(0, float) = STAT(HEALING_ORB_ALPHA);
+ return true;
+ }
+ MUTATOR_HOOKFUNCTION(cl_nades, Ent_Projectile)
+ {
+ if (self.cnt == PROJECTILE_NAPALM_FOUNTAIN)
+ {
+ self.modelindex = 0;
+ self.traileffect = EFFECT_FIREBALL.m_id;
+ return true;
+ }
+ if (Nade_FromProjectile(self.cnt) != NADE_TYPE_Null)
+ {
+ setmodel(self, MDL_PROJECTILE_NADE);
+ entity trail = Nade_TrailEffect(self.cnt, self.team);
+ if (trail.eent_eff_name) self.traileffect = trail.m_id;
+ return true;
+ }
+ }
+ MUTATOR_HOOKFUNCTION(cl_nades, EditProjectile)
+ {
+ if (self.cnt == PROJECTILE_NAPALM_FOUNTAIN)
+ {
+ loopsound(self, CH_SHOTS_SINGLE, SND(FIREBALL_FLY2), VOL_BASE, ATTEN_NORM);
+ self.mins = '-16 -16 -16';
+ self.maxs = '16 16 16';
+ }
+
+ entity nade_type = Nade_FromProjectile(self.cnt);
+ if (nade_type == NADE_TYPE_Null) return;
+ self.mins = '-16 -16 -16';
+ self.maxs = '16 16 16';
+ self.colormod = nade_type.m_color;
+ self.move_movetype = MOVETYPE_BOUNCE;
+ self.move_touch = func_null;
+ self.scale = 1.5;
+ self.avelocity = randomvec() * 720;
+
+ if (nade_type == NADE_TYPE_TRANSLOCATE || nade_type == NADE_TYPE_SPAWN)
+ self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
+ else
+ self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY;
+ }
+ bool Projectile_isnade(int p)
+ {
+ return Nade_FromProjectile(p) != NADE_TYPE_Null;
+ }
+ void DrawAmmoNades(vector myPos, vector mySize, bool draw_expanding, float expand_time)
+ {
- float bonusNades = getstatf(STAT_NADE_BONUS);
- float bonusProgress = getstatf(STAT_NADE_BONUS_SCORE);
- float bonusType = getstati(STAT_NADE_BONUS_TYPE);
++ float bonusNades = STAT(NADE_BONUS);
++ float bonusProgress = STAT(NADE_BONUS_SCORE);
++ float bonusType = STAT(NADE_BONUS_TYPE);
+ Nade def = Nades_from(bonusType);
+ vector nadeColor = def.m_color;
+ string nadeIcon = def.m_icon;
+
+ vector iconPos, textPos;
+
+ if(autocvar_hud_panel_ammo_iconalign)
+ {
+ iconPos = myPos + eX * 2 * mySize.y;
+ textPos = myPos;
+ }
+ else
+ {
+ iconPos = myPos;
+ textPos = myPos + eX * mySize.y;
+ }
+
+ if(bonusNades > 0 || bonusProgress > 0)
+ {
+ DrawNadeProgressBar(myPos, mySize, bonusProgress, nadeColor);
+
+ if(autocvar_hud_panel_ammo_text)
+ drawstring_aspect(textPos, ftos(bonusNades), eX * (2/3) * mySize.x + eY * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ if(draw_expanding)
+ drawpic_aspect_skin_expanding(iconPos, nadeIcon, '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, expand_time);
+ drawpic_aspect_skin(iconPos, nadeIcon, '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ }
+ }
#endif
- #ifdef IMPLEMENTATION
+ #ifdef SVQC
- #include "../../../nades/all.qh"
#include "../../../gamemodes/all.qh"
#include "../../../monsters/spawn.qh"
#include "../../../monsters/sv_monsters.qh"
--- /dev/null
-.float nade_timer;
+ #ifndef NADES_ALL_H
+ #define NADES_ALL_H
+
+ #include "../../../teams.qh"
+
+ // use slots 70-100
+ const int PROJECTILE_NADE = 71;
+ const int PROJECTILE_NADE_BURN = 72;
+ const int PROJECTILE_NADE_NAPALM = 73;
+ const int PROJECTILE_NADE_NAPALM_BURN = 74;
+ const int PROJECTILE_NAPALM_FOUNTAIN = 75;
+ const int PROJECTILE_NADE_ICE = 76;
+ const int PROJECTILE_NADE_ICE_BURN = 77;
+ const int PROJECTILE_NADE_TRANSLOCATE = 78;
+ const int PROJECTILE_NADE_SPAWN = 79;
+ const int PROJECTILE_NADE_HEAL = 80;
+ const int PROJECTILE_NADE_HEAL_BURN = 81;
+ const int PROJECTILE_NADE_MONSTER = 82;
+ const int PROJECTILE_NADE_MONSTER_BURN = 83;
+
+ REGISTRY(Nades, BITS(4))
+ #define Nades_from(i) _Nades_from(i, NADE_TYPE_Null)
+ REGISTER_REGISTRY(Nades)
+ REGISTRY_CHECK(Nades)
+
+ #define REGISTER_NADE(id) REGISTER(Nades, NADE_TYPE, id, m_id, NEW(Nade))
+
+ CLASS(Nade, Object)
+ ATTRIB(Nade, m_id, int, 0)
+ ATTRIB(Nade, m_color, vector, '0 0 0')
+ ATTRIB(Nade, m_name, string, _("Grenade"))
+ ATTRIB(Nade, m_icon, string, "nade_normal")
+ ATTRIBARRAY(Nade, m_projectile, int, 2)
+ ATTRIBARRAY(Nade, m_trail, entity, 2)
+ METHOD(Nade, display, void(entity this, void(string name, string icon) returns)) {
+ returns(this.m_name, sprintf("/gfx/hud/%s/%s", cvar_string("menu_skin"), this.m_icon));
+ }
+ ENDCLASS(Nade)
+
+ REGISTER_NADE(Null);
+
+ Nade Nade_FromProjectile(int proj)
+ {
+ FOREACH(Nades, true, LAMBDA(
+ for (int j = 0; j < 2; j++)
+ {
+ if (it.m_projectile[j] == proj) return it;
+ }
+ ));
+ return NADE_TYPE_Null;
+ }
+
+ #ifndef MENUQC
+ #include "effects.inc"
+ #endif
+
+ #include "nades.inc"
+
+ .float healer_lifetime;
+ .float healer_radius;
+
+ #ifdef SVQC
+
+ .entity nade;
+ .entity fake_nade;
-.float bonus_nades;
++.float nade_timer = _STAT(NADE_TIMER);
+ .float nade_refire;
-.float bonus_nade_score;
-.float nade_type;
++.float bonus_nades = _STAT(NADE_BONUS);
+ .float nade_special_time;
-.float stat_healing_orb;
-.float stat_healing_orb_alpha;
++.float bonus_nade_score = _STAT(NADE_BONUS_SCORE);
++.int nade_type = _STAT(NADE_BONUS_TYPE);
+ .string pokenade_type;
+ .entity nade_damage_target;
+ .float cvar_cl_nade_type;
+ .string cvar_cl_pokenade_type;
+ .float toss_time;
++.float stat_healing_orb = _STAT(HEALING_ORB);
++.float stat_healing_orb_alpha = _STAT(HEALING_ORB_ALPHA);
+ .float nade_show_particles;
+
+ bool healer_send(entity this, entity to, int sf);
+
+ // Remove nades that are being thrown
+ void nades_Clear(entity player);
+
+ // Give a bonus grenade to a player
+ void(entity player, float score) nades_GiveBonus;
+
+ /**
+ * called to adjust nade damage and force on hit
+ */
+ #define EV_Nade_Damage(i, o) \
+ /** weapon */ i(entity, MUTATOR_ARGV_0_entity) \
+ /** force */ i(vector, MUTATOR_ARGV_0_vector) \
+ /**/ o(vector, MUTATOR_ARGV_0_vector) \
+ /** damage */ i(float, MUTATOR_ARGV_0_float) \
+ /**/ o(float, MUTATOR_ARGV_0_float) \
+ /**/
+ MUTATOR_HOOKABLE(Nade_Damage, EV_Nade_Damage);
+
+ #endif
+
+ #endif
v >= PHYS_STOPSPEED * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION)
*/
}
- float addspeed = wishspeed - self.velocity * wishdir;
+ const float addspeed = wishspeed - this.velocity * wishdir;
if (addspeed > 0)
{
- float accelspeed = min(PHYS_ACCELERATE * PHYS_INPUT_TIMELENGTH * wishspeed, addspeed);
- self.velocity += accelspeed * wishdir;
+ const float accelspeed = min(PHYS_ACCELERATE * PHYS_INPUT_TIMELENGTH * wishspeed, addspeed);
+ this.velocity += accelspeed * wishdir;
}
- float g = PHYS_GRAVITY(this) * PHYS_ENTGRAVITY(self) * PHYS_INPUT_TIMELENGTH;
- const float g = PHYS_GRAVITY * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
++ const float g = PHYS_GRAVITY(this) * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
if (!(GAMEPLAYFIX_NOGRAVITYONGROUND))
- self.velocity_z -= g * (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1);
- if (self.velocity * self.velocity)
+ this.velocity_z -= g * (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1);
+ if (vdist(this.velocity, >, 0))
PM_ClientMovement_Move();
if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
- if (!IS_ONGROUND(self) || !GAMEPLAYFIX_NOGRAVITYONGROUND)
- self.velocity_z -= g * 0.5;
+ if (!IS_ONGROUND(this) || !GAMEPLAYFIX_NOGRAVITYONGROUND)
+ this.velocity_z -= g * 0.5;
}
void PM_air(float buttons_prev, float maxspd_mod)
maxspeed_mod *= PHYS_HIGHSPEED;
#ifdef SVQC
- Physics_UpdateStats(maxspeed_mod);
+ Physics_UpdateStats(this, maxspeed_mod);
- if (self.PlayerPhysplug)
- if (self.PlayerPhysplug())
+ if (this.PlayerPhysplug)
+ if (this.PlayerPhysplug())
return;
#endif
#define PHYS_DEAD(s) s.csqcmodel_isdead
- #define GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE boolean(moveflags & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE)
- #define GAMEPLAYFIX_NOGRAVITYONGROUND cvar("sv_gameplayfix_nogravityonground")
- #define GAMEPLAYFIX_Q2AIRACCELERATE cvar("sv_gameplayfix_q2airaccelerate")
- #define GAMEPLAYFIX_EASIERWATERJUMP getstati(STAT_GAMEPLAYFIX_EASIERWATERJUMP)
- #define GAMEPLAYFIX_DOWNTRACEONGROUND getstati(STAT_GAMEPLAYFIX_DOWNTRACEONGROUND)
- #define GAMEPLAYFIX_STEPMULTIPLETIMES getstati(STAT_GAMEPLAYFIX_STEPMULTIPLETIMES)
- #define GAMEPLAYFIX_UNSTICKPLAYERS getstati(STAT_GAMEPLAYFIX_UNSTICKPLAYERS)
- #define GAMEPLAYFIX_STEPDOWN getstati(STAT_GAMEPLAYFIX_STEPDOWN)
+ #define GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE (boolean(moveflags & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE))
+ #define GAMEPLAYFIX_NOGRAVITYONGROUND (boolean(moveflags & MOVEFLAG_NOGRAVITYONGROUND))
+ #define GAMEPLAYFIX_Q2AIRACCELERATE (boolean(moveflags & MOVEFLAG_Q2AIRACCELERATE))
- #define IS_DUCKED(s) !!(s.flags & FL_DUCKED)
+ #define IS_DUCKED(s) boolean(s.flags & FL_DUCKED)
#define SET_DUCKED(s) s.flags |= FL_DUCKED
#define UNSET_DUCKED(s) s.flags &= ~FL_DUCKED
#define SET_ONGROUND(s) s.flags |= FL_ONGROUND
#define UNSET_ONGROUND(s) s.flags &= ~FL_ONGROUND
- #define WAS_ONGROUND(s) !!(s.lastflags & FL_ONGROUND)
+ #define WAS_ONGROUND(s) boolean(s.lastflags & FL_ONGROUND)
#define ITEMS_STAT(s) (s).items
- #define BUFFS_STAT(s) getstati(STAT_BUFFS)
-
- #define PHYS_AMMO_FUEL(s) getstati(STAT_FUEL)
-
- #define PHYS_FROZEN(s) getstati(STAT_FROZEN)
-
- #define PHYS_DOUBLEJUMP getstati(STAT_DOUBLEJUMP)
-
- #define PHYS_BUGRIGS getstati(STAT_BUGRIGS)
- #define PHYS_BUGRIGS_ANGLE_SMOOTHING getstati(STAT_BUGRIGS_ANGLE_SMOOTHING)
- #define PHYS_BUGRIGS_PLANAR_MOVEMENT getstati(STAT_BUGRIGS_PLANAR_MOVEMENT)
- #define PHYS_BUGRIGS_REVERSE_SPEEDING getstati(STAT_BUGRIGS_REVERSE_SPEEDING)
- #define PHYS_BUGRIGS_FRICTION_FLOOR getstatf(STAT_BUGRIGS_FRICTION_FLOOR)
- #define PHYS_BUGRIGS_AIR_STEERING getstati(STAT_BUGRIGS_AIR_STEERING)
- #define PHYS_BUGRIGS_FRICTION_BRAKE getstatf(STAT_BUGRIGS_FRICTION_BRAKE)
- #define PHYS_BUGRIGS_ACCEL getstatf(STAT_BUGRIGS_ACCEL)
- #define PHYS_BUGRIGS_SPEED_REF getstatf(STAT_BUGRIGS_SPEED_REF)
- #define PHYS_BUGRIGS_SPEED_POW getstatf(STAT_BUGRIGS_SPEED_POW)
- #define PHYS_BUGRIGS_STEER getstatf(STAT_BUGRIGS_STEER)
- #define PHYS_BUGRIGS_FRICTION_AIR getstatf(STAT_BUGRIGS_FRICTION_AIR)
- #define PHYS_BUGRIGS_CAR_JUMPING getstatf(STAT_BUGRIGS_CAR_JUMPING)
- #define PHYS_BUGRIGS_REVERSE_SPINNING getstatf(STAT_BUGRIGS_REVERSE_SPINNING)
- #define PHYS_BUGRIGS_REVERSE_STOPPING getstatf(STAT_BUGRIGS_REVERSE_STOPPING)
#define PHYS_JUMPSPEEDCAP_MIN cvar_string("cl_jumpspeedcap_min")
#define PHYS_JUMPSPEEDCAP_MAX cvar_string("cl_jumpspeedcap_max")
#define SET_ONGROUND(s) s.flags |= FL_ONGROUND
#define UNSET_ONGROUND(s) s.flags &= ~FL_ONGROUND
- #define WAS_ONGROUND(s) !!((s).lastflags & FL_ONGROUND)
+ #define WAS_ONGROUND(s) boolean((s).lastflags & FL_ONGROUND)
#define ITEMS_STAT(s) s.items
- #define BUFFS_STAT(s) (s).buffs
-
- #define PHYS_AMMO_FUEL(s) s.ammo_fuel
-
- #define PHYS_FROZEN(s) s.frozen
-
- #define PHYS_DOUBLEJUMP autocvar_sv_doublejump
-
- #define PHYS_BUGRIGS g_bugrigs
- #define PHYS_BUGRIGS_ANGLE_SMOOTHING g_bugrigs_angle_smoothing
- #define PHYS_BUGRIGS_PLANAR_MOVEMENT g_bugrigs_planar_movement
- #define PHYS_BUGRIGS_REVERSE_SPEEDING g_bugrigs_reverse_speeding
- #define PHYS_BUGRIGS_FRICTION_FLOOR g_bugrigs_friction_floor
- #define PHYS_BUGRIGS_AIR_STEERING g_bugrigs_air_steering
- #define PHYS_BUGRIGS_FRICTION_BRAKE g_bugrigs_friction_brake
- #define PHYS_BUGRIGS_ACCEL g_bugrigs_accel
- #define PHYS_BUGRIGS_SPEED_REF g_bugrigs_speed_ref
- #define PHYS_BUGRIGS_SPEED_POW g_bugrigs_speed_pow
- #define PHYS_BUGRIGS_STEER g_bugrigs_steer
- #define PHYS_BUGRIGS_FRICTION_AIR g_bugrigs_friction_air
- #define PHYS_BUGRIGS_CAR_JUMPING g_bugrigs_planar_movement_car_jumping
- #define PHYS_BUGRIGS_REVERSE_SPINNING g_bugrigs_reverse_spinning
- #define PHYS_BUGRIGS_REVERSE_STOPPING g_bugrigs_reverse_stopping
#define PHYS_JUMPSPEEDCAP_MIN autocvar_sv_jumpspeedcap_min
#define PHYS_JUMPSPEEDCAP_MAX autocvar_sv_jumpspeedcap_max
// weapon sets
typedef vector WepSet;
- #define WEPSET(id) WepSet_FromWeapon(WEP_##id.m_id)
- WepSet WepSet_FromWeapon(int a);
#ifdef SVQC
-void WepSet_AddStat();
-void WepSet_AddStat_InMap();
void WriteWepSet(float dest, WepSet w);
#endif
charge = sqrt(charge); // divide evenly among trail spacing and alpha
particles_alphamin = particles_alphamax = particles_fade = charge;
- if (autocvar_cl_particles_oldvortexbeam && (STAT(ALLOW_OLDVORTEXBEAM) || isdemo()))
+ if(!MUTATOR_CALLHOOK(Particles_VortexBeam, shotorg, endpos))
- if(autocvar_cl_particles_oldvortexbeam && (getstati(STAT_ALLOW_OLDVORTEXBEAM) || isdemo()))
++ if(autocvar_cl_particles_oldvortexbeam && (STAT(ALLOW_OLDVORTEXBEAM) || isdemo()))
WarpZone_TrailParticles_WithMultiplier(world, particleeffectnum(EFFECT_VORTEX_BEAM_OLD), shotorg, endpos, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE);
else
WarpZone_TrailParticles_WithMultiplier(world, particleeffectnum(EFFECT_VORTEX_BEAM), shotorg, endpos, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE);
#undef pointparticles
#undef setmodel
+#undef STAT_FRAGLIMIT
+#undef STAT_TIMELIMIT
+#undef STAT_MOVEVARS_TICRATE
+#undef STAT_MOVEVARS_TIMESCALE
+#undef STAT_MOVEVARS_GRAVITY
+
#pragma noref 0
- #define ReadFloat() ReadCoord()
-
#endif
* } \
* REGISTER_INIT(FOO, id)
*
- * Don't forget to forward declare `initfunc` and call `REGISTER_REGISTRY`:
- * void RegisterFoos();
- * REGISTER_REGISTRY(RegisterFoos)
*
- * @param initfunc The global constructor to accumulate into
+ * @param registry The registry to add each entity to.
* @param ns Short for namespace, prefix for each global (ns##_##id)
- * @param array The array to add each entity to. Also requires `array##_first` and `array##_last` to be defined
* @param id The identifier of the current entity being registered
- * @param fld The field to store the current count into
+ * @param fld The field to store the locally unique unique entity id
* @param inst An expression to create a new instance, invoked for every registration
*/
- #define REGISTER(initfunc, ns, array, id, fld, inst) \
- entity ns##_##id; \
- REGISTER_INIT(ns, id) {} \
- REGISTER_INIT_POST(ns, id) {} \
- void Register_##ns##_##id() \
+ #define REGISTER(...) EVAL(OVERLOAD(REGISTER, __VA_ARGS__))
+ #define REGISTER_5(registry, ns, id, fld, inst) REGISTER_4(registry, ns##_##id, fld, inst)
+ #define REGISTER_4(registry, id, fld, inst) \
+ entity id; \
+ REGISTER_INIT(id) {} \
+ REGISTER_INIT_POST(id) {} \
+ void Register_##id() \
{ \
- if (array##_COUNT >= array##_MAX) LOG_FATALF("Registry capacity exceeded (%s)", ftos(array##_MAX)); \
- entity this = inst; \
- ns##_##id = this; \
+ if (registry##_COUNT >= registry##_MAX) LOG_FATALF("Registry capacity exceeded (%s)", ftos(registry##_MAX)); \
+ entity this = id = inst; \
this.registered_id = #id; \
- REGISTRY_PUSH(array, fld, this); \
- Register_##ns##_##id##_init(this); \
- Register_##ns##_##id##_init_post(this); \
- this.fld = registry##_COUNT; \
- _R_SET(_##registry, registry##_COUNT, this); \
- ++registry##_COUNT; \
- if (!registry##_first) registry##_first = this; \
- if (registry##_last) registry##_last.REGISTRY_NEXT = this; \
- registry##_last = this; \
++ REGISTRY_PUSH(registry, fld, this); \
+ Register_##id##_init(this); \
+ Register_##id##_init_post(this); \
} \
- ACCUMULATE_FUNCTION(initfunc, Register_##ns##_##id) \
- REGISTER_INIT(ns, id)
-
- #define REGISTRY_PUSH(array, fld, it) do { \
- it.fld = array##_COUNT; \
- _##array[array##_COUNT++] = it; \
- if (!array##_first) array##_first = it; \
- if (array##_last) array##_last.REGISTRY_NEXT = it; \
- array##_last = it; \
+ ACCUMULATE_FUNCTION(Register##registry, Register_##id) \
+ REGISTER_INIT(id)
+
++#define REGISTRY_PUSH(registry, fld, it) do { \
++ it.fld = registry##_COUNT; \
++ _R_SET(_##registry, registry##_COUNT, it); \
++ ++registry##_COUNT; \
++ if (!registry##_first) registry##_first = it; \
++ if (registry##_last) registry##_last.REGISTRY_NEXT = it; \
++ registry##_last = it; \
+} while (0)
+
+#define REGISTRY_RESERVE(registry, fld, id, suffix) do { \
+ entity e = new(registry_reserved); \
- e.registered_id = #id #suffix; \
++ e.registered_id = #id "/" #suffix; \
+ REGISTRY_PUSH(registry, fld, e); \
+} while (0)
+
+ #define REGISTER_INIT(id) [[accumulate]] void Register_##id##_init(entity this)
+ #define REGISTER_INIT_POST(id) [[accumulate]] void Register_##id##_init_post(entity this)
+
/** internal next pointer */
#define REGISTRY_NEXT enemy
.entity REGISTRY_NEXT;
#define getstat_int(id) getstati(id, 0, 24)
#define getstat_bool(id) boolean(getstati(id))
#define getstat_float(id) getstatf(id)
+ #define getstat_vector(id) vec3(getstat_float(id + 0), getstat_float(id + 1), getstat_float(id + 2))
+ #define getstat_vectori(id) vec3(getstat_int(id + 0), getstat_int(id + 1), getstat_int(id + 2))
#define _STAT(id) g_stat_##id
- #define REGISTER_STAT(id, type) \
- type _STAT(id); \
- REGISTER(Stats, STAT, id, m_id, new(stat)) \
+ #define REGISTER_STAT_2(id, T) \
+ T _STAT(id); \
- REGISTER(RegisterStats, STAT, Stats, id, m_id, new(stat)) \
++ REGISTER(Stats, STAT_##id, m_id, new(stat)) \
{ \
make_pure(this); \
- REGISTRY_RESERVE(Stats, m_id, id, _y); \
- REGISTRY_RESERVE(Stats, m_id, id, _z); \
+ if (#T == "vector" || #T == "vectori") { \
++ REGISTRY_RESERVE(Stats, m_id, STAT_##id, y); \
++ REGISTRY_RESERVE(Stats, m_id, STAT_##id, z); \
+ } \
} \
[[accumulate]] void stats_get() \
{ \
const int AS_INT = 2;
const int AS_FLOAT = 8;
+ .int __stat_null;
+ /** Prevent engine stats being sent */
+ STATIC_INIT(stats_clear)
+ {
+ int r = 32;
+ for (int i = 0, n = 256 - r; i < n; ++i) {
+ addstat(r + i, AS_INT, __stat_null);
+ }
+ }
+
#define _STAT(id) stat_##id
- #define REGISTER_STAT(id, type) \
- .type _STAT(id); \
- REGISTER(Stats, STAT, id, m_id, new(stat)) \
+ #define REGISTER_STAT_2(id, T) \
+ .T _STAT(id); \
- REGISTER(RegisterStats, STAT, Stats, id, m_id, new(stat)) \
++ REGISTER(Stats, STAT_##id, m_id, new(stat)) \
{ \
make_pure(this); \
- REGISTRY_RESERVE(Stats, m_id, id, _y); \
- REGISTRY_RESERVE(Stats, m_id, id, _z); \
+ if (#T == "vector" || #T == "vectori") { \
++ REGISTRY_RESERVE(Stats, m_id, STAT_##id, y); \
++ REGISTRY_RESERVE(Stats, m_id, STAT_##id, z); \
+ } \
} \
[[accumulate]] void stats_add() \
{ \
- addstat_##type(STAT_##id.m_id, _STAT(id)); \
+ addstat_##T(STAT_##id.m_id, _STAT(id)); \
}
+ void GlobalStats_update(entity this) {}
+ #define REGISTER_STAT_3(x, T, expr) \
+ REGISTER_STAT(x, T); \
+ [[accumulate]] void GlobalStats_update(entity this) { STAT(x, this) = (expr); } \
+ STATIC_INIT(worldstat_##x) { entity this = world; STAT(x, this) = (expr); }
#else
- #define REGISTER_STAT(id, type)
+ #define REGISTER_STAT_2(id, type)
+ #define REGISTER_STAT_3(x, T, expr)
#endif
-const int STATS_ENGINE_RESERVE = 32 + (8 * 3); // Not sure how to handle vector stats yet, reserve them too
+const int STATS_ENGINE_RESERVE = 32;
-REGISTRY(Stats, 220 - STATS_ENGINE_RESERVE)
+REGISTRY(Stats, 256 - STATS_ENGINE_RESERVE)
- REGISTER_REGISTRY(RegisterStats)
- REGISTRY_SORT(Stats, 0)
+ REGISTER_REGISTRY(Stats)
+ REGISTRY_SORT(Stats)
REGISTRY_CHECK(Stats)
STATIC_INIT(RegisterStats_renumber)
{
return false;
}
-.int buffs; // TODO: remove
++.int buffs = _STAT(BUFFS); // TODO: remove
+
void Obituary(entity attacker, entity inflictor, entity targ, int deathtype)
{
// Sanity check