]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/weapons/weapon/vortex.qc
tuba: fix #1621
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / weapons / weapon / vortex.qc
index bae7cca3de0ccb6fbd30086152c9c0f3cb31bedc..83ea7e597643820988d78ea5e040b7888d838d46 100644 (file)
@@ -14,53 +14,88 @@ CLASS(Vortex, Weapon)
 /* wepimg    */ ATTRIB(Vortex, model2, string, "weaponnex");
 /* refname   */ ATTRIB(Vortex, netname, string, "vortex");
 /* wepname   */ ATTRIB(Vortex, m_name, string, _("Vortex"));
+
+#define X(BEGIN, P, END, class, prefix) \
+       BEGIN(class) \
+               P(class, prefix, ammo, float, BOTH) \
+               P(class, prefix, animtime, float, BOTH) \
+               P(class, prefix, chargepool, float, SEC) \
+               P(class, prefix, chargepool_pause_regen, float, SEC) \
+               P(class, prefix, chargepool_regen, float, SEC) \
+               P(class, prefix, charge, float, NONE) \
+               P(class, prefix, charge_animlimit, float, NONE) \
+               P(class, prefix, charge_limit, float, NONE) \
+               P(class, prefix, charge_maxspeed, float, NONE) \
+               P(class, prefix, charge_mindmg, float, NONE) \
+               P(class, prefix, charge_minspeed, float, NONE) \
+               P(class, prefix, charge_rate, float, NONE) \
+               P(class, prefix, charge_rot_pause, float, NONE) \
+               P(class, prefix, charge_rot_rate, float, NONE) \
+               P(class, prefix, charge_shot_multiplier, float, NONE) \
+               P(class, prefix, charge_start, float, NONE) \
+               P(class, prefix, charge_velocity_rate, float, NONE) \
+               P(class, prefix, damagefalloff_forcehalflife, float, BOTH) \
+               P(class, prefix, damagefalloff_halflife, float, BOTH) \
+               P(class, prefix, damagefalloff_maxdist, float, BOTH) \
+               P(class, prefix, damagefalloff_mindist, float, BOTH) \
+               P(class, prefix, damage, float, BOTH) \
+               P(class, prefix, force, float, BOTH) \
+               P(class, prefix, refire, float, BOTH) \
+               P(class, prefix, secondary, float, NONE) \
+               P(class, prefix, reload_ammo, float, NONE) \
+        P(class, prefix, reload_time, float, NONE) \
+        P(class, prefix, switchdelay_raise, float, NONE) \
+        P(class, prefix, switchdelay_drop, float, NONE) \
+        P(class, prefix, weaponreplace, string, NONE) \
+        P(class, prefix, weaponstart, float, NONE) \
+        P(class, prefix, weaponstartoverride, float, NONE) \
+        P(class, prefix, weaponthrowable, float, NONE) \
+       END()
+    W_PROPS(X, Vortex, vortex)
+#undef X
+
 ENDCLASS(Vortex)
-REGISTER_WEAPON(VORTEX, NEW(Vortex));
-
-#define VORTEX_SETTINGS(w_cvar,w_prop) VORTEX_SETTINGS_LIST(w_cvar, w_prop, VORTEX, vortex)
-#define VORTEX_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-       w_cvar(id, sn, BOTH, ammo) \
-       w_cvar(id, sn, BOTH, animtime) \
-       w_cvar(id, sn, BOTH, damage) \
-       w_cvar(id, sn, BOTH, force) \
-       w_cvar(id, sn, BOTH, damagefalloff_mindist) \
-       w_cvar(id, sn, BOTH, damagefalloff_maxdist) \
-       w_cvar(id, sn, BOTH, damagefalloff_halflife) \
-       w_cvar(id, sn, BOTH, damagefalloff_forcehalflife) \
-       w_cvar(id, sn, BOTH, refire) \
-       w_cvar(id, sn, NONE, charge) \
-       w_cvar(id, sn, NONE, charge_mindmg) \
-       w_cvar(id, sn, NONE, charge_shot_multiplier) \
-       w_cvar(id, sn, NONE, charge_animlimit) \
-       w_cvar(id, sn, NONE, charge_limit) \
-       w_cvar(id, sn, NONE, charge_rate) \
-       w_cvar(id, sn, NONE, charge_rot_rate) \
-       w_cvar(id, sn, NONE, charge_rot_pause) \
-       w_cvar(id, sn, NONE, charge_start) \
-       w_cvar(id, sn, NONE, charge_minspeed) \
-       w_cvar(id, sn, NONE, charge_maxspeed) \
-       w_cvar(id, sn, NONE, charge_velocity_rate) \
-       w_cvar(id, sn, NONE, secondary) \
-       w_cvar(id, sn, SEC,  chargepool) \
-       w_cvar(id, sn, SEC,  chargepool_regen) \
-       w_cvar(id, sn, SEC,  chargepool_pause_regen) \
-       w_prop(id, sn, float,  reloading_ammo, reload_ammo) \
-       w_prop(id, sn, float,  reloading_time, reload_time) \
-       w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-       w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-       w_prop(id, sn, string, weaponreplace, weaponreplace) \
-       w_prop(id, sn, float,  weaponstart, weaponstart) \
-       w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-       w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
+REGISTER_WEAPON(VORTEX, vortex, NEW(Vortex));
+
 
 #ifdef SVQC
-VORTEX_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 
 .float vortex_lasthit;
 #endif
 #endif
 #ifdef IMPLEMENTATION
 
+REGISTER_STAT(WEP_CVAR_vortex_charge, bool, WEP_CVAR(vortex, charge))
+REGISTER_STAT(WEP_CVAR_vortex_charge_animlimit, float, WEP_CVAR(vortex, charge_animlimit))
+
+#if defined(CSQC)
+float autocvar_g_weapon_charge_colormod_red_full;
+float autocvar_g_weapon_charge_colormod_red_half;
+float autocvar_g_weapon_charge_colormod_green_full;
+float autocvar_g_weapon_charge_colormod_blue_full;
+float autocvar_g_weapon_charge_colormod_blue_half;
+float autocvar_g_weapon_charge_colormod_green_half;
+float autocvar_g_weapon_charge_colormod_hdrmultiplier;
+
+METHOD(Vortex, wr_glow, vector(Vortex this))
+{
+       if (!STAT(WEP_CVAR_vortex_charge)) return '0 0 0';
+       float charge = STAT(VORTEX_CHARGE);
+       float animlimit = STAT(WEP_CVAR_vortex_charge_animlimit);
+       vector g;
+       g.x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, charge / animlimit);
+       g.y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, charge / animlimit);
+       g.z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, charge / animlimit);
+       if (charge > animlimit)
+       {
+               g.x += autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (charge - animlimit) / (1 - animlimit);
+               g.y += autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (charge - animlimit) / (1 - animlimit);
+               g.z += autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (charge - animlimit) / (1 - animlimit);
+       }
+       return g;
+}
+#endif
+
 REGISTER_NET_TEMP(TE_CSQC_VORTEXBEAMPARTICLE)
 
 #if defined(SVQC)
@@ -91,7 +126,8 @@ NET_HANDLE(TE_CSQC_VORTEXBEAMPARTICLE, bool isNew)
        charge = sqrt(charge); // divide evenly among trail spacing and alpha
        particles_alphamin = particles_alphamax = particles_fade = charge;
 
-       if (autocvar_cl_particles_oldvortexbeam && (getstati(STAT_ALLOW_OLDVORTEXBEAM) || isdemo()))
+       if(!MUTATOR_CALLHOOK(Particles_VortexBeam, shotorg, endpos))
+       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);
@@ -103,6 +139,22 @@ NET_HANDLE(TE_CSQC_VORTEXBEAMPARTICLE, bool isNew)
 spawnfunc(weapon_vortex) { weapon_defaultspawnfunc(this, WEP_VORTEX); }
 spawnfunc(weapon_nex) { spawnfunc_weapon_vortex(this); }
 
+REGISTER_MUTATOR(vortex_charge, true);
+
+MUTATOR_HOOKFUNCTION(vortex_charge, GetPressedKeys)
+{SELFPARAM();
+       // WEAPONTODO
+       float xyspeed = vlen(vec2(self.velocity));
+       if (PS(self).m_weapon == WEP_VORTEX && WEP_CVAR(vortex, charge) && WEP_CVAR(vortex, charge_velocity_rate) && xyspeed > WEP_CVAR(vortex, charge_minspeed))
+       {
+               // add a maximum of charge_velocity_rate when going fast (f = 1), gradually increasing from minspeed (f = 0) to maxspeed
+               xyspeed = min(xyspeed, WEP_CVAR(vortex, charge_maxspeed));
+               float f = (xyspeed - WEP_CVAR(vortex, charge_minspeed)) / (WEP_CVAR(vortex, charge_maxspeed) - WEP_CVAR(vortex, charge_minspeed));
+               // add the extra charge
+               self.vortex_charge = min(1, self.vortex_charge + WEP_CVAR(vortex, charge_velocity_rate) * f * PHYS_INPUT_TIMELENGTH);
+       }
+}
+
 void W_Vortex_Attack(Weapon thiswep, float issecondary)
 {SELFPARAM();
        float mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, myammo, charge;
@@ -182,8 +234,7 @@ void W_Vortex_Attack(Weapon thiswep, float issecondary)
                                }
 
                        if(autocvar_g_balance_vortex_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo))) { // forced reload
-                               Weapon w = get_weaponinfo(actor.weapon);
-                               w.wr_reload(w);
+                               thiswep.wr_reload(thiswep, actor, weaponentity);
                        } else
                        {
                                if(fire & 1)
@@ -239,11 +290,11 @@ void W_Vortex_Attack(Weapon thiswep, float issecondary)
                                                                                }
                                                                                else
                                                                                {
-                                                                                       dt = min(dt, (actor.WEP_AMMO(VORTEX) - WEP_CVAR_PRI(vortex, ammo)) / WEP_CVAR_SEC(vortex, ammo));
+                                                                                       dt = min(dt, (actor.(thiswep.ammo_field) - WEP_CVAR_PRI(vortex, ammo)) / WEP_CVAR_SEC(vortex, ammo));
                                                                                        dt = max(0, dt);
                                                                                        if(dt > 0)
                                                                                        {
-                                                                                               actor.WEP_AMMO(VORTEX) = max(WEP_CVAR_SEC(vortex, ammo), actor.WEP_AMMO(VORTEX) - WEP_CVAR_SEC(vortex, ammo) * dt);
+                                                                                               actor.(thiswep.ammo_field) = max(WEP_CVAR_SEC(vortex, ammo), actor.(thiswep.ammo_field) - WEP_CVAR_SEC(vortex, ammo) * dt);
                                                                                        }
                                                                                }
                                                                        }
@@ -269,17 +320,13 @@ void W_Vortex_Attack(Weapon thiswep, float issecondary)
                                }
                        }
                }
-               METHOD(Vortex, wr_init, void(entity thiswep))
-               {
-                       VORTEX_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-               }
                METHOD(Vortex, wr_setup, void(entity thiswep))
                {
                        self.vortex_lasthit = 0;
                }
                METHOD(Vortex, wr_checkammo1, bool(entity thiswep))
                {
-                       float ammo_amount = self.WEP_AMMO(VORTEX) >= WEP_CVAR_PRI(vortex, ammo);
+                       float ammo_amount = self.(thiswep.ammo_field) >= WEP_CVAR_PRI(vortex, ammo);
                        ammo_amount += (autocvar_g_balance_vortex_reload_ammo && self.(weapon_load[WEP_VORTEX.m_id]) >= WEP_CVAR_PRI(vortex, ammo));
                        return ammo_amount;
                }
@@ -288,7 +335,7 @@ void W_Vortex_Attack(Weapon thiswep, float issecondary)
                        if(WEP_CVAR(vortex, secondary))
                        {
                                // don't allow charging if we don't have enough ammo
-                               float ammo_amount = self.WEP_AMMO(VORTEX) >= WEP_CVAR_SEC(vortex, ammo);
+                               float ammo_amount = self.(thiswep.ammo_field) >= WEP_CVAR_SEC(vortex, ammo);
                                ammo_amount += self.(weapon_load[WEP_VORTEX.m_id]) >= WEP_CVAR_SEC(vortex, ammo);
                                return ammo_amount;
                        }
@@ -297,10 +344,6 @@ void W_Vortex_Attack(Weapon thiswep, float issecondary)
                                return false; // zoom is not a fire mode
                        }
                }
-               METHOD(Vortex, wr_config, void(entity thiswep))
-               {
-                       VORTEX_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-               }
                METHOD(Vortex, wr_resetplayer, void(entity thiswep))
                {
                        if (WEP_CVAR(vortex, charge)) {
@@ -311,7 +354,7 @@ void W_Vortex_Attack(Weapon thiswep, float issecondary)
                        }
                        self.vortex_lasthit = 0;
                }
-               METHOD(Vortex, wr_reload, void(entity thiswep))
+               METHOD(Vortex, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
                {
                        W_Reload(self, min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo)), SND(RELOAD));
                }
@@ -326,7 +369,6 @@ void W_Vortex_Attack(Weapon thiswep, float issecondary)
 
 #endif
 #ifdef CSQC
-float autocvar_g_balance_vortex_secondary = 0; // WEAPONTODO
 
                METHOD(Vortex, wr_impacteffect, void(entity thiswep))
                {