-fftepp -flno -futf8 -fno-bail-on-werror -fftepp-predefs \
-frelaxed-switch -freturn-assignments \
$(QCCFLAGS_WATERMARK) \
+ -DNDEBUG=1 \
$(QCCFLAGS_FEATURES) \
$(QCCFLAGS_EXTRA)
self.traileffect = 0;
switch (self.cnt)
{
- #define CASE(id) case PROJECTILE_##id: setmodel(self, MDL_PROJECTILE_##id);
- CASE(ELECTRO) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
- CASE(ROCKET) self.traileffect = EFFECT_TR_ROCKET.m_id; self.scale = 2; break;
- CASE(CRYLINK) self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
- CASE(CRYLINK_BOUNCING) self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
- CASE(ELECTRO_BEAM) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
- CASE(GRENADE) self.traileffect = EFFECT_TR_GRENADE.m_id; break;
- CASE(GRENADE_BOUNCING) self.traileffect = EFFECT_TR_GRENADE.m_id; break;
- CASE(MINE) self.traileffect = EFFECT_TR_GRENADE.m_id; break;
- CASE(BLASTER) self.traileffect = EFFECT_Null.m_id; break;
- CASE(HLAC) self.traileffect = EFFECT_Null.m_id; break;
- CASE(PORTO_RED) self.traileffect = EFFECT_TR_WIZSPIKE.m_id; self.scale = 4; break;
- CASE(PORTO_BLUE) self.traileffect = EFFECT_TR_WIZSPIKE.m_id; self.scale = 4; break;
- CASE(HOOKBOMB) self.traileffect = EFFECT_TR_KNIGHTSPIKE.m_id; break;
- CASE(HAGAR) self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
- CASE(HAGAR_BOUNCING) self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
- CASE(NAPALM_FOUNTAIN) // fallthrough // sself.modelindex = 0; self.traileffect = _particleeffectnum("torch_small"); break;
- CASE(FIREBALL) self.modelindex = 0; self.traileffect = EFFECT_FIREBALL.m_id; break; // particle effect is good enough
- CASE(FIREMINE) self.modelindex = 0; self.traileffect = EFFECT_FIREMINE.m_id; break; // particle effect is good enough
- CASE(TAG) self.traileffect = EFFECT_TR_ROCKET.m_id; break;
- CASE(FLAC) self.scale = 0.4; self.traileffect = EFFECT_FLAC_TRAIL.m_id; break;
- CASE(SEEKER) self.traileffect = EFFECT_SEEKER_TRAIL.m_id; break;
-
- CASE(MAGE_SPIKE) self.traileffect = EFFECT_TR_VORESPIKE.m_id; break;
- CASE(SHAMBLER_LIGHTNING) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
-
- CASE(RAPTORBOMB) self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = EFFECT_Null.m_id; break;
- CASE(RAPTORBOMBLET) self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = EFFECT_Null.m_id; break;
- CASE(RAPTORCANNON) self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
-
- CASE(SPIDERROCKET) self.traileffect = EFFECT_SPIDERBOT_ROCKET_TRAIL.m_id; break;
- CASE(WAKIROCKET) self.traileffect = EFFECT_RACER_ROCKET_TRAIL.m_id; break;
- CASE(WAKICANNON) self.traileffect = EFFECT_Null.m_id; break;
-
- CASE(BUMBLE_GUN) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
- CASE(BUMBLE_BEAM) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
-
- CASE(RPC) self.traileffect = EFFECT_TR_ROCKET.m_id; break;
-
- CASE(ROCKETMINSTA_LASER) self.traileffect = EFFECT_ROCKETMINSTA_LASER(self.team).m_id; break;
-#undef CASE
+ #define HANDLE(id) case PROJECTILE_##id: setmodel(self, MDL_PROJECTILE_##id);
+ HANDLE(ELECTRO) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+ HANDLE(ROCKET) self.traileffect = EFFECT_TR_ROCKET.m_id; self.scale = 2; break;
+ HANDLE(CRYLINK) self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
+ HANDLE(CRYLINK_BOUNCING) self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
+ HANDLE(ELECTRO_BEAM) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+ HANDLE(GRENADE) self.traileffect = EFFECT_TR_GRENADE.m_id; break;
+ HANDLE(GRENADE_BOUNCING) self.traileffect = EFFECT_TR_GRENADE.m_id; break;
+ HANDLE(MINE) self.traileffect = EFFECT_TR_GRENADE.m_id; break;
+ HANDLE(BLASTER) self.traileffect = EFFECT_Null.m_id; break;
+ HANDLE(HLAC) self.traileffect = EFFECT_Null.m_id; break;
+ HANDLE(PORTO_RED) self.traileffect = EFFECT_TR_WIZSPIKE.m_id; self.scale = 4; break;
+ HANDLE(PORTO_BLUE) self.traileffect = EFFECT_TR_WIZSPIKE.m_id; self.scale = 4; break;
+ HANDLE(HOOKBOMB) self.traileffect = EFFECT_TR_KNIGHTSPIKE.m_id; break;
+ HANDLE(HAGAR) self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
+ HANDLE(HAGAR_BOUNCING) self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
+ HANDLE(NAPALM_FOUNTAIN) // fallthrough // sself.modelindex = 0; self.traileffect = _particleeffectnum("torch_small"); break;
+ HANDLE(FIREBALL) self.modelindex = 0; self.traileffect = EFFECT_FIREBALL.m_id; break; // particle effect is good enough
+ HANDLE(FIREMINE) self.modelindex = 0; self.traileffect = EFFECT_FIREMINE.m_id; break; // particle effect is good enough
+ HANDLE(TAG) self.traileffect = EFFECT_TR_ROCKET.m_id; break;
+ HANDLE(FLAC) self.scale = 0.4; self.traileffect = EFFECT_FLAC_TRAIL.m_id; break;
+ HANDLE(SEEKER) self.traileffect = EFFECT_SEEKER_TRAIL.m_id; break;
+
+ HANDLE(MAGE_SPIKE) self.traileffect = EFFECT_TR_VORESPIKE.m_id; break;
+ HANDLE(SHAMBLER_LIGHTNING) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+
+ HANDLE(RAPTORBOMB) self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = EFFECT_Null.m_id; break;
+ HANDLE(RAPTORBOMBLET) self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = EFFECT_Null.m_id; break;
+ HANDLE(RAPTORCANNON) self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
+
+ HANDLE(SPIDERROCKET) self.traileffect = EFFECT_SPIDERBOT_ROCKET_TRAIL.m_id; break;
+ HANDLE(WAKIROCKET) self.traileffect = EFFECT_RACER_ROCKET_TRAIL.m_id; break;
+ HANDLE(WAKICANNON) self.traileffect = EFFECT_Null.m_id; break;
+
+ HANDLE(BUMBLE_GUN) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+ HANDLE(BUMBLE_BEAM) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+
+ HANDLE(RPC) self.traileffect = EFFECT_TR_ROCKET.m_id; break;
+
+ HANDLE(ROCKETMINSTA_LASER) self.traileffect = EFFECT_ROCKETMINSTA_LASER(self.team).m_id; break;
+#undef HANDLE
default:
if (MUTATOR_CALLHOOK(Ent_Projectile, self))
break;
-void setanim(entity e, vector anim, bool looping, bool override, int restart)
+#include "anim.qh"
+
+/**
+ * @param anim x = startframe, y = numframes, z = framerate
+ */
+void anim_set(entity e, vector anim, bool looping, bool override, bool restart)
{
if (!anim) return; // no animation was given to us! We can't use this.
if (anim.z == e.animstate_framerate)
{
if (!restart) return;
- if (restart > 0 && anim.y == 1) // ZYM animation
+ if (anim.y == 1) // ZYM animation
BITXOR_ASSIGN(e.effects, EF_RESTARTANIM_BIT);
}
}
e.animstate_startframe = anim.x;
e.animstate_numframes = anim.y;
e.animstate_framerate = anim.z;
- e.animstate_starttime = servertime - 0.1 * frametime; // shift it a little bit into the past to prevent float inaccuracy hiccups
+ e.animstate_starttime = time - 0.1 * frametime; // shift it a little bit into the past to prevent float inaccuracy hiccups
e.animstate_endtime = e.animstate_starttime + e.animstate_numframes / e.animstate_framerate;
e.animstate_looping = looping;
e.animstate_override = override;
e.frame = e.animstate_startframe;
- e.frame1time = servertime;
+ e.frame1time = time;
}
-void updateanim(entity e)
+/**
+ * Update e.frame based on its animstate relative to time
+ */
+void anim_update(entity e)
{
if (time >= e.animstate_endtime)
{
}
e.animstate_override = false;
}
- e.frame = e.animstate_startframe + bound(0, (time - e.animstate_starttime) * e.animstate_framerate,
- e.animstate_numframes - 1);
- // print(ftos(time), " -> ", ftos(e.frame), "\n");
+ float frameofs = bound(0, (time - e.animstate_starttime) * e.animstate_framerate, e.animstate_numframes - 1);
+ e.frame = e.animstate_startframe + frameofs;
}
#ifndef ANIM_H
#define ANIM_H
-void setanim(entity e, vector anim, float looping, float override, float restart);
-void updateanim(entity e);
+// begin engine fields
+
+/** primary framegroup animation (strength = 1 - lerpfrac - lerpfrac3 - lerpfrac4) */
+.float frame;
+/** secondary framegroup animation (strength = lerpfrac) */
+.float frame2;
+/** tertiary framegroup animation (strength = lerpfrac3) */
+.float frame3;
+/** quaternary framegroup animation (strength = lerpfrac4) */
+.float frame4;
+
+/** strength of framegroup blend */
+.float lerpfrac;
+/** strength of framegroup blend */
+.float lerpfrac3;
+/** strength of framegroup blend */
+.float lerpfrac4;
+
+/** start time of framegroup animation */
+.float frame1time;
+/** start time of framegroup animation */
+.float frame2time;
+/** start time of framegroup animation */
+.float frame3time;
+/** start time of framegroup animation */
+.float frame4time;
+
+// end engine fields
+
+// player animation state
+
+.int animstate_startframe;
+.int animstate_numframes;
+.float animstate_framerate;
+.float animstate_starttime;
+.float animstate_endtime;
+/** whether to repeat */
+.bool animstate_looping;
+/** true for one cycle, then changed to false */
+.bool animstate_override;
+
+void anim_set(entity e, vector anim, bool looping, bool override, bool restart);
+#define setanim(...) anim_set(__VA_ARGS__)
+void anim_update(entity e);
+#define updateanim(...) anim_update(__VA_ARGS__)
#endif
.vector destvec;
.vector destvec2;
-// player animation state
-.float animstate_startframe;
-.float animstate_numframes;
-.float animstate_framerate;
-.float animstate_starttime;
-.float animstate_endtime;
-.float animstate_override;
-.float animstate_looping;
-
.float delay;
.float wait;
.float lip;
.vector anim_reload;
// static frame globals
-.int wframe;
-const float WFRAME_DONTCHANGE = -1;
-const float WFRAME_FIRE1 = 0;
-const float WFRAME_FIRE2 = 1;
-const float WFRAME_IDLE = 2;
-const float WFRAME_RELOAD = 3;
+ENUMCLASS(WFRAME)
+CASE(WFRAME, DONTCHANGE)
+CASE(WFRAME, FIRE1)
+CASE(WFRAME, FIRE2)
+CASE(WFRAME, IDLE)
+CASE(WFRAME, RELOAD)
+ENUMCLASS_END(WFRAME)
+
+.WFRAME wframe;
vector shotorg_adjust_values(vector vecs, bool y_is_right, bool visual, int algn);
void CL_WeaponEntity_SetModel(entity this, string name);
}
.void(void) rifle_bullethail_attackfunc;
-.float rifle_bullethail_frame;
+.WFRAME rifle_bullethail_frame;
.float rifle_bullethail_animtime;
.float rifle_bullethail_refire;
void W_Rifle_BulletHail_Continue(Weapon thiswep, entity actor, .entity weaponentity, int fire)
}
}
-void W_Rifle_BulletHail(.entity weaponentity, float mode, void(void) AttackFunc, float fr, float animtime, float refire)
+void W_Rifle_BulletHail(.entity weaponentity, float mode, void(void) AttackFunc, WFRAME fr, float animtime, float refire)
{SELFPARAM();
// if we get here, we have at least one bullet to fire
AttackFunc();
#include "cvar.qh"
#include "defer.qh"
#include "draw.qh"
+#include "enumclass.qh"
#include "file.qh"
#include "functional.qh"
#include "i18n.qh"
--- /dev/null
+#ifndef ENUMCLASS_H
+#define ENUMCLASS_H
+
+#include "oo.qh"
+
+// purpose: prevent transposed parameter passing
+
+#if NDEBUG
+
+// zero overhead mode, use this for releases
+
+#define ENUMCLASS(id) typedef int id; enum {
+#define CASE(class, id) class##_##id,
+#define ENUMCLASS_END(id) };
+
+#else
+
+// edict overhead mode, use this for type checking
+
+#define ENUMCLASS(id) CLASS(id, Object)
+#define CASE(class, id) class class##_##id; STATIC_INIT(class##_##id) { class##_##id = NEW(class); }
+#define ENUMCLASS_END(id) ENDCLASS(id)
+
+#endif
+
+#endif
#include "teamplay.qh"
#include "weapons/throwing.qh"
#include "command/common.qh"
+#include "../common/anim.qh"
#include "../common/animdecide.qh"
#include "../common/csqcmodel_settings.qh"
#include "../common/deathtypes/all.qh"
.float fade_rate;
void() player_setupanimsformodel;
-void setanim(entity e, vector anim, float looping, float override, float restart);
.string mdl;
spawnfunc(info_null);
-void setanim(entity e, vector anim, float looping, float override, float restart);
-
-void updateanim(entity e);
-
/*
==================
SUB_Remove
}
-void weapon_thinkf(entity actor, .entity weaponentity, float fr, float t, void(Weapon thiswep, entity actor,
- .entity weaponentity, int fire) func);
-
bool CL_Weaponentity_CustomizeEntityForClient()
{
SELFPARAM();
void wframe_send(entity actor, entity weaponentity, vector a, bool restartanim);
-void weapon_thinkf(entity actor, .entity weaponentity, float fr, float t, void(Weapon thiswep, entity actor,
+void weapon_thinkf(entity actor, .entity weaponentity, WFRAME fr, float t, void(Weapon thiswep, entity actor,
.entity weaponentity, int fire) func)
{
+ entity this = actor.(weaponentity);
bool restartanim;
if (fr == WFRAME_DONTCHANGE)
{
- fr = actor.(weaponentity).wframe;
+ fr = this.wframe;
restartanim = false;
}
else if (fr == WFRAME_IDLE)
vector or = v_right;
vector ou = v_up;
- if (actor.(weaponentity))
+ if (this)
{
- actor.(weaponentity).wframe = fr;
+ this.wframe = fr;
vector a = '0 0 0';
- if (fr == WFRAME_IDLE) a = actor.(weaponentity).anim_idle;
- else if (fr == WFRAME_FIRE1) a = actor.(weaponentity).anim_fire1;
- else if (fr == WFRAME_FIRE2) a = actor.(weaponentity).anim_fire2;
+ if (fr == WFRAME_IDLE) a = this.anim_idle;
+ else if (fr == WFRAME_FIRE1) a = this.anim_fire1;
+ else if (fr == WFRAME_FIRE2) a = this.anim_fire2;
else // if (fr == WFRAME_RELOAD)
- a = actor.(weaponentity).anim_reload;
+ a = this.anim_reload;
a.z *= g_weaponratefactor;
entity e; FOR_EACH_CLIENT(e) if (e == actor || (IS_SPEC(e) && e.enemy == actor)) {
- wframe_send(e, actor.(weaponentity), a, restartanim);
+ wframe_send(e, this, a, restartanim);
}
}
v_right = or;
v_up = ou;
- if (actor.weapon_think == w_ready && func != w_ready && actor.(weaponentity).state == WS_RAISE) backtrace(
+ if (actor.weapon_think == w_ready && func != w_ready && this.state == WS_RAISE) backtrace(
"Tried to override initial weapon think function - should this really happen?");
t *= W_WeaponRateFactor();
void weapon_prepareattack_do(entity actor, .entity weaponentity, float secondary, float attacktime);
-void weapon_thinkf(entity actor, .entity weaponentity, float fr, float t, void(Weapon thiswep, entity actor, .entity weaponentity, int fire) func);
+void weapon_thinkf(entity actor, .entity weaponentity, WFRAME fr, float t, void(Weapon thiswep, entity actor, .entity weaponentity, int fire) func);
#endif