]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/mutators/mutator_nades.qc
Merge branch 'Mario/nades_mutator' into Mario/mutators
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / mutator_nades.qc
index 591fcc9dca998c6731f10dc3cbd09c2b48fa5873..4466ccf53540ff3fd760959a28982b861ddb2850 100644 (file)
@@ -1,4 +1,5 @@
 .entity nade;
+.entity fake_nade;
 .float nade_refire;
 
 void nade_timer_think()
@@ -81,8 +82,8 @@ void nade_boom() // TODO: DamageInfo
 void nade_touch()
 {
        PROJECTILE_TOUCH;
-       setsize(self, '-2 -2 -2', '2 2 2');
-       UpdateCSQCProjectile(self);
+       //setsize(self, '-2 -2 -2', '2 2 2');
+       //UpdateCSQCProjectile(self);
        if(self.health == autocvar_g_nades_nade_health)
        {
                spamsound(self, CH_SHOTS, strcat("weapons/grenade_bounce", ftos(1 + rint(random() * 5)), ".wav"), VOL_BASE, ATTN_NORM);
@@ -114,8 +115,14 @@ void nade_damage(entity inflictor, entity attacker, float damage, float deathtyp
        if(DEATH_ISWEAPON(deathtype, WEP_UZI))
                damage = autocvar_g_nades_nade_health * 0.1;
 
-       if(DEATH_ISWEAPON(deathtype, WEP_SHOTGUN))
+       if(DEATH_ISWEAPON(deathtype, WEP_SHOTGUN) && !(deathtype & HITTYPE_SECONDARY))
                damage = autocvar_g_nades_nade_health * 1.1;
+               
+       if(DEATH_ISWEAPON(deathtype, WEP_SHOTGUN) && (deathtype & HITTYPE_SECONDARY))
+       {
+               damage = autocvar_g_nades_nade_health * 0.1;
+               force *= 15;
+       }
        
        self.velocity += force;
 
@@ -143,14 +150,27 @@ void toss_nade(entity e, vector _velocity, float _time)
        entity _nade = e.nade;
        e.nade = world;
        
+       remove(e.fake_nade);
+       e.fake_nade = world;
+       
+       makevectors(e.v_angle);
+       
+       W_SetupShot(e, FALSE, FALSE, "", CH_WEAPON_A, 0);
+       
        Kill_Notification(NOTIF_ONE_ONLY, e, MSG_CENTER_CPID, CPID_NADES);
        
-       setorigin(_nade, gettaginfo(_nade, gettagindex(_nade, "Object001")));
+       //setorigin(_nade, CENTER_OR_VIEWOFS(e) + (v_right * 10) * -1);
+       setorigin(_nade, w_shotorg + (v_right * 10) * -1);
+       setmodel(_nade, "models/weapons/v_ok_grenade.md3");
        setattachment(_nade, world, "");
        PROJECTILE_MAKETRIGGER(_nade);
        setsize(_nade, '-16 -16 -16', '16 16 16');
        _nade.movetype = MOVETYPE_BOUNCE;
        
+       tracebox(_nade.origin, _nade.mins, _nade.maxs, _nade.origin, FALSE, _nade);
+       if (trace_startsolid)
+               setorigin(_nade, e.origin);
+       
        if(e.crouch)
                _nade.velocity = '0 0 -10';
        else if(autocvar_g_nades_nade_newton_style == 1)
@@ -158,14 +178,20 @@ void toss_nade(entity e, vector _velocity, float _time)
        else if(autocvar_g_nades_nade_newton_style == 2)
                _nade.velocity = _velocity;
        else
-               _nade.velocity = W_CalculateProjectileVelocity(e.velocity, _velocity, FALSE);
+               _nade.velocity = W_CalculateProjectileVelocity(e.velocity, _velocity, TRUE);
 
-       _nade.solid = SOLID_BBOX;
+       //_nade.solid = SOLID_BBOX; // TODO: remember why this was needed
        _nade.touch = nade_touch;
        _nade.health = autocvar_g_nades_nade_health;
-       _nade.takedamage = DAMAGE_YES;
+       _nade.takedamage = DAMAGE_AIM;
        _nade.event_damage = nade_damage;
        _nade.teleportable = TRUE;
+       _nade.pushable = TRUE;
+       _nade.gravity = 1;
+       _nade.missile_flags = MIF_SPLASH | MIF_ARC;
+       _nade.damagedbycontents = TRUE;
+       _nade.angles = vectoangles(_nade.velocity);
+       _nade.flags = FL_PROJECTILE;
 
        nade_spawn(_nade);
 
@@ -182,19 +208,33 @@ void nade_prime()
 {
        if(self.nade)
                remove(self.nade);
+               
+       if(self.fake_nade)
+               remove(self.fake_nade);
        
        self.nade = spawn();
-       setmodel(self.nade, "models/weapons/h_ok_grenade.iqm");
-       setattachment(self.nade, self.weaponentity, "");
+       setmodel(self.nade, "null");
+       setattachment(self.nade, self, "bip01 l hand");
        self.nade.classname = "nade";
        self.nade.realowner = self;
        self.nade.colormap = self.colormap;
        self.nade.glowmod = self.glowmod;
        self.nade.wait = time + autocvar_g_nades_nade_lifetime;
-       self.nade.cnt = time;
+       self.nade.lifetime = time;
        self.nade.think = nade_beep;
        self.nade.nextthink = max(self.nade.wait - 3, time);
        self.nade.projectiledeathtype = DEATH_NADE;
+
+       self.fake_nade = spawn();
+       setmodel(self.fake_nade, "models/weapons/h_ok_grenade.iqm");
+       setattachment(self.fake_nade, self.weaponentity, "");
+       self.fake_nade.classname = "fake_nade";
+       //self.fake_nade.viewmodelforclient = self;
+       self.fake_nade.realowner = self.fake_nade.owner = self;
+       self.fake_nade.colormap = self.colormap;
+       self.fake_nade.glowmod = self.glowmod;
+       self.fake_nade.think = SUB_Remove;
+       self.fake_nade.nextthink = self.nade.wait;
 }
 
 float CanThrowNade()
@@ -204,6 +244,9 @@ float CanThrowNade()
                
        if(gameover)
                return FALSE;
+               
+       if(self.deadflag != DEAD_NO)
+               return FALSE;
        
        if not(autocvar_g_nades)
                return FALSE; // allow turning them off mid match
@@ -236,10 +279,10 @@ MUTATOR_HOOKFUNCTION(nades_ForbidThrowing)
        }
        else
        {
-               if(time - self.nade.cnt >= 1)
+               if(time - self.nade.lifetime >= 1)
                {
                        makevectors(self.v_angle);
-                       float _force = time - self.nade.cnt;
+                       float _force = time - self.nade.lifetime;
                        _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);
@@ -259,7 +302,7 @@ MUTATOR_HOOKFUNCTION(nades_VehicleEnter)
 
 MUTATOR_HOOKFUNCTION(nades_PlayerPreThink)
 {
-       float key_pressed = ((g_grappling_hook) ? self.button16 : self.BUTTON_HOOK);
+       float key_pressed = ((g_grappling_hook || client_hasweapon(self, WEP_HOOK, FALSE, FALSE) || WEPSET_CONTAINS_AW(weaponsInMap, WEP_HOOK)) ? self.button16 : self.BUTTON_HOOK);
        
        if(self.nade)
                if(self.nade.wait - 0.1 <= time)
@@ -273,12 +316,12 @@ MUTATOR_HOOKFUNCTION(nades_PlayerPreThink)
                        if(!self.nade)
                                nade_prime();
                }
-               else if(time - self.nade.cnt >= 1)
+               else if(time - self.nade.lifetime >= 1)
                {
                        if(self.nade)
                        {
                                makevectors(self.v_angle);
-                               float _force = time - self.nade.cnt;
+                               float _force = time - self.nade.lifetime;
                                _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);
@@ -307,6 +350,17 @@ MUTATOR_HOOKFUNCTION(nades_PlayerDies)
        return FALSE;
 }
 
+MUTATOR_HOOKFUNCTION(nades_RemovePlayer)
+{
+       if(self.nade)
+               remove(self.nade);
+
+       if(self.fake_nade)
+               remove(self.fake_nade);
+               
+       return FALSE;
+}
+
 MUTATOR_HOOKFUNCTION(nades_BuildMutatorsString)
 {
        ret_string = strcat(ret_string, ":Nades");
@@ -326,6 +380,8 @@ MUTATOR_DEFINITION(mutator_nades)
        MUTATOR_HOOK(PlayerPreThink, nades_PlayerPreThink, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerSpawn, nades_PlayerSpawn, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerDies, nades_PlayerDies, CBC_ORDER_ANY);
+       MUTATOR_HOOK(MakePlayerObserver, nades_RemovePlayer, CBC_ORDER_ANY);
+       MUTATOR_HOOK(ClientDisconnect, nades_RemovePlayer, CBC_ORDER_ANY);
        MUTATOR_HOOK(BuildMutatorsString, nades_BuildMutatorsString, CBC_ORDER_ANY);
        MUTATOR_HOOK(BuildMutatorsPrettyString, nades_BuildMutatorsPrettyString, CBC_ORDER_ANY);