]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/mutators/mutator_nades.qc
Nades: rename registry globals
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / mutator_nades.qc
index 8e49e2aa63404fe6c9505f84026935dd38e830af..d4cebf9d7a172597fd8be264d1834effa6316ae9 100644 (file)
@@ -5,11 +5,11 @@
 
 #include "gamemode_keyhunt.qh"
 #include "gamemode_freezetag.qh"
-#include "../../common/nades.qh"
+#include "../../common/nades/all.qh"
 #include "../../common/monsters/spawn.qh"
 #include "../../common/monsters/sv_monsters.qh"
 
-.float lifetime;
+.float nade_time_primed;
 
 .entity nade_spawnloc;
 
@@ -23,13 +23,13 @@ void nade_timer_think()
 
 void nade_burn_spawn(entity _nade)
 {
-       CSQCProjectile(_nade, true, NADES[_nade.nade_type].m_projectile[true], true);
+       CSQCProjectile(_nade, true, Nades[_nade.nade_type].m_projectile[true], true);
 }
 
 void nade_spawn(entity _nade)
 {
        entity timer = spawn();
-       setmodel(timer, "models/ok_nade_counter/ok_nade_counter.md3");
+       setmodel(timer, MDL_NADE_TIMER);
        setattachment(timer, _nade, "");
        timer.classname = "nade_timer";
        timer.colormap = _nade.colormap;
@@ -42,7 +42,7 @@ void nade_spawn(entity _nade)
 
        _nade.effects |= EF_LOWPRECISION;
 
-       CSQCProjectile(_nade, true, NADES[_nade.nade_type].m_projectile[false], true);
+       CSQCProjectile(_nade, true, Nades[_nade.nade_type].m_projectile[false], true);
 }
 
 void napalm_damage(float dist, float damage, float edgedamage, float burntime)
@@ -121,7 +121,7 @@ void nade_napalm_ball()
        entity proj;
        vector kick;
 
-       spamsound(self, CH_SHOTS, W_Sound("fireball_fire"), VOL_BASE, ATTEN_NORM);
+       spamsound(self, CH_SHOTS, SND(FIREBALL_FIRE), VOL_BASE, ATTEN_NORM);
 
        proj = spawn ();
        proj.owner = self.owner;
@@ -133,7 +133,7 @@ void nade_napalm_ball()
        proj.movetype = MOVETYPE_BOUNCE;
        proj.projectiledeathtype = DEATH_NADE_NAPALM;
        PROJECTILE_MAKETRIGGER(proj);
-       setmodel(proj, "null");
+       setmodel(proj, MDL_Null);
        proj.scale = 1;//0.5;
        setsize(proj, '-4 -4 -4', '4 4 4');
        setorigin(proj, self.origin);
@@ -250,17 +250,9 @@ void nade_ice_think()
        {
                if ( autocvar_g_nades_ice_explode )
                {
-                       entity expef = NULL;
-                       switch(self.realowner.team)
-                       {
-                               case NUM_TEAM_1: expef = EFFECT_NADE_RED_EXPLODE; break;
-                               case NUM_TEAM_2: expef = EFFECT_NADE_BLUE_EXPLODE; break;
-                               case NUM_TEAM_3: expef = EFFECT_NADE_YELLOW_EXPLODE; break;
-                               case NUM_TEAM_4: expef = EFFECT_NADE_PINK_EXPLODE; break;
-                               default:                 expef = EFFECT_NADE_NEUTRAL_EXPLODE; break;
-                       }
+                       entity expef = EFFECT_NADE_EXPLODE(self.realowner.team);
                        Send_Effect(expef, self.origin + '0 0 1', '0 0 0', 1);
-                       sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+                       sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
 
                        RadiusDamage(self, self.realowner, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
                                autocvar_g_nades_nade_radius, self, world, autocvar_g_nades_nade_force, self.projectiledeathtype, self.enemy);
@@ -331,9 +323,9 @@ void nade_ice_boom()
 
        if ( autocvar_g_nades_ice_explode )
        {
-               setmodel(fountain, "models/grenademodel.md3");
+               setmodel(fountain, MDL_PROJECTILE_GRENADE);
                entity timer = spawn();
-               setmodel(timer, "models/ok_nade_counter/ok_nade_counter.md3");
+               setmodel(timer, MDL_NADE_TIMER);
                setattachment(timer, fountain, "");
                timer.classname = "nade_timer";
                timer.colormap = self.colormap;
@@ -345,7 +337,7 @@ void nade_ice_boom()
                timer.skin = 10;
        }
        else
-               setmodel(fountain, "null");
+               setmodel(fountain, MDL_Null);
 }
 
 void nade_translocate_boom()
@@ -459,7 +451,7 @@ void nade_heal_boom()
        healer.solid = SOLID_TRIGGER;
        healer.touch = nade_heal_touch;
 
-       setmodel(healer, "models/ctf/shield.md3");
+       setmodel(healer, MDL_NADE_HEAL);
        healer.healer_radius = autocvar_g_nades_nade_radius;
        vector size = '1 1 1' * healer.healer_radius / 2;
        setsize(healer,-size,size);
@@ -485,7 +477,7 @@ void nade_boom()
        entity expef = NULL;
        bool nade_blast = true;
 
-       switch ( NADES[self.nade_type] )
+       switch ( Nades[self.nade_type] )
        {
                case NADE_TYPE_NAPALM:
                        nade_blast = autocvar_g_nades_napalm_blast;
@@ -517,21 +509,15 @@ void nade_boom()
 
                default:
                case NADE_TYPE_NORMAL:
-                       switch(self.realowner.team)
-                       {
-                               case NUM_TEAM_1: expef = EFFECT_NADE_RED_EXPLODE; break;
-                               case NUM_TEAM_2: expef = EFFECT_NADE_BLUE_EXPLODE; break;
-                               case NUM_TEAM_3: expef = EFFECT_NADE_YELLOW_EXPLODE; break;
-                               case NUM_TEAM_4: expef = EFFECT_NADE_PINK_EXPLODE; break;
-                               default:                 expef = EFFECT_NADE_NEUTRAL_EXPLODE; break;
-                       }
+                       expef = EFFECT_NADE_EXPLODE(self.realowner.team);
+                       break;
        }
 
        if(expef)
                Send_Effect(expef, findbetterlocation(self.origin, 8), '0 0 0', 1);
 
-       sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM);
-       sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+       sound(self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
+       sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
 
        self.event_damage = func_null; // prevent somehow calling damage in the next call
 
@@ -543,7 +529,7 @@ void nade_boom()
        }
 
        if(self.takedamage)
-       switch ( NADES[self.nade_type] )
+       switch ( Nades[self.nade_type] )
        {
                case NADE_TYPE_NAPALM: nade_napalm_boom(); break;
                case NADE_TYPE_ICE: nade_ice_boom(); break;
@@ -584,7 +570,7 @@ void nade_touch()
        //UpdateCSQCProjectile(self);
        if(self.health == self.max_health)
        {
-               spamsound(self, CH_SHOTS, W_Sound(strcat("grenade_bounce", ftos(1 + rint(random() * 5)))), VOL_BASE, ATTEN_NORM);
+               spamsound(self, CH_SHOTS, SND(GRENADE_BOUNCE_RANDOM()), VOL_BASE, ATTEN_NORM);
                return;
        }
 
@@ -594,7 +580,7 @@ void nade_touch()
 
 void nade_beep()
 {SELFPARAM();
-       sound(self, CH_SHOTS_SINGLE, "overkill/grenadebip.ogg", VOL_BASE, 0.5 *(ATTEN_LARGE + ATTEN_MAX));
+       sound(self, CH_SHOTS_SINGLE, SND_NADE_BEEP, VOL_BASE, 0.5 *(ATTEN_LARGE + ATTEN_MAX));
        self.think = nade_boom;
        self.nextthink = max(self.wait, time);
 }
@@ -649,7 +635,7 @@ void nade_damage(entity inflictor, entity attacker, float damage, int deathtype,
 
        if(self.health == self.max_health)
        {
-               sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, 0.5 *(ATTEN_LARGE + ATTEN_MAX));
+               sound(self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, 0.5 *(ATTEN_LARGE + ATTEN_MAX));
                self.nextthink = max(time + autocvar_g_nades_nade_lifetime, time);
                self.think = nade_beep;
        }
@@ -689,7 +675,7 @@ void toss_nade(entity e, vector _velocity, float _time)
                offset = '0 0 0';
 
        setorigin(_nade, w_shotorg + offset + (v_right * 25) * -1);
-       //setmodel(_nade, W_Model("v_ok_grenade.md3"));
+       //setmodel(_nade, MDL_PROJECTILE_NADE);
        //setattachment(_nade, world, "");
        PROJECTILE_MAKETRIGGER(_nade);
        setsize(_nade, '-16 -16 -16', '16 16 16');
@@ -759,7 +745,7 @@ void nades_GiveBonus(entity player, float score)
                if ( player.bonus_nade_score >= 1 )
                {
                        Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_NADE_BONUS);
-                       play2(player,"kh/alarm.wav");
+                       play2(player, SND(KH_ALARM));
                        player.bonus_nades++;
                        player.bonus_nade_score -= 1;
                }
@@ -786,7 +772,7 @@ float nade_customize()
        {
                //self.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
                if(!self.traileffectnum)
-                       self.traileffectnum = _particleeffectnum(Nade_TrailEffect(NADES[self.nade_type].m_projectile[false], self.team));
+                       self.traileffectnum = _particleeffectnum(Nade_TrailEffect(Nades[self.nade_type].m_projectile[false], self.team).eent_eff_name);
                self.alpha = 1;
        }
 
@@ -824,27 +810,27 @@ void nade_prime()
                n.pokenade_type = ((autocvar_g_nades_client_select) ? self.cvar_cl_pokenade_type : autocvar_g_nades_pokenade_monster_type);
        }
 
-       n.nade_type = bound(1, n.nade_type, NADES_COUNT);
+       n.nade_type = bound(1, n.nade_type, Nades_COUNT);
 
-       setmodel(n, W_Model("v_ok_grenade.md3"));
+       setmodel(n, MDL_PROJECTILE_NADE);
        //setattachment(n, self, "bip01 l hand");
        n.exteriormodeltoclient = self;
        n.customizeentityforclient = nade_customize;
-       n.traileffectnum = _particleeffectnum(Nade_TrailEffect(NADES[n.nade_type].m_projectile[false], self.team));
-       n.colormod = NADES[n.nade_type].m_color;
+       n.traileffectnum = _particleeffectnum(Nade_TrailEffect(Nades[n.nade_type].m_projectile[false], self.team).eent_eff_name);
+       n.colormod = Nades[n.nade_type].m_color;
        n.realowner = self;
        n.colormap = self.colormap;
        n.glowmod = self.glowmod;
        n.wait = time + autocvar_g_nades_nade_lifetime;
-       n.lifetime = time;
+       n.nade_time_primed = time;
        n.think = nade_beep;
        n.nextthink = max(n.wait - 3, time);
        n.projectiledeathtype = DEATH_NADE;
 
-       setmodel(fn, W_Model("h_ok_grenade.iqm"));
+       setmodel(fn, MDL_NADE_VIEW);
        setattachment(fn, self.weaponentity, "");
        fn.realowner = fn.owner = self;
-       fn.colormod = NADES[n.nade_type].m_color;
+       fn.colormod = Nades[n.nade_type].m_color;
        fn.colormap = self.colormap;
        fn.glowmod = self.glowmod;
        fn.think = SUB_Remove;
@@ -877,14 +863,18 @@ float CanThrowNade()
        return true;
 }
 
+.bool nade_altbutton;
+
 void nades_CheckThrow()
 {SELFPARAM();
        if(!CanThrowNade())
                return;
 
-       if(!self.nade)
+       entity held_nade = self.nade;
+       if (!held_nade)
        {
-               if(self.nade_refire < time)
+               self.nade_altbutton = true;
+               if(time > self.nade_refire)
                {
                        Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_NADE_THROW);
                        nade_prime();
@@ -893,10 +883,10 @@ void nades_CheckThrow()
        }
        else
        {
-               if(time - self.nade.lifetime >= 1)
-               {
+               self.nade_altbutton = false;
+               if (time >= held_nade.nade_time_primed + 1) {
                        makevectors(self.v_angle);
-                       float _force = time - self.nade.lifetime;
+                       float _force = time - held_nade.nade_time_primed;
                        _force /= autocvar_g_nades_nade_lifetime;
                        _force = autocvar_g_nades_nade_minforce + (_force * (autocvar_g_nades_nade_maxforce - autocvar_g_nades_nade_minforce));
                        toss_nade(self, (v_forward * 0.75 + v_up * 0.2 + v_right * 0.05) * _force, 0);
@@ -915,12 +905,6 @@ void nades_Clear(entity player)
        player.nade_timer = 0;
 }
 
-MUTATOR_HOOKFUNCTION(nades_CheckThrow)
-{
-       if(MUTATOR_RETURNVALUE) { nades_CheckThrow(); }
-       return false;
-}
-
 MUTATOR_HOOKFUNCTION(nades_VehicleEnter)
 {
        if(vh_player.nade)
@@ -929,51 +913,57 @@ MUTATOR_HOOKFUNCTION(nades_VehicleEnter)
        return false;
 }
 
-MUTATOR_HOOKFUNCTION(nades_PlayerPreThink)
-{SELFPARAM();
-       if(!IS_PLAYER(self)) { return false; }
-
-       float key_pressed = self.BUTTON_HOOK;
-       float time_score;
-
-       if(g_grappling_hook || client_hasweapon(self, WEP_HOOK.m_id, false, false) || (weaponsInMap & WEPSET_HOOK))
-               key_pressed = self.button16; // if hook is enabled, use an alternate key
-
-       if(self.nade)
-       {
-               self.nade_timer = bound(0, (time - self.nade.lifetime) / autocvar_g_nades_nade_lifetime, 1);
-               //print(sprintf("%d %d\n", self.nade_timer, time - self.nade.lifetime));
-               makevectors(self.angles);
-               self.nade.velocity = self.velocity;
-
-               setorigin(self.nade, self.origin + self.view_ofs + v_forward * 8 + v_right * -8 + v_up * 0);
-               self.nade.angles_y = self.angles.y;
-       }
-
-       if(self.nade)
-       if(self.nade.wait - 0.1 <= time)
-               toss_nade(self, '0 0 0', time + 0.05);
-
-       if(CanThrowNade())
-       if(self.nade_refire < time)
-       {
-               if(key_pressed)
+CLASS(NadeOffhand, OffhandWeapon)
+    METHOD(NadeOffhand, offhand_think, void(NadeOffhand this, entity player, bool key_pressed))
+    {
+       entity held_nade = player.nade;
+               if (held_nade)
                {
-                       if(!self.nade)
-                               nade_prime();
+                       player.nade_timer = bound(0, (time - held_nade.nade_time_primed) / autocvar_g_nades_nade_lifetime, 1);
+                       // LOG_TRACEF("%d %d\n", player.nade_timer, time - held_nade.nade_time_primed);
+                       makevectors(player.angles);
+                       held_nade.velocity = player.velocity;
+                       setorigin(held_nade, player.origin + player.view_ofs + v_forward * 8 + v_right * -8 + v_up * 0);
+                       held_nade.angles_y = player.angles.y;
+
+                       if (time + 0.1 >= held_nade.wait)
+                               toss_nade(player, '0 0 0', time + 0.05);
                }
-               else if(time - self.nade.lifetime >= 1)
-               {
-                       if(self.nade)
-                       {
-                               makevectors(self.v_angle);
-                               float _force = time - self.nade.lifetime;
+
+        if (!CanThrowNade()) return;
+        if (!(time > player.nade_refire)) return;
+               if (key_pressed) {
+                       if (!held_nade) {
+                               nade_prime();
+                               held_nade = player.nade;
+                       }
+               } else if (time >= held_nade.nade_time_primed + 1) {
+                       if (held_nade) {
+                               makevectors(player.v_angle);
+                               float _force = time - held_nade.nade_time_primed;
                                _force /= autocvar_g_nades_nade_lifetime;
                                _force = autocvar_g_nades_nade_minforce + (_force * (autocvar_g_nades_nade_maxforce - autocvar_g_nades_nade_minforce));
-                               toss_nade(self, (v_forward * 0.7 + v_up * 0.2 + v_right * 0.1) * _force, 0);
+                               toss_nade(player, (v_forward * 0.7 + v_up * 0.2 + v_right * 0.1) * _force, 0);
                        }
                }
+    }
+ENDCLASS(NadeOffhand)
+NadeOffhand OFFHAND_NADE; STATIC_INIT(OFFHAND_NADE) { OFFHAND_NADE = NEW(NadeOffhand); }
+
+MUTATOR_HOOKFUNCTION(nades_CheckThrow)
+{
+       if (self.offhand != OFFHAND_NADE || (self.weapons & WEPSET(HOOK))) {
+               nades_CheckThrow();
+               return true;
        }
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(nades_PlayerPreThink)
+{SELFPARAM();
+       if (!IS_PLAYER(self)) { return false; }
+
+       if (self.nade && self.offhand != OFFHAND_NADE) OFFHAND_NADE.offhand_think(OFFHAND_NADE, self, self.nade_altbutton);
 
        if(IS_PLAYER(self))
        {
@@ -983,6 +973,7 @@ MUTATOR_HOOKFUNCTION(nades_PlayerPreThink)
                        float key_count = 0;
                        FOR_EACH_KH_KEY(key) if(key.owner == self) { ++key_count; }
 
+                       float time_score;
                        if(self.flagcarried || self.ballcarried) // this player is important
                                time_score = autocvar_g_nades_bonus_score_time_flagcarrier;
                        else
@@ -1002,7 +993,7 @@ MUTATOR_HOOKFUNCTION(nades_PlayerPreThink)
                                self.pokenade_type = autocvar_g_nades_pokenade_monster_type;
                        }
 
-                       self.nade_type = bound(1, self.nade_type, NADES_COUNT);
+                       self.nade_type = bound(1, self.nade_type, Nades_COUNT);
 
                        if(self.bonus_nade_score >= 0 && autocvar_g_nades_bonus_score_max)
                                nades_GiveBonus(self, time_score / autocvar_g_nades_bonus_score_max);
@@ -1072,6 +1063,8 @@ MUTATOR_HOOKFUNCTION(nades_PlayerSpawn)
 
        self.nade_timer = 0;
 
+       if (!self.offhand) self.offhand = OFFHAND_NADE;
+
        if(self.nade_spawnloc)
        {
                setorigin(self, self.nade_spawnloc.origin);
@@ -1198,20 +1191,6 @@ void nades_Initialize()
        addstat(STAT_NADE_BONUS_SCORE, AS_FLOAT, bonus_nade_score);
        addstat(STAT_HEALING_ORB, AS_FLOAT, stat_healing_orb);
        addstat(STAT_HEALING_ORB_ALPHA, AS_FLOAT, stat_healing_orb_alpha);
-
-       precache_model("models/ok_nade_counter/ok_nade_counter.md3");
-       precache_model(W_Model("h_ok_grenade.iqm"));
-       precache_model(W_Model("v_ok_grenade.md3"));
-       precache_model("models/ctf/shield.md3");
-
-       precache_sound(W_Sound("rocket_impact"));
-       precache_sound(W_Sound("grenade_bounce1"));
-       precache_sound(W_Sound("grenade_bounce2"));
-       precache_sound(W_Sound("grenade_bounce3"));
-       precache_sound(W_Sound("grenade_bounce4"));
-       precache_sound(W_Sound("grenade_bounce5"));
-       precache_sound(W_Sound("grenade_bounce6"));
-       precache_sound("overkill/grenadebip.ogg");
 }
 
 MUTATOR_DEFINITION(mutator_nades)