From 31f6ab4bb689aac5e84830cb5ea3aa3966ebc140 Mon Sep 17 00:00:00 2001 From: TimePath Date: Fri, 6 Nov 2015 19:40:11 +1100 Subject: [PATCH] Anim: cleanup --- qcsrc/Makefile | 1 + qcsrc/client/weapons/projectile.qc | 82 ++++++++++++++-------------- qcsrc/common/anim.qc | 23 +++++--- qcsrc/common/anim.qh | 47 +++++++++++++++- qcsrc/common/triggers/subs.qh | 9 --- qcsrc/common/weapons/all.qh | 15 +++-- qcsrc/common/weapons/weapon/rifle.qc | 4 +- qcsrc/lib/_all.inc | 1 + qcsrc/lib/enumclass.qh | 26 +++++++++ qcsrc/server/cl_player.qc | 1 + qcsrc/server/defs.qh | 1 - qcsrc/server/g_subs.qh | 4 -- qcsrc/server/weapons/weaponsystem.qc | 24 ++++---- qcsrc/server/weapons/weaponsystem.qh | 2 +- 14 files changed, 153 insertions(+), 87 deletions(-) create mode 100644 qcsrc/lib/enumclass.qh diff --git a/qcsrc/Makefile b/qcsrc/Makefile index 452dfc9a6..b5b77e09b 100644 --- a/qcsrc/Makefile +++ b/qcsrc/Makefile @@ -22,6 +22,7 @@ QCCFLAGS ?= \ -fftepp -flno -futf8 -fno-bail-on-werror -fftepp-predefs \ -frelaxed-switch -freturn-assignments \ $(QCCFLAGS_WATERMARK) \ + -DNDEBUG=1 \ $(QCCFLAGS_FEATURES) \ $(QCCFLAGS_EXTRA) diff --git a/qcsrc/client/weapons/projectile.qc b/qcsrc/client/weapons/projectile.qc index 9969a89f1..d220ccbf1 100644 --- a/qcsrc/client/weapons/projectile.qc +++ b/qcsrc/client/weapons/projectile.qc @@ -282,47 +282,47 @@ void Ent_Projectile() 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; diff --git a/qcsrc/common/anim.qc b/qcsrc/common/anim.qc index c2781c666..6a4dbe50f 100644 --- a/qcsrc/common/anim.qc +++ b/qcsrc/common/anim.qc @@ -1,4 +1,9 @@ -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. @@ -9,7 +14,7 @@ void setanim(entity e, vector anim, bool looping, bool override, int restart) 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); } } @@ -17,15 +22,18 @@ void setanim(entity e, vector anim, bool looping, bool override, int restart) 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) { @@ -36,7 +44,6 @@ void updateanim(entity e) } 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; } diff --git a/qcsrc/common/anim.qh b/qcsrc/common/anim.qh index c1dee151b..acf6735f3 100644 --- a/qcsrc/common/anim.qh +++ b/qcsrc/common/anim.qh @@ -1,7 +1,50 @@ #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 diff --git a/qcsrc/common/triggers/subs.qh b/qcsrc/common/triggers/subs.qh index 95cc59904..5e3f543fa 100644 --- a/qcsrc/common/triggers/subs.qh +++ b/qcsrc/common/triggers/subs.qh @@ -48,15 +48,6 @@ void SUB_VanishOrRemove (entity ent); .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; diff --git a/qcsrc/common/weapons/all.qh b/qcsrc/common/weapons/all.qh index 7379878ef..9959b64df 100644 --- a/qcsrc/common/weapons/all.qh +++ b/qcsrc/common/weapons/all.qh @@ -186,13 +186,16 @@ STATIC_INIT(register_weapons_done) .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); diff --git a/qcsrc/common/weapons/weapon/rifle.qc b/qcsrc/common/weapons/weapon/rifle.qc index 5aed6a7d4..a48765364 100644 --- a/qcsrc/common/weapons/weapon/rifle.qc +++ b/qcsrc/common/weapons/weapon/rifle.qc @@ -87,7 +87,7 @@ void W_Rifle_Attack2(void) } .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) @@ -116,7 +116,7 @@ void W_Rifle_BulletHail_Continue(Weapon thiswep, entity actor, .entity weaponent } } -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(); diff --git a/qcsrc/lib/_all.inc b/qcsrc/lib/_all.inc index 5a6b7394e..8a31df602 100644 --- a/qcsrc/lib/_all.inc +++ b/qcsrc/lib/_all.inc @@ -35,6 +35,7 @@ #include "cvar.qh" #include "defer.qh" #include "draw.qh" +#include "enumclass.qh" #include "file.qh" #include "functional.qh" #include "i18n.qh" diff --git a/qcsrc/lib/enumclass.qh b/qcsrc/lib/enumclass.qh new file mode 100644 index 000000000..2959565c5 --- /dev/null +++ b/qcsrc/lib/enumclass.qh @@ -0,0 +1,26 @@ +#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 diff --git a/qcsrc/server/cl_player.qc b/qcsrc/server/cl_player.qc index b8b3618de..cb99c022b 100644 --- a/qcsrc/server/cl_player.qc +++ b/qcsrc/server/cl_player.qc @@ -10,6 +10,7 @@ #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" diff --git a/qcsrc/server/defs.qh b/qcsrc/server/defs.qh index f85a94b3a..4e8188dfd 100644 --- a/qcsrc/server/defs.qh +++ b/qcsrc/server/defs.qh @@ -93,7 +93,6 @@ float server_is_dedicated; .float fade_rate; void() player_setupanimsformodel; -void setanim(entity e, vector anim, float looping, float override, float restart); .string mdl; diff --git a/qcsrc/server/g_subs.qh b/qcsrc/server/g_subs.qh index 149324f6d..3b9447c3e 100644 --- a/qcsrc/server/g_subs.qh +++ b/qcsrc/server/g_subs.qh @@ -10,10 +10,6 @@ void() SUB_Remove; spawnfunc(info_null); -void setanim(entity e, vector anim, float looping, float override, float restart); - -void updateanim(entity e); - /* ================== SUB_Remove diff --git a/qcsrc/server/weapons/weaponsystem.qc b/qcsrc/server/weapons/weaponsystem.qc index d35492473..9c0902507 100644 --- a/qcsrc/server/weapons/weaponsystem.qc +++ b/qcsrc/server/weapons/weaponsystem.qc @@ -39,9 +39,6 @@ float W_WeaponSpeedFactor() } -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(); @@ -309,13 +306,14 @@ bool weapon_prepareattack(Weapon thiswep, entity actor, .entity weaponentity, bo 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) @@ -331,18 +329,18 @@ void weapon_thinkf(entity actor, .entity weaponentity, float fr, float t, void(W 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); } } @@ -350,7 +348,7 @@ void weapon_thinkf(entity actor, .entity weaponentity, float fr, float t, void(W 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(); diff --git a/qcsrc/server/weapons/weaponsystem.qh b/qcsrc/server/weapons/weaponsystem.qh index dbede43e0..0000ac215 100644 --- a/qcsrc/server/weapons/weaponsystem.qh +++ b/qcsrc/server/weapons/weaponsystem.qh @@ -32,6 +32,6 @@ bool weapon_prepareattack_check(Weapon thiswep, entity actor, .entity weaponenti 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 -- 2.39.2