From: TimePath Date: Sun, 29 Nov 2015 22:59:11 +0000 (+1100) Subject: Merge branch 'master' into TimePath/csqc_viewmodels X-Git-Tag: xonotic-v0.8.2~1601^2~7 X-Git-Url: https://git.xonotic.org/?a=commitdiff_plain;h=201f6309c92217b63dc34daf004fbb7424096eca;p=xonotic%2Fxonotic-data.pk3dir.git Merge branch 'master' into TimePath/csqc_viewmodels # Conflicts: # qcsrc/client/weapons/projectile.qc # qcsrc/common/stats.qh # qcsrc/common/weapons/all.qc # qcsrc/common/weapons/weapon.qh # qcsrc/server/defs.qh # qcsrc/server/g_subs.qh # qcsrc/server/g_world.qc --- 201f6309c92217b63dc34daf004fbb7424096eca diff --cc qcsrc/client/progs.inc index 12d43b5c4,4a6b58788..8c443568e --- a/qcsrc/client/progs.inc +++ b/qcsrc/client/progs.inc @@@ -25,9 -25,9 +25,10 @@@ #include "weapons/projectile.qc" // TODO +#include "../common/anim.qc" #include "../common/animdecide.qc" #include "../common/effects/effectinfo.qc" + #include "../common/ent_cs.qc" #include "../common/mapinfo.qc" #include "../common/movetypes/include.qc" #include "../common/net_notice.qc" diff --cc qcsrc/client/view.qc index 45629f206,c98400df5..a6d05d9a6 --- a/qcsrc/client/view.qc +++ b/qcsrc/client/view.qc @@@ -30,311 -29,6 +30,311 @@@ #include "../lib/warpzone/client.qh" #include "../lib/warpzone/common.qh" +#define EFMASK_CHEAP (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NODRAW | EF_NOSHADOW | EF_SELECTABLE | EF_TELEPORT_BIT) + +float autocvar_cl_viewmodel_scale; + +bool autocvar_cl_bobmodel; +float autocvar_cl_bobmodel_speed; +float autocvar_cl_bobmodel_side; +float autocvar_cl_bobmodel_up; + +float autocvar_cl_followmodel; +float autocvar_cl_followmodel_side_speed; +float autocvar_cl_followmodel_side_highpass; +float autocvar_cl_followmodel_side_highpass1; +float autocvar_cl_followmodel_side_limit; +float autocvar_cl_followmodel_side_lowpass; +float autocvar_cl_followmodel_up_speed; +float autocvar_cl_followmodel_up_highpass; +float autocvar_cl_followmodel_up_highpass1; +float autocvar_cl_followmodel_up_limit; +float autocvar_cl_followmodel_up_lowpass; + +float autocvar_cl_leanmodel; +float autocvar_cl_leanmodel_side_speed; +float autocvar_cl_leanmodel_side_highpass; +float autocvar_cl_leanmodel_side_highpass1; +float autocvar_cl_leanmodel_side_lowpass; +float autocvar_cl_leanmodel_side_limit; +float autocvar_cl_leanmodel_up_speed; +float autocvar_cl_leanmodel_up_highpass; +float autocvar_cl_leanmodel_up_highpass1; +float autocvar_cl_leanmodel_up_lowpass; +float autocvar_cl_leanmodel_up_limit; + +#define lowpass(value, frac, ref_store, ret) do \ +{ \ + float __frac = bound(0, frac, 1); \ + ret = ref_store = ref_store * (1 - __frac) + (value) * __frac; \ +} while (0) + +#define lowpass_limited(value, frac, limit, ref_store, ret) do \ +{ \ + float __ignore; lowpass(value, frac, ref_store, __ignore); \ + ret = ref_store = bound((value) - (limit), ref_store, (value) + (limit)); \ +} while (0) + +#define highpass(value, frac, ref_store, ret) do \ +{ \ + float __f; lowpass(value, frac, ref_store, __f); \ + ret = (value) - __f; \ +} while (0) + +#define highpass_limited(value, frac, limit, ref_store, ret) do \ +{ \ + float __f; lowpass_limited(value, frac, limit, ref_store, __f); \ + ret = (value) - __f; \ +} while (0) + +#define lowpass3(value, fracx, fracy, fracz, ref_store, ref_out) do \ +{ \ + lowpass(value.x, fracx, ref_store.x, ref_out.x); \ + lowpass(value.y, fracy, ref_store.y, ref_out.y); \ + lowpass(value.z, fracz, ref_store.z, ref_out.z); \ +} while (0) + +#define highpass3(value, fracx, fracy, fracz, ref_store, ref_out) do \ +{ \ + highpass(value.x, fracx, ref_store.x, ref_out.x); \ + highpass(value.y, fracy, ref_store.y, ref_out.y); \ + highpass(value.z, fracz, ref_store.z, ref_out.z); \ +} while (0) + +#define highpass3_limited(value, fracx, limitx, fracy, limity, fracz, limitz, ref_store, ref_out) do \ +{ \ + highpass_limited(value.x, fracx, limitx, ref_store.x, ref_out.x); \ + highpass_limited(value.y, fracy, limity, ref_store.y, ref_out.y); \ + highpass_limited(value.z, fracz, limitz, ref_store.z, ref_out.z); \ +} while (0) + +void viewmodel_animate(entity this) +{ + static float prevtime; - float frametime = (time - prevtime) * getstatf(STAT_MOVEVARS_TIMESCALE); ++ float frametime = (time - prevtime) * STAT(MOVEVARS_TIMESCALE); + prevtime = time; + + if (autocvar_chase_active) return; + if (getstati(STAT_HEALTH) <= 0) return; + - entity view = CSQCModel_server2csqc(player_localentnum); ++ entity view = CSQCModel_server2csqc(player_localentnum - 1); + + bool clonground = !(view.anim_implicit_state & ANIMIMPLICITSTATE_INAIR); + static bool oldonground; + static float hitgroundtime; + static float lastongroundtime; + if (clonground) + { + float f = time; // cl.movecmd[0].time + if (!oldonground) + hitgroundtime = f; + lastongroundtime = f; + } + oldonground = clonground; + + vector gunorg = '0 0 0', gunangles = '0 0 0'; + static vector gunorg_prev = '0 0 0', gunangles_prev = '0 0 0'; + + bool teleported = view.csqcmodel_teleported; + + // 1. if we teleported, clear the frametime... the lowpass will recover the previous value then + if (teleported) + { + // try to fix the first highpass; result is NOT + // perfect! TODO find a better fix + gunangles_prev = view_angles; + gunorg_prev = view_origin; + } + + static vector gunorg_highpass = '0 0 0'; + + // 2. for the gun origin, only keep the high frequency (non-DC) parts, which is "somewhat like velocity" + gunorg_highpass += gunorg_prev; + highpass3_limited(view_origin, + frametime * autocvar_cl_followmodel_side_highpass1, autocvar_cl_followmodel_side_limit, + frametime * autocvar_cl_followmodel_side_highpass1, autocvar_cl_followmodel_side_limit, + frametime * autocvar_cl_followmodel_up_highpass1, autocvar_cl_followmodel_up_limit, + gunorg_highpass, gunorg); + gunorg_prev = view_origin; + gunorg_highpass -= gunorg_prev; + + static vector gunangles_highpass = '0 0 0'; + + // in the highpass, we _store_ the DIFFERENCE to the actual view angles... + gunangles_highpass += gunangles_prev; + PITCH(gunangles_highpass) += 360 * floor((PITCH(view_angles) - PITCH(gunangles_highpass)) / 360 + 0.5); + YAW(gunangles_highpass) += 360 * floor((YAW(view_angles) - YAW(gunangles_highpass)) / 360 + 0.5); + ROLL(gunangles_highpass) += 360 * floor((ROLL(view_angles) - ROLL(gunangles_highpass)) / 360 + 0.5); + highpass3_limited(view_angles, + frametime * autocvar_cl_leanmodel_up_highpass1, autocvar_cl_leanmodel_up_limit, + frametime * autocvar_cl_leanmodel_side_highpass1, autocvar_cl_leanmodel_side_limit, + 0, 0, + gunangles_highpass, gunangles); + gunangles_prev = view_angles; + gunangles_highpass -= gunangles_prev; + + // 3. calculate the RAW adjustment vectors + gunorg.x *= (autocvar_cl_followmodel ? -autocvar_cl_followmodel_side_speed : 0); + gunorg.y *= (autocvar_cl_followmodel ? -autocvar_cl_followmodel_side_speed : 0); + gunorg.z *= (autocvar_cl_followmodel ? -autocvar_cl_followmodel_up_speed : 0); + + PITCH(gunangles) *= (autocvar_cl_leanmodel ? -autocvar_cl_leanmodel_up_speed : 0); + YAW(gunangles) *= (autocvar_cl_leanmodel ? -autocvar_cl_leanmodel_side_speed : 0); + ROLL(gunangles) = 0; + + static vector gunorg_adjustment_highpass; + static vector gunorg_adjustment_lowpass; + static vector gunangles_adjustment_highpass; + static vector gunangles_adjustment_lowpass; + + // 4. perform highpass/lowpass on the adjustment vectors (turning velocity into acceleration!) + // trick: we must do the lowpass LAST, so the lowpass vector IS the final vector! + highpass3(gunorg, + frametime * autocvar_cl_followmodel_side_highpass, + frametime * autocvar_cl_followmodel_side_highpass, + frametime * autocvar_cl_followmodel_up_highpass, + gunorg_adjustment_highpass, gunorg); + lowpass3(gunorg, + frametime * autocvar_cl_followmodel_side_lowpass, + frametime * autocvar_cl_followmodel_side_lowpass, + frametime * autocvar_cl_followmodel_up_lowpass, + gunorg_adjustment_lowpass, gunorg); + // we assume here: PITCH = 0, YAW = 1, ROLL = 2 + highpass3(gunangles, + frametime * autocvar_cl_leanmodel_up_highpass, + frametime * autocvar_cl_leanmodel_side_highpass, + 0, + gunangles_adjustment_highpass, gunangles); + lowpass3(gunangles, + frametime * autocvar_cl_leanmodel_up_lowpass, + frametime * autocvar_cl_leanmodel_side_lowpass, + 0, + gunangles_adjustment_lowpass, gunangles); + float xyspeed = bound(0, vlen(vec2(view.velocity)), 400); + + // vertical view bobbing code + // TODO: cl_bob + + // horizontal view bobbing code + // TODO: cl_bob2 + + // fall bobbing code + // causes the view to swing down and back up when touching the ground + // TODO: cl_bobfall + + // gun model bobbing code + if (autocvar_cl_bobmodel) + { + // calculate for swinging gun model + // the gun bobs when running on the ground, but doesn't bob when you're in the air. + // Sajt: I tried to smooth out the transitions between bob and no bob, which works + // for the most part, but for some reason when you go through a message trigger or + // pick up an item or anything like that it will momentarily jolt the gun. + vector forward, right, up; + float bspeed; + float t = 1; + float s = time * autocvar_cl_bobmodel_speed; + if (clonground) + { + if (time - hitgroundtime < 0.2) + { + // just hit the ground, speed the bob back up over the next 0.2 seconds + t = time - hitgroundtime; + t = bound(0, t, 0.2); + t *= 5; + } + } + else + { + // recently left the ground, slow the bob down over the next 0.2 seconds + t = time - lastongroundtime; + t = 0.2 - bound(0, t, 0.2); + t *= 5; + } + bspeed = xyspeed * 0.01; + MAKEVECTORS(makevectors, gunangles, forward, right, up); + float bobr = bspeed * autocvar_cl_bobmodel_side * autocvar_cl_viewmodel_scale * sin(s) * t; + gunorg += bobr * right; + float bobu = bspeed * autocvar_cl_bobmodel_up * autocvar_cl_viewmodel_scale * cos(s * 2) * t; + gunorg += bobu * up; + } + this.origin += view_forward * gunorg.x + view_right * gunorg.y + view_up * gunorg.z; + gunangles.x = -gunangles.x; // pitch was inverted, now that actually matters + this.angles += gunangles; +} + +.vector viewmodel_origin, viewmodel_angles; + +void viewmodel_draw(entity this) +{ + int mask = (intermission || (getstati(STAT_HEALTH) <= 0) || autocvar_chase_active) ? 0 : MASK_NORMAL; + float a = this.alpha; + int c = stof(getplayerkeyvalue(current_player, "colors")); + vector g = this.glowmod; // TODO: completely clientside: colormapPaletteColor(c & 0x0F, true) * 2; - entity me = CSQCModel_server2csqc(player_localentnum); ++ entity me = CSQCModel_server2csqc(player_localentnum - 1); + int fx = ((me.csqcmodel_effects & EFMASK_CHEAP) + | EF_NODEPTHTEST) + &~ (EF_FULLBRIGHT); // can mask team color, so get rid of it + for (entity e = this; e; e = e.weaponchild) + { + e.drawmask = mask; + e.alpha = a; + e.colormap = c; + e.glowmod = g; + e.csqcmodel_effects = fx; + WITH(entity, self, e, CSQCModel_Effects_Apply()); + } + { + static string name_last; + string name = Weapons_from(activeweapon).mdl; + if (name != name_last) + { + name_last = name; + CL_WeaponEntity_SetModel(this, name); + this.viewmodel_origin = this.origin; + this.viewmodel_angles = this.angles; + } + anim_update(this); + if (!this.animstate_override) + anim_set(this, this.anim_idle, true, false, false); + } - float eta = (getstatf(STAT_WEAPON_NEXTTHINK) - time); // TODO: / W_WeaponRateFactor(); ++ float eta = (STAT(WEAPON_NEXTTHINK) - time); // TODO: / W_WeaponRateFactor(); + float f = 0; // 0..1; 0: fully active + switch (this.state) + { + case WS_RAISE: + { + // entity newwep = Weapons_from(activeweapon); + float delay = 0.2; // TODO: newwep.switchdelay_raise; + f = eta / max(eta, delay); + break; + } + case WS_DROP: + { + // entity oldwep = Weapons_from(activeweapon); + float delay = 0.2; // TODO: newwep.switchdelay_drop; + f = 1 - eta / max(eta, delay); + break; + } + case WS_CLEAR: + { + f = 1; + break; + } + } + this.origin = this.viewmodel_origin; + this.angles = this.viewmodel_angles; + this.angles_x = (-90 * f * f); + viewmodel_animate(this); + setorigin(this, this.origin); +} + +entity viewmodel; +STATIC_INIT(viewmodel) { + viewmodel = new(viewmodel); + viewmodel.draw = viewmodel_draw; +} + entity porto; vector polyline[16]; void Porto_Draw(entity this) diff --cc qcsrc/client/weapons/projectile.qc index c423032fe,1591bad96..2100c3f5f --- a/qcsrc/client/weapons/projectile.qc +++ b/qcsrc/client/weapons/projectile.qc @@@ -279,47 -280,46 +280,46 @@@ NET_HANDLE(ENT_CLIENT_PROJECTILE, bool 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(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 --cc qcsrc/common/stats.qh index 68bfbe833,6825ff76b..be3e10f5e --- a/qcsrc/common/stats.qh +++ b/qcsrc/common/stats.qh @@@ -4,312 -4,256 +4,260 @@@ // Full list of all stat constants, included in a single location for easy reference // 255 is the current limit (MAX_CL_STATS - 1), engine will need to be modified if you wish to add more stats - const int MAX_CL_STATS = 256; - // -Wdouble-declaration - // const int STAT_HEALTH = 0; - // 1 empty? - const int STAT_WEAPON = 2; - // -Wdouble-declaration - // const int STAT_AMMO = 3; - // -Wdouble-declaration - // const int STAT_ARMOR = 4; - // -Wdouble-declaration - // const int STAT_WEAPONFRAME = 5; - // -Wdouble-declaration - // const int STAT_SHELLS = 6; - // -Wdouble-declaration - // const int STAT_NAILS = 7; - // -Wdouble-declaration - // const int STAT_ROCKETS = 8; - // -Wdouble-declaration - // const int STAT_CELLS = 9; - // -Wdouble-declaration - // const int STAT_ACTIVEWEAPON = 10; - // -Wdouble-declaration - // const int STAT_TOTALSECRETS = 11; - // -Wdouble-declaration - // const int STAT_TOTALMONSTERS = 12; - // -Wdouble-declaration - // const int STAT_SECRETS = 13; - // -Wdouble-declaration - // const int STAT_MONSTERS = 14; - // -Wdouble-declaration - // const int STAT_ITEMS = 15; - // -Wdouble-declaration - // const int STAT_VIEWHEIGHT = 16; - // 17 empty? - // 18 empty? - // 19 empty? - // 20 empty? - const int STAT_VIEWZOOM = 21; - // 22 empty? - // 23 empty? - // 24 empty? - // 25 empty? - // 26 empty? - // 27 empty? - // 28 empty? - // 29 empty? - // 30 empty? - // 31 empty? - const int STAT_KH_KEYS = 32; - const int STAT_CTF_STATE = 33; - // 34 empty? - const int STAT_WEAPONS = 35; - const int STAT_SWITCHWEAPON = 36; - const int STAT_GAMESTARTTIME = 37; - const int STAT_STRENGTH_FINISHED = 38; - const int STAT_INVINCIBLE_FINISHED = 39; - // 40 empty? - const int STAT_ARC_HEAT = 41; - const int STAT_PRESSED_KEYS = 42; - const int STAT_ALLOW_OLDVORTEXBEAM = 43; // this stat could later contain some other bits of info, like, more server-side particle config - const int STAT_FUEL = 44; - const int STAT_NB_METERSTART = 45; - const int STAT_SHOTORG = 46; // compressShotOrigin - const int STAT_LEADLIMIT = 47; - const int STAT_WEAPON_CLIPLOAD = 48; - const int STAT_WEAPON_CLIPSIZE = 49; - const int STAT_VORTEX_CHARGE = 50; - const int STAT_LAST_PICKUP = 51; - const int STAT_HUD = 52; - const int STAT_VORTEX_CHARGEPOOL = 53; - const int STAT_HIT_TIME = 54; - const int STAT_DAMAGE_DEALT_TOTAL = 55; - const int STAT_TYPEHIT_TIME = 56; - const int STAT_LAYED_MINES = 57; - const int STAT_HAGAR_LOAD = 58; - const int STAT_SWITCHINGWEAPON = 59; - const int STAT_SUPERWEAPONS_FINISHED = 60; - const int STAT_VEHICLESTAT_HEALTH = 61; - const int STAT_VEHICLESTAT_SHIELD = 62; - const int STAT_VEHICLESTAT_ENERGY = 63; - const int STAT_VEHICLESTAT_AMMO1 = 64; - const int STAT_VEHICLESTAT_RELOAD1 = 65; - const int STAT_VEHICLESTAT_AMMO2 = 66; - const int STAT_VEHICLESTAT_RELOAD2 = 67; - const int STAT_VEHICLESTAT_W2MODE = 68; - const int STAT_NADE_TIMER = 69; - const int STAT_SECRETS_TOTAL = 70; - const int STAT_SECRETS_FOUND = 71; - const int STAT_RESPAWN_TIME = 72; - const int STAT_ROUNDSTARTTIME = 73; - const int STAT_WEAPONS2 = 74; - const int STAT_WEAPONS3 = 75; - const int STAT_MONSTERS_TOTAL = 76; - const int STAT_MONSTERS_KILLED = 77; - const int STAT_BUFFS = 78; - const int STAT_NADE_BONUS = 79; - const int STAT_NADE_BONUS_TYPE = 80; - const int STAT_NADE_BONUS_SCORE = 81; - const int STAT_HEALING_ORB = 82; - const int STAT_HEALING_ORB_ALPHA = 83; - const int STAT_PLASMA = 84; - const int STAT_OK_AMMO_CHARGE = 85; - const int STAT_OK_AMMO_CHARGEPOOL = 86; - const int STAT_FROZEN = 87; - const int STAT_REVIVE_PROGRESS = 88; - const int STAT_WEAPON_NEXTTHINK = 89; - // 90 empty? - // 91 empty? - // 92 empty? - // 93 empty? - // 94 empty? - // 95 empty? - // 96 empty? - // 97 empty? - // 98 empty? - const int STAT_ROUNDLOST = 99; + const int MAX_CL_STATS = 256; + #ifndef CSQC + const int STAT_HEALTH = 0; // .health + const int STAT_ARMOR = 4; // .armorvalue + const int STAT_SHELLS = 6; // .ammo_shells + const int STAT_NAILS = 7; // .ammo_nails + const int STAT_ROCKETS = 8; // .ammo_rockets + const int STAT_CELLS = 9; // .ammo_cells + const int STAT_ACTIVEWEAPON = 10; // .weapon + const int STAT_ITEMS = 15; // .items | .items2 << 23 | serverflags << 28 + const int STAT_VIEWHEIGHT = 16; // .view_ofs_z + #endif + + REGISTER_STAT(WEAPONS, vectori) + REGISTER_STAT(WEAPONSINMAP, vectori) + + REGISTER_STAT(PL_VIEW_OFS, vector, autocvar_sv_player_viewoffset) + REGISTER_STAT(PL_CROUCH_VIEW_OFS, vector, autocvar_sv_player_crouch_viewoffset) + + REGISTER_STAT(PL_MIN, vector, autocvar_sv_player_mins) + REGISTER_STAT(PL_CROUCH_MIN, vector, autocvar_sv_player_crouch_mins) + + REGISTER_STAT(PL_MAX, vector, autocvar_sv_player_maxs) + REGISTER_STAT(PL_CROUCH_MAX, vector, autocvar_sv_player_crouch_maxs) + + REGISTER_STAT(KH_KEYS, int) ++ + /** weapon requested to switch to; next WANTED weapon (for HUD) */ + REGISTER_STAT(SWITCHWEAPON, int) ++/** weapon currently being switched to (is copied from switchweapon once switch is possible) */ ++REGISTER_STAT(SWITCHINGWEAPON, int) ++REGISTER_STAT(WEAPON_NEXTTHINK, float) ++ + REGISTER_STAT(GAMESTARTTIME, float) + REGISTER_STAT(STRENGTH_FINISHED, float) + REGISTER_STAT(INVINCIBLE_FINISHED, float) + /** arc heat in [0,1] */ + REGISTER_STAT(ARC_HEAT, float) + REGISTER_STAT(PRESSED_KEYS, int) + /** this stat could later contain some other bits of info, like, more server-side particle config */ + REGISTER_STAT(ALLOW_OLDVORTEXBEAM, bool) + REGISTER_STAT(FUEL, int) + REGISTER_STAT(NB_METERSTART, float) + /** compressShotOrigin */ + REGISTER_STAT(SHOTORG, int) + REGISTER_STAT(LEADLIMIT, float) + REGISTER_STAT(WEAPON_CLIPLOAD, int) + REGISTER_STAT(WEAPON_CLIPSIZE, int) + + REGISTER_STAT(VORTEX_CHARGE, float) + REGISTER_STAT(LAST_PICKUP, float) + REGISTER_STAT(HUD, int) + REGISTER_STAT(VORTEX_CHARGEPOOL, float) + REGISTER_STAT(HIT_TIME, float) + REGISTER_STAT(DAMAGE_DEALT_TOTAL, int) + REGISTER_STAT(TYPEHIT_TIME, float) + REGISTER_STAT(LAYED_MINES, int) + REGISTER_STAT(HAGAR_LOAD, int) -REGISTER_STAT(SWITCHINGWEAPON, int) + REGISTER_STAT(SUPERWEAPONS_FINISHED, float) + REGISTER_STAT(VEHICLESTAT_HEALTH, int) + REGISTER_STAT(VEHICLESTAT_SHIELD, int) + REGISTER_STAT(VEHICLESTAT_ENERGY, int) + REGISTER_STAT(VEHICLESTAT_AMMO1, int) + REGISTER_STAT(VEHICLESTAT_RELOAD1, int) + REGISTER_STAT(VEHICLESTAT_AMMO2, int) + REGISTER_STAT(VEHICLESTAT_RELOAD2, int) + REGISTER_STAT(VEHICLESTAT_W2MODE, int) + REGISTER_STAT(NADE_TIMER, float) + REGISTER_STAT(SECRETS_TOTAL, float) + REGISTER_STAT(SECRETS_FOUND, float) + REGISTER_STAT(RESPAWN_TIME, float) + REGISTER_STAT(ROUNDSTARTTIME, float) + REGISTER_STAT(MONSTERS_TOTAL, int) + REGISTER_STAT(MONSTERS_KILLED, int) + REGISTER_STAT(BUFFS, int) + REGISTER_STAT(NADE_BONUS, float) + REGISTER_STAT(NADE_BONUS_TYPE, int) + REGISTER_STAT(NADE_BONUS_SCORE, float) + REGISTER_STAT(HEALING_ORB, float) + REGISTER_STAT(HEALING_ORB_ALPHA, float) + REGISTER_STAT(PLASMA, int) + REGISTER_STAT(OK_AMMO_CHARGE, float) + REGISTER_STAT(OK_AMMO_CHARGEPOOL, float) + REGISTER_STAT(FROZEN, int) + REGISTER_STAT(REVIVE_PROGRESS, float) + REGISTER_STAT(ROUNDLOST, int) + REGISTER_STAT(BUFF_TIME, float) + REGISTER_STAT(CTF_FLAGSTATUS, int) + + #ifdef SVQC + int autocvar_g_multijump; + float autocvar_g_multijump_add; + float autocvar_g_multijump_speed; + float autocvar_g_multijump_maxspeed; + float autocvar_g_multijump_dodging = 1; + #endif + REGISTER_STAT(MULTIJUMP_DODGING, int, autocvar_g_multijump_dodging) + 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) + .int multijump_count; + REGISTER_STAT(MULTIJUMP_COUNT, int, this.multijump_count) + REGISTER_STAT(MULTIJUMP, int, autocvar_g_multijump) + REGISTER_STAT(DOUBLEJUMP, int, autocvar_sv_doublejump) + + #ifdef SVQC + 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; + float g_bugrigs_air_steering; + float g_bugrigs_angle_smoothing; + float g_bugrigs_friction_floor; + float g_bugrigs_friction_brake; + float g_bugrigs_friction_air; + float g_bugrigs_accel; + float g_bugrigs_speed_ref; + float g_bugrigs_speed_pow; + float g_bugrigs_steer; + #endif + REGISTER_STAT(BUGRIGS, int, g_bugrigs) + REGISTER_STAT(BUGRIGS_ACCEL, float, g_bugrigs_accel) + REGISTER_STAT(BUGRIGS_AIR_STEERING, int, g_bugrigs_air_steering) + REGISTER_STAT(BUGRIGS_ANGLE_SMOOTHING, int, g_bugrigs_angle_smoothing) + REGISTER_STAT(BUGRIGS_CAR_JUMPING, int, g_bugrigs_planar_movement_car_jumping) + REGISTER_STAT(BUGRIGS_FRICTION_AIR, float, g_bugrigs_friction_air) + REGISTER_STAT(BUGRIGS_FRICTION_BRAKE, float, g_bugrigs_friction_brake) + REGISTER_STAT(BUGRIGS_FRICTION_FLOOR, float, g_bugrigs_friction_floor) + REGISTER_STAT(BUGRIGS_PLANAR_MOVEMENT, int, g_bugrigs_planar_movement) + REGISTER_STAT(BUGRIGS_REVERSE_SPEEDING, int, g_bugrigs_reverse_speeding) + REGISTER_STAT(BUGRIGS_REVERSE_SPINNING, int, g_bugrigs_reverse_spinning) + REGISTER_STAT(BUGRIGS_REVERSE_STOPPING, int, g_bugrigs_reverse_stopping) + REGISTER_STAT(BUGRIGS_SPEED_POW, float, g_bugrigs_speed_pow) + REGISTER_STAT(BUGRIGS_SPEED_REF, float, g_bugrigs_speed_ref) + REGISTER_STAT(BUGRIGS_STEER, float, g_bugrigs_steer) + + REGISTER_STAT(GAMEPLAYFIX_DOWNTRACEONGROUND, int, cvar("sv_gameplayfix_downtracesupportsongroundflag")) + REGISTER_STAT(GAMEPLAYFIX_EASIERWATERJUMP, int, cvar("sv_gameplayfix_easierwaterjump")) + REGISTER_STAT(GAMEPLAYFIX_STEPDOWN, int, cvar("sv_gameplayfix_stepdown")) + REGISTER_STAT(GAMEPLAYFIX_STEPMULTIPLETIMES, int, cvar("sv_gameplayfix_stepmultipletimes")) + REGISTER_STAT(GAMEPLAYFIX_UNSTICKPLAYERS, int, cvar("sv_gameplayfix_unstickplayers")) + REGISTER_STAT(GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND, int, autocvar_sv_gameplayfix_upwardvelocityclearsongroundflag) + + REGISTER_STAT(MOVEVARS_JUMPSTEP, int, cvar("sv_jumpstep")) + REGISTER_STAT(NOSTEP, int, cvar("sv_nostep")) + + REGISTER_STAT(MOVEVARS_FRICTION, float) + REGISTER_STAT(MOVEVARS_FRICTION_SLICK, float, autocvar_sv_friction_slick) + REGISTER_STAT(MOVEVARS_FRICTION_ONLAND, float, autocvar_sv_friction_on_land) + + REGISTER_STAT(MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS, int, autocvar_sv_jumpspeedcap_max_disable_on_ramps) + REGISTER_STAT(MOVEVARS_TRACK_CANJUMP, int) + /** cvar loopback */ + REGISTER_STAT(MOVEVARS_CL_TRACK_CANJUMP, int) + + #ifdef SVQC + int g_dodging; + float autocvar_sv_dodging_delay; + float autocvar_sv_dodging_wall_distance_threshold; + bool autocvar_sv_dodging_frozen; + bool autocvar_sv_dodging_frozen_doubletap; + float autocvar_sv_dodging_height_threshold; + float autocvar_sv_dodging_horiz_speed; + float autocvar_sv_dodging_horiz_speed_frozen; + float autocvar_sv_dodging_ramp_time; + float autocvar_sv_dodging_up_speed; + bool autocvar_sv_dodging_wall_dodging; + #endif + + REGISTER_STAT(DODGING, int, g_dodging) + REGISTER_STAT(DODGING_DELAY, float, autocvar_sv_dodging_delay) + REGISTER_STAT(DODGING_DISTANCE_THRESHOLD, float, autocvar_sv_dodging_wall_distance_threshold) + REGISTER_STAT(DODGING_FROZEN, int, autocvar_sv_dodging_frozen) + REGISTER_STAT(DODGING_FROZEN_NO_DOUBLETAP, int, autocvar_sv_dodging_frozen_doubletap) + REGISTER_STAT(DODGING_HEIGHT_THRESHOLD, float, autocvar_sv_dodging_height_threshold) + REGISTER_STAT(DODGING_HORIZ_SPEED, float, autocvar_sv_dodging_horiz_speed) + REGISTER_STAT(DODGING_HORIZ_SPEED_FROZEN, float, autocvar_sv_dodging_horiz_speed_frozen) + REGISTER_STAT(DODGING_RAMP_TIME, float, autocvar_sv_dodging_ramp_time) + /** cvar loopback */ + REGISTER_STAT(DODGING_TIMEOUT, float) + REGISTER_STAT(DODGING_UP_SPEED, float, autocvar_sv_dodging_up_speed) + REGISTER_STAT(DODGING_WALL, int, autocvar_sv_dodging_wall_dodging) + + REGISTER_STAT(JETPACK_ACCEL_SIDE, float, autocvar_g_jetpack_acceleration_side) + REGISTER_STAT(JETPACK_ACCEL_UP, float, autocvar_g_jetpack_acceleration_up) + REGISTER_STAT(JETPACK_ANTIGRAVITY, float, autocvar_g_jetpack_antigravity) + REGISTER_STAT(JETPACK_FUEL, float, autocvar_g_jetpack_fuel) + REGISTER_STAT(JETPACK_MAXSPEED_SIDE, float, autocvar_g_jetpack_maxspeed_side) + REGISTER_STAT(JETPACK_MAXSPEED_UP, float, autocvar_g_jetpack_maxspeed_up) - /* The following stats change depending on the gamemode, so can share the same ID */ - // IDs 100 to 104 reserved for gamemodes + REGISTER_STAT(MOVEVARS_HIGHSPEED, float, autocvar_g_movement_highspeed) - // freeze tag, clan arena, jailbreak - const int STAT_REDALIVE = 100; - const int STAT_BLUEALIVE = 101; - const int STAT_YELLOWALIVE = 102; - const int STAT_PINKALIVE = 103; + // freeze tag, clan arena + REGISTER_STAT(REDALIVE, int) + REGISTER_STAT(BLUEALIVE, int) + REGISTER_STAT(YELLOWALIVE, int) + REGISTER_STAT(PINKALIVE, int) // domination - const int STAT_DOM_TOTAL_PPS = 100; - const int STAT_DOM_PPS_RED = 101; - const int STAT_DOM_PPS_BLUE = 102; - const int STAT_DOM_PPS_YELLOW = 103; - const int STAT_DOM_PPS_PINK = 104; + REGISTER_STAT(DOM_TOTAL_PPS, float) + REGISTER_STAT(DOM_PPS_RED, float) + REGISTER_STAT(DOM_PPS_BLUE, float) + REGISTER_STAT(DOM_PPS_YELLOW, float) + REGISTER_STAT(DOM_PPS_PINK, float) - // vip - const int STAT_VIP = 100; - const int STAT_VIP_RED = 101; - const int STAT_VIP_BLUE = 102; - const int STAT_VIP_YELLOW = 103; - const int STAT_VIP_PINK = 104; + REGISTER_STAT(TELEPORT_MAXSPEED, float, autocvar_g_teleport_maxspeed) + REGISTER_STAT(TELEPORT_TELEFRAG_AVOID, int, autocvar_g_telefrags_avoid) - // key hunt - const int STAT_KH_REDKEY_TEAM = 100; - const int STAT_KH_BLUEKEY_TEAM = 101; - const int STAT_KH_YELLOWKEY_TEAM = 102; - const int STAT_KH_PINKKEY_TEAM = 103; + #ifdef SVQC + #include "movetypes/movetypes.qh" + #endif + + REGISTER_STAT(MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, float) + REGISTER_STAT(MOVEVARS_AIRCONTROL_PENALTY, float) + REGISTER_STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, float) + REGISTER_STAT(MOVEVARS_AIRSTRAFEACCEL_QW, float) + REGISTER_STAT(MOVEVARS_AIRCONTROL_POWER, float) + noref bool autocvar_sv_gameplayfix_nogravityonground; + REGISTER_STAT(MOVEFLAGS, int, MOVEFLAG_VALID + | (autocvar_sv_gameplayfix_q2airaccelerate ? MOVEFLAG_Q2AIRACCELERATE : 0) + | (autocvar_sv_gameplayfix_nogravityonground ? MOVEFLAG_NOGRAVITYONGROUND : 0) + | (autocvar_sv_gameplayfix_gravityunaffectedbyticrate ? MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE : 0)) - /* Gamemode-specific stats end here */ + REGISTER_STAT(MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, float) + REGISTER_STAT(MOVEVARS_WARSOWBUNNY_ACCEL, float) + REGISTER_STAT(MOVEVARS_WARSOWBUNNY_TOPSPEED, float) + REGISTER_STAT(MOVEVARS_WARSOWBUNNY_TURNACCEL, float) + REGISTER_STAT(MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, float) - const int STAT_PL_VIEW_OFS1 = 105; - const int STAT_PL_VIEW_OFS2 = 106; - const int STAT_PL_VIEW_OFS3 = 107; - const int STAT_PL_MIN1 = 108; - const int STAT_PL_MIN2 = 109; - const int STAT_PL_MIN3 = 110; - const int STAT_PL_MAX1 = 111; - const int STAT_PL_MAX2 = 112; - const int STAT_PL_MAX3 = 113; - const int STAT_PL_CROUCH_MIN1 = 114; - const int STAT_PL_CROUCH_MIN2 = 115; - const int STAT_PL_CROUCH_MIN3 = 116; - const int STAT_PL_CROUCH_MAX1 = 117; - const int STAT_PL_CROUCH_MAX2 = 118; - const int STAT_PL_CROUCH_MAX3 = 119; - const int STAT_PL_CROUCH_VIEW_OFS1 = 117; - const int STAT_PL_CROUCH_VIEW_OFS2 = 118; - const int STAT_PL_CROUCH_VIEW_OFS3 = 119; - const int STAT_WEAPONSINMAP = 120; - const int STAT_WEAPONSINMAP2 = 121; - const int STAT_WEAPONSINMAP3 = 122; - const int STAT_BUFF_TIME = 123; - const int STAT_CTF_FLAGSTATUS = 124; - // 125 empty? - // 126 empty? - // 127 empty? - // 128 empty? - // 129 empty? - // 130 empty? - // 131 empty? - // 132 empty? - // 133 empty? - // 134 empty? - // 135 empty? - // 136 empty? - // 137 empty? - // 138 empty? - // 139 empty? - // 140 reserved - // 141 reserved - // 142 reserved - // 143 reserved - // 144 reserved - // 145 reserved - // 146 reserved - // 147 reserved - // 148 reserved - // 149 reserved - // 150 reserved - // 151 reserved - // 152 reserved - // 153 reserved - // 154 reserved - // 155 reserved - // 156 empty? - // 157 empty? - // 158 empty? - // 159 empty? - // 160 empty? - // 161 empty? - // 162 empty? - // 162 empty? - // 163 empty? - // 164 empty? - // 165 empty? - const int STAT_MULTIJUMP_DODGING = 166; - const int STAT_MULTIJUMP_MAXSPEED = 167; - const int STAT_GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND = 168; - const int STAT_BUGRIGS_REVERSE_STOPPING = 169; - const int STAT_BUGRIGS_REVERSE_SPINNING = 170; - const int STAT_BUGRIGS_CAR_JUMPING = 171; - const int STAT_BUGRIGS_FRICTION_AIR = 172; - const int STAT_BUGRIGS_STEER = 173; - const int STAT_BUGRIGS_SPEED_POW = 174; - const int STAT_BUGRIGS_SPEED_REF = 175; - const int STAT_BUGRIGS_ACCEL = 176; - const int STAT_BUGRIGS_FRICTION_BRAKE = 177; - const int STAT_BUGRIGS_AIR_STEERING = 178; - const int STAT_BUGRIGS_FRICTION_FLOOR = 179; - const int STAT_BUGRIGS_REVERSE_SPEEDING = 180; - const int STAT_BUGRIGS_PLANAR_MOVEMENT = 181; - const int STAT_BUGRIGS_ANGLE_SMOOTHING = 182; - const int STAT_BUGRIGS = 183; - const int STAT_GAMEPLAYFIX_STEPDOWN = 184; - const int STAT_MOVEVARS_JUMPSTEP = 185; - const int STAT_NOSTEP = 186; - const int STAT_GAMEPLAYFIX_UNSTICKPLAYERS = 187; - const int STAT_GAMEPLAYFIX_STEPMULTIPLETIMES = 188; - const int STAT_GAMEPLAYFIX_DOWNTRACEONGROUND = 189; - const int STAT_GAMEPLAYFIX_EASIERWATERJUMP = 190; - const int STAT_MOVEVARS_FRICTION_SLICK = 191; - const int STAT_MOVEVARS_FRICTION_ONLAND = 192; - const int STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS = 193; - const int STAT_MOVEVARS_TRACK_CANJUMP = 194; - // 195 empty? - const int STAT_DOUBLEJUMP = 196; - const int STAT_MOVEVARS_CL_TRACK_CANJUMP = 197; - const int STAT_MULTIJUMP_ADD = 198; - const int STAT_MULTIJUMP_SPEED = 199; - const int STAT_MULTIJUMP = 200; - const int STAT_DODGING_TIMEOUT = 201; - const int STAT_DODGING_WALL = 202; - const int STAT_DODGING_UP_SPEED = 203; - const int STAT_DODGING_RAMP_TIME = 204; - const int STAT_DODGING_HEIGHT_THRESHOLD = 205; - const int STAT_DODGING_DISTANCE_THRESHOLD = 206; - const int STAT_DODGING_HORIZ_SPEED = 207; - const int STAT_DODGING_DELAY = 208; - const int STAT_DODGING_FROZEN_NO_DOUBLETAP = 209; - const int STAT_DODGING_HORIZ_SPEED_FROZEN = 210; - const int STAT_DODGING = 211; - const int STAT_DODGING_FROZEN = 212; - const int STAT_JETPACK_MAXSPEED_UP = 213; - const int STAT_JETPACK_MAXSPEED_SIDE = 214; - const int STAT_JETPACK_FUEL = 215; - const int STAT_JETPACK_ANTIGRAVITY = 216; - const int STAT_JETPACK_ACCEL_SIDE = 217; - const int STAT_JETPACK_ACCEL_UP = 218; - const int STAT_MOVEVARS_HIGHSPEED = 219; - const int STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR = 220; - const int STAT_MOVEVARS_AIRCONTROL_PENALTY = 221; - const int STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW = 222; - const int STAT_MOVEVARS_AIRSTRAFEACCEL_QW = 223; - const int STAT_MOVEVARS_AIRCONTROL_POWER = 224; - const int STAT_MOVEFLAGS = 225; - const int STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL = 226; - const int STAT_MOVEVARS_WARSOWBUNNY_ACCEL = 227; - const int STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED = 228; - const int STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL = 229; - const int STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO = 230; - const int STAT_MOVEVARS_AIRSTOPACCELERATE = 231; - const int STAT_MOVEVARS_AIRSTRAFEACCELERATE = 232; - const int STAT_MOVEVARS_MAXAIRSTRAFESPEED = 233; - const int STAT_MOVEVARS_AIRCONTROL = 234; - // -Wdouble-declaration - // const int STAT_FRAGLIMIT = 235; - // -Wdouble-declaration - // const int STAT_TIMELIMIT = 236; - const int STAT_MOVEVARS_WALLFRICTION = 237; - const int STAT_MOVEVARS_FRICTION = 238; - const int STAT_MOVEVARS_WATERFRICTION = 239; - // -Wdouble-declaration - // const int STAT_MOVEVARS_TICRATE = 240; - // -Wdouble-declaration - // const int STAT_MOVEVARS_TIMESCALE = 241; - // -Wdouble-declaration - // const int STAT_MOVEVARS_GRAVITY = 242; - const int STAT_MOVEVARS_STOPSPEED = 243; - const int STAT_MOVEVARS_MAXSPEED = 244; - const int STAT_MOVEVARS_SPECTATORMAXSPEED = 245; - const int STAT_MOVEVARS_ACCELERATE = 246; - const int STAT_MOVEVARS_AIRACCELERATE = 247; - const int STAT_MOVEVARS_WATERACCELERATE = 248; - const int STAT_MOVEVARS_ENTGRAVITY = 249; - const int STAT_MOVEVARS_JUMPVELOCITY = 250; - const int STAT_MOVEVARS_EDGEFRICTION = 251; - const int STAT_MOVEVARS_MAXAIRSPEED = 252; - const int STAT_MOVEVARS_STEPHEIGHT = 253; - const int STAT_MOVEVARS_AIRACCEL_QW = 254; - const int STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION = 255; + REGISTER_STAT(MOVEVARS_AIRSTOPACCELERATE, float) + REGISTER_STAT(MOVEVARS_AIRSTRAFEACCELERATE, float) + REGISTER_STAT(MOVEVARS_MAXAIRSTRAFESPEED, float) + REGISTER_STAT(MOVEVARS_AIRCONTROL, float) + REGISTER_STAT(FRAGLIMIT, float, autocvar_fraglimit) + REGISTER_STAT(TIMELIMIT, float, autocvar_timelimit) + #ifdef SVQC + float autocvar_sv_wallfriction; + #endif + REGISTER_STAT(MOVEVARS_WALLFRICTION, int, autocvar_sv_wallfriction) + REGISTER_STAT(MOVEVARS_TICRATE, float, autocvar_sys_ticrate) + REGISTER_STAT(MOVEVARS_TIMESCALE, float, autocvar_slowmo) + REGISTER_STAT(MOVEVARS_GRAVITY, float, autocvar_sv_gravity) + REGISTER_STAT(MOVEVARS_STOPSPEED, float) + REGISTER_STAT(MOVEVARS_MAXSPEED, float) + REGISTER_STAT(MOVEVARS_ACCELERATE, float) + REGISTER_STAT(MOVEVARS_AIRACCELERATE, float) + .float gravity; + // FIXME: Was 0 on server, 1 on client. Still want that? + REGISTER_STAT(MOVEVARS_ENTGRAVITY, float, (this.gravity) ? this.gravity : 1) + REGISTER_STAT(MOVEVARS_JUMPVELOCITY, float) + REGISTER_STAT(MOVEVARS_MAXAIRSPEED, float) + REGISTER_STAT(MOVEVARS_STEPHEIGHT, float, autocvar_sv_stepheight) + REGISTER_STAT(MOVEVARS_AIRACCEL_QW, float) + REGISTER_STAT(MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, float) #endif diff --cc qcsrc/common/weapons/all.qc index fed883f06,f7ba35cc4..849403f87 --- a/qcsrc/common/weapons/all.qc +++ b/qcsrc/common/weapons/all.qc @@@ -20,34 -19,33 +19,33 @@@ #include "../../lib/csqcmodel/cl_model.qh" #elif defined(MENUQC) #elif defined(SVQC) - #include "../../lib/warpzone/anglestransform.qh" - #include "../../lib/warpzone/common.qh" - #include "../../lib/warpzone/util_server.qh" - #include "../../lib/warpzone/server.qh" - #include "../constants.qh" - #include "../stats.qh" - #include "../teams.qh" - #include "../util.qh" - #include "../buffs/all.qh" - #include "../monsters/all.qh" - #include "config.qh" - #include "../../server/weapons/csqcprojectile.qh" - #include "../../server/weapons/tracing.qh" - #include "../../server/t_items.qh" - #include "../../server/autocvars.qh" - #include "../../server/constants.qh" - #include "../../server/defs.qh" - #include "../notifications.qh" - #include "../deathtypes/all.qh" - #include "../../server/mutators/all.qh" - #include "../mapinfo.qh" - #include "../../server/command/common.qh" - #include "../../lib/csqcmodel/sv_model.qh" - #include "../../server/portals.qh" - #include "../../server/g_hook.qh" + #include "../../lib/warpzone/anglestransform.qh" + #include "../../lib/warpzone/common.qh" + #include "../../lib/warpzone/util_server.qh" + #include "../../lib/warpzone/server.qh" + #include "../constants.qh" + #include "../stats.qh" + #include "../teams.qh" + #include "../util.qh" + #include "../monsters/all.qh" + #include "config.qh" + #include "../../server/weapons/csqcprojectile.qh" + #include "../../server/weapons/tracing.qh" + #include "../../server/t_items.qh" + #include "../../server/autocvars.qh" + #include "../../server/constants.qh" + #include "../../server/defs.qh" + #include "../notifications.qh" + #include "../deathtypes/all.qh" + #include "../../server/mutators/all.qh" + #include "../mapinfo.qh" + #include "../../server/command/common.qh" + #include "../../lib/csqcmodel/sv_model.qh" + #include "../../server/portals.qh" + #include "../../server/g_hook.qh" #endif #ifndef MENUQC -#include "calculations.qc" + #include "calculations.qc" #endif #define IMPLEMENTATION #include "all.inc" @@@ -55,66 -53,48 +53,46 @@@ // WEAPON PLUGIN SYSTEM - WepSet WepSet_FromWeapon(int a) -WepSet _WepSet_FromWeapon(int a) { ++WepSet _WepSet_FromWeapon(int a) +{ a -= WEP_FIRST; if (Weapons_MAX > 24) - if (a >= 24) { - a -= 24; - if (Weapons_MAX > 48) - if (a >= 24) { + if (a >= 24) + { a -= 24; - return '0 0 1' * power2of(a); + if (Weapons_MAX > 48) + if (a >= 24) + { + a -= 24; + return '0 0 1' * power2of(a); + } + return '0 1 0' * power2of(a); } - return '0 1 0' * power2of(a); - } return '1 0 0' * power2of(a); } #ifdef SVQC - void WepSet_AddStat() - { - addstat(STAT_WEAPONS, AS_INT, weapons_x); - if (Weapons_MAX > 24) addstat(STAT_WEAPONS2, AS_INT, weapons_y); - if (Weapons_MAX > 48) addstat(STAT_WEAPONS3, AS_INT, weapons_z); - } - void WepSet_AddStat_InMap() - { - addstat(STAT_WEAPONSINMAP, AS_INT, weaponsinmap_x); - if (Weapons_MAX > 24) addstat(STAT_WEAPONSINMAP2, AS_INT, weaponsinmap_y); - if (Weapons_MAX > 48) addstat(STAT_WEAPONSINMAP3, AS_INT, weaponsinmap_z); - } -void WriteWepSet(float dst, WepSet w) -{ - if (Weapons_MAX > 48) - WriteInt72_t(dst, w); - else if (Weapons_MAX > 24) - WriteInt48_t(dst, w); - else - WriteInt24_t(dst, w.x); -} + void WriteWepSet(float dst, WepSet w) + { + if (Weapons_MAX > 48) WriteInt72_t(dst, w); + else if (Weapons_MAX > 24) WriteInt48_t(dst, w); + else WriteInt24_t(dst, w.x); + } #endif #ifdef CSQC -WepSet WepSet_GetFromStat() -{ - return STAT(WEAPONS); -} -WepSet WepSet_GetFromStat_InMap() -{ - return STAT(WEAPONSINMAP); -} -WepSet ReadWepSet() -{ - if (Weapons_MAX > 48) - return ReadInt72_t(); - if (Weapons_MAX > 24) - return ReadInt48_t(); - return ReadInt24_t() * '1 0 0'; -} + WepSet WepSet_GetFromStat() + { - WepSet w = '0 0 0'; - w.x = getstati(STAT_WEAPONS); - if (Weapons_MAX > 24) w.y = getstati(STAT_WEAPONS2); - if (Weapons_MAX > 48) w.z = getstati(STAT_WEAPONS3); - return w; ++ return STAT(WEAPONS); + } + WepSet WepSet_GetFromStat_InMap() + { - WepSet w = '0 0 0'; - w_x = getstati(STAT_WEAPONSINMAP); - if (Weapons_MAX > 24) w_y = getstati(STAT_WEAPONSINMAP2); - if (Weapons_MAX > 48) w_z = getstati(STAT_WEAPONSINMAP3); - return w; ++ return STAT(WEAPONSINMAP); + } + WepSet ReadWepSet() + { + if (Weapons_MAX > 48) return ReadInt72_t(); + if (Weapons_MAX > 24) return ReadInt48_t(); + return ReadInt24_t() * '1 0 0'; + } #endif string W_FixWeaponOrder(string order, float complete) @@@ -246,33 -230,33 +224,33 @@@ string GetAmmoPicture(.int ammotype } #ifdef CSQC -.int GetAmmoFieldFromNum(int i) -{ - switch(i) + .int GetAmmoFieldFromNum(int i) { - case 0: return ammo_shells; - case 1: return ammo_nails; - case 2: return ammo_rockets; - case 3: return ammo_cells; - case 4: return ammo_plasma; - case 5: return ammo_fuel; - default: return ammo_none; + switch (i) + { + case 0: return ammo_shells; + case 1: return ammo_nails; + case 2: return ammo_rockets; + case 3: return ammo_cells; + case 4: return ammo_plasma; + case 5: return ammo_fuel; + default: return ammo_none; + } } -} -int GetAmmoStat(.int ammotype) -{ - switch(ammotype) + int GetAmmoStat(.int ammotype) { - case ammo_shells: return STAT_SHELLS; - case ammo_nails: return STAT_NAILS; - case ammo_rockets: return STAT_ROCKETS; - case ammo_cells: return STAT_CELLS; - case ammo_plasma: return STAT_PLASMA.m_id; - case ammo_fuel: return STAT_FUEL.m_id; - default: return -1; + switch (ammotype) + { + case ammo_shells: return STAT_SHELLS; + case ammo_nails: return STAT_NAILS; + case ammo_rockets: return STAT_ROCKETS; + case ammo_cells: return STAT_CELLS; - case ammo_plasma: return STAT_PLASMA; - case ammo_fuel: return STAT_FUEL; ++ case ammo_plasma: return STAT_PLASMA.m_id; ++ case ammo_fuel: return STAT_FUEL.m_id; + default: return -1; + } } -} #endif string W_Sound(string w_snd) diff --cc qcsrc/common/weapons/all.qh index 76d536b4a,eb7a48f7f..47568b31a --- a/qcsrc/common/weapons/all.qh +++ b/qcsrc/common/weapons/all.qh @@@ -167,39 -172,4 +172,41 @@@ STATIC_INIT(register_weapons_done weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1)); } +#ifndef MENUQC + +.entity weaponchild; +.entity exteriorweaponentity; +.vector weaponentity_glowmod; + +//.int weapon; // current weapon - .int switchweapon; // weapon requested to switch to - .int switchingweapon; // weapon currently being switched to (is copied from switchweapon once switch is possible) ++#ifdef SVQC ++.int switchweapon = _STAT(SWITCHWEAPON); ++.int switchingweapon = _STAT(SWITCHINGWEAPON); ++#endif +.string weaponname; // name of .weapon + +.vector spawnorigin; // for casings + +// weapon animation vectors: +.vector anim_fire1; +.vector anim_fire2; +.vector anim_idle; +.vector anim_reload; + +// static frame globals + +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); +#endif + #endif diff --cc qcsrc/common/weapons/weapon.qh index 2a92f955b,3016b501f..71e121f81 --- a/qcsrc/common/weapons/weapon.qh +++ b/qcsrc/common/weapons/weapon.qh @@@ -17,18 -18,15 +18,27 @@@ int weaponslot(.entity weaponentity return 0; } +// weapon states (actor.(weaponentity).state) +/** no weapon selected */ +const int WS_CLEAR = 0; +/** raise frame */ +const int WS_RAISE = 1; +/** deselecting frame */ +const int WS_DROP = 2; +/** fire state */ +const int WS_INUSE = 3; +/** idle frame */ +const int WS_READY = 4; + + #ifdef SVQC + .int ammo_shells; + .int ammo_nails; + .int ammo_rockets; + .int ammo_cells; + .int ammo_plasma = _STAT(PLASMA); + .int ammo_fuel = _STAT(FUEL); + .int ammo_none; + #else .int ammo_shells; .int ammo_nails; .int ammo_rockets; diff --cc qcsrc/lib/vector.qh index 9813f2fa9,d6eee7ace..776bf6eed --- a/qcsrc/lib/vector.qh +++ b/qcsrc/lib/vector.qh @@@ -47,31 -67,12 +67,22 @@@ float boxesoverlap(vector m1, vector m2 /** requires the same as boxesoverlap, but is a stronger condition */ float boxinsidebox(vector smins, vector smaxs, vector bmins, vector bmaxs) { return smins.x >= bmins.x && smaxs.x <= bmaxs.x && smins.y >= bmins.y && smaxs.y <= bmaxs.y && smins.z >= bmins.z && smaxs.z <= bmaxs.z; } +#define PITCH(v) (v).x +#define YAW(v) (v).y +#define ROLL(v) (v).z + +#define MAKEVECTORS(f, angles, forward, right, up) do { \ + f(angles); \ + forward = v_forward; \ + right = v_right; \ + up = v_up; \ +} while (0) - vector vec2(vector v) - { - v.z = 0; - return v; - } + noref vector _vec2; + #define vec2(v) (_vec2 = (v), _vec2.z = 0, _vec2) - vector vec3(float x, float y, float z) - { - vector v; - v.x = x; - v.y = y; - v.z = z; - return v; - } + noref vector _vec3; + #define vec3(x, y, z) (_vec3_x = (x), _vec3_y = (y), _vec3_z = (z), _vec3) vector rotate(vector v, float a) { diff --cc qcsrc/server/defs.qh index 0fc8381ac,9c2dc4064..a18dd3c43 --- a/qcsrc/server/defs.qh +++ b/qcsrc/server/defs.qh @@@ -149,7 -165,7 +148,7 @@@ float client_hasweapon(entity cl, floa void w_clear(Weapon thiswep, entity actor, .entity weaponentity, int fire); void w_ready(Weapon thiswep, entity actor, .entity weaponentity, int fire); // VorteX: standalone think for weapons, so normal think on weaponentity can be reserved by weaponflashes (which needs update even player dies) --.float weapon_nextthink; ++.float weapon_nextthink = _STAT(WEAPON_NEXTTHINK); .void(Weapon thiswep, entity actor, .entity weaponentity, int fire) weapon_think; diff --cc qcsrc/server/g_subs.qh index 24cbe917e,cebf61b70..81516f935 --- a/qcsrc/server/g_subs.qh +++ b/qcsrc/server/g_subs.qh @@@ -9,16 -9,12 +9,6 @@@ void() SUB_CalcAngleMoveDone spawnfunc(info_null); - /* - ================== - SUB_Remove -void setanim(entity e, vector anim, float looping, float override, float restart); -- - Remove self - ================== - */ - void SUB_Remove (); -void updateanim(entity e); - - -- /* ================== SUB_Friction