weapon independency fixes
authordrjaska <drjaska83@gmail.com>
Sun, 22 May 2022 18:58:42 +0000 (21:58 +0300)
committerdrjaska <drjaska83@gmail.com>
Sun, 22 May 2022 19:03:58 +0000 (22:03 +0300)
Damage() function now checks that the target entity does not have a realowner which is another independent player before dealing damage and/or force to it
fireball's primary BFG no longer tries to target independent players
fireball's secondary "turrets" no longer try to target independent players
they also ignore frozen players as suggested by terence
electro's primary's explosion no longer explodes electro balls owned by other independent players
electro's primary's midair combo no longer explodes electro balls owned by other independent players
electro's comboexplosion no longer explodes electro balls owned by other independent players

qcsrc/common/weapons/weapon/electro.qc
qcsrc/common/weapons/weapon/fireball.qc
qcsrc/server/damage.qc

index d80703175983b87eb0c046ffa68e42276aad0d4e..3a70920e07839ed32bee603e7ec368c640b9bac2 100644 (file)
@@ -10,6 +10,13 @@ void W_Electro_TriggerCombo(vector org, float rad, entity own)
        {
                if(e.classname == "electro_orb")
                {
+                       // check if the ball we are exploding is not owned by an
+                       // independent player which is not the player who shot the ball
+                       if(IS_INDEPENDENT_PLAYER(e.realowner) && own != e.realowner)
+                       {
+                               e = e.chain;
+                               continue;
+                       }
                        // do we allow thruwall triggering?
                        if(WEP_CVAR(electro, combo_comboradius_thruwall))
                        {
@@ -151,6 +158,13 @@ void W_Electro_Bolt_Think(entity this)
                {
                        if(e.classname == "electro_orb")
                        {
+                               // check if the ball we are exploding is not owned by an
+                               // independent player which is not the player who shot the ball
+                               if(IS_INDEPENDENT_PLAYER(e.realowner) && this.realowner != e.realowner)
+                               {
+                                       e = e.chain;
+                                       continue;
+                               }
                                bool explode;
                                if (this.owner == e.owner)
                                {
index 3021843be0da7d12e6f2594b2c61f6169e07b161..b4a3da78a82e29c34afcd999ade1437cb2ef176c 100644 (file)
@@ -15,7 +15,20 @@ void W_Fireball_Explode(entity this, entity directhitentity)
 
        // 1. dist damage
        d = (GetResource(this.realowner, RES_HEALTH) + GetResource(this.realowner, RES_ARMOR));
-       RadiusDamage(this, this.realowner, WEP_CVAR_PRI(fireball, damage), WEP_CVAR_PRI(fireball, edgedamage), WEP_CVAR_PRI(fireball, radius), NULL, NULL, WEP_CVAR_PRI(fireball, force), this.projectiledeathtype, this.weaponentity_fld, directhitentity);
+
+       RadiusDamage(
+               this,
+               this.realowner,
+               WEP_CVAR_PRI(fireball, damage),
+               WEP_CVAR_PRI(fireball, edgedamage),
+               WEP_CVAR_PRI(fireball, radius),
+               NULL,
+               NULL,
+               WEP_CVAR_PRI(fireball, force),
+               this.projectiledeathtype,
+               this.weaponentity_fld, directhitentity
+       );
+
        if(GetResource(this.realowner, RES_HEALTH) + GetResource(this.realowner, RES_ARMOR) >= d)
        if(!this.cnt)
        {
@@ -24,28 +37,42 @@ void W_Fireball_Explode(entity this, entity directhitentity)
                // 2. bfg effect
                // NOTE: this cannot be made warpzone aware by design. So, better intentionally ignore warpzones here.
                for(e = findradius(this.origin, WEP_CVAR_PRI(fireball, bfgradius)); e; e = e.chain)
-               if(e != this.realowner) if(e.takedamage == DAMAGE_AIM) if(!IS_PLAYER(e) || !this.realowner || DIFF_TEAM(e, this))
                {
-                       // can we see fireball?
-                       traceline(e.origin + e.view_ofs, this.origin, MOVE_NORMAL, e);
-                       if(/* trace_startsolid || */ trace_fraction != 1) // startsolid should be never happening anyway
-                               continue;
-                       // can we see player who shot fireball?
-                       traceline(e.origin + e.view_ofs, this.realowner.origin + this.realowner.view_ofs, MOVE_NORMAL, e);
-                       if(trace_ent != this.realowner)
-                       if(/* trace_startsolid || */ trace_fraction != 1)
-                               continue;
-                       dist = vlen(this.origin - e.origin - e.view_ofs);
-                       points = (1 - sqrt(dist / WEP_CVAR_PRI(fireball, bfgradius)));
-                       if(points <= 0)
-                               continue;
-                       dir = normalize(e.origin + e.view_ofs - this.origin);
-
-                       if(accuracy_isgooddamage(this.realowner, e))
-                               accuracy_add(this.realowner, WEP_FIREBALL, 0, WEP_CVAR_PRI(fireball, bfgdamage) * points);
-
-                       Damage(e, this, this.realowner, WEP_CVAR_PRI(fireball, bfgdamage) * points, this.projectiledeathtype | HITTYPE_BOUNCE | HITTYPE_SPLASH, this.weaponentity_fld, e.origin + e.view_ofs, WEP_CVAR_PRI(fireball, bfgforce) * dir);
-                       Send_Effect(EFFECT_FIREBALL_BFGDAMAGE, e.origin, -1 * dir, 1);
+                       if(e != this.realowner && e.takedamage == DAMAGE_AIM && !IS_INDEPENDENT_PLAYER(e))
+                       if(!IS_PLAYER(e) || !this.realowner || DIFF_TEAM(e, this))
+                       {
+
+                               // can we see fireball?
+                               traceline(e.origin + e.view_ofs, this.origin, MOVE_NORMAL, e);
+                               if(/* trace_startsolid || */ trace_fraction != 1) // startsolid should be never happening anyway
+                                       continue;
+                               // can we see player who shot fireball?
+                               traceline(e.origin + e.view_ofs, this.realowner.origin + this.realowner.view_ofs, MOVE_NORMAL, e);
+                               if(trace_ent != this.realowner)
+                               if(/* trace_startsolid || */ trace_fraction != 1)
+                                       continue;
+                               dist = vlen(this.origin - e.origin - e.view_ofs);
+                               points = (1 - sqrt(dist / WEP_CVAR_PRI(fireball, bfgradius)));
+                               if(points <= 0)
+                                       continue;
+                               dir = normalize(e.origin + e.view_ofs - this.origin);
+
+                               if(accuracy_isgooddamage(this.realowner, e))
+                                       accuracy_add(this.realowner, WEP_FIREBALL, 0, WEP_CVAR_PRI(fireball, bfgdamage) * points);
+
+                               Damage(
+                                       e,
+                                       this,
+                                       this.realowner,
+                                       WEP_CVAR_PRI(fireball, bfgdamage) * points,
+                                       this.projectiledeathtype | HITTYPE_BOUNCE | HITTYPE_SPLASH,
+                                       this.weaponentity_fld,
+                                       e.origin + e.view_ofs,
+                                       WEP_CVAR_PRI(fireball, bfgforce) * dir
+                               );
+
+                               Send_Effect(EFFECT_FIREBALL_BFGDAMAGE, e.origin, -1 * dir, 1);
+                       }
                }
        }
 
@@ -80,7 +107,9 @@ void W_Fireball_LaserPlay(entity this, float dt, float dist, float damage, float
        RandomSelection_Init();
        for(e = WarpZone_FindRadius(this.origin, dist, true); e; e = e.chain)
        {
+               if(STAT(FROZEN, e)) continue;
                if(e == this.realowner) continue;
+               if(IS_INDEPENDENT_PLAYER(e)) continue;
                if(e.takedamage != DAMAGE_AIM) continue;
                if(IS_PLAYER(e) && this.realowner && SAME_TEAM(e, this)) continue;
 
index d0b3a288fb3011d5472d1d5df49a2d58ea217399..db9ddd0d9bd70c35034c7b933816561e330d63fd 100644 (file)
@@ -628,11 +628,19 @@ void Damage(entity targ, entity inflictor, entity attacker, float damage, int de
                if(deathtype != DEATH_TELEFRAG.m_id)
                if(IS_PLAYER(attacker))
                {
+                       // avoid dealing damage or force to other independent players
                        if(IS_PLAYER(targ) && targ != attacker && (IS_INDEPENDENT_PLAYER(attacker) || IS_INDEPENDENT_PLAYER(targ)))
                        {
                                damage = 0;
                                force = '0 0 0';
                        }
+                       // avoid dealing damage or force to things owned by other independent players
+                       if(targ.realowner)
+                       if(IS_INDEPENDENT_PLAYER(targ.realowner) && attacker != targ.realowner)
+                       {
+                               damage = 0;
+                               force = '0 0 0';
+                       }
                        else if(!STAT(FROZEN, targ) && SAME_TEAM(attacker, targ))
                        {
                                if(autocvar_teamplay_mode == 1)