]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Allow projectile<>projectile interactions to be disabled bones_was_here/g_projectiles_interact 1500/head
authorbones_was_here <bones_was_here@xonotic.au>
Thu, 1 May 2025 11:50:54 +0000 (21:50 +1000)
committerbones_was_here <bones_was_here@xonotic.au>
Thu, 8 May 2025 16:58:56 +0000 (02:58 +1000)
Adds cvar g_projectiles_interact which defaults to the traditional
behaviour.

balance-xonotic.cfg
qcsrc/common/checkextension.qc
qcsrc/common/weapons/weapon/blaster.qc
qcsrc/server/weapons/common.qc
qcsrc/server/weapons/common.qh

index 64f054caf0727ef45e47130c21134a297a14a20b..6fe54405c3b15395761347e7904faa5695af2346 100644 (file)
@@ -205,6 +205,7 @@ set g_balance_firetransfer_damage 0.8
 set g_throughfloor_damage 0.75
 set g_throughfloor_force 0.75
 set g_projectiles_damage -2 "\"-2\" = allow no damage to projectiles, \"-1\" = no damage other than the exceptions (electro combo, hagar join explode, ML mines), \"0\" = only damage from contents (lava/slime) or exceptions, \"1\" = only self damage or damage from contents or exceptions, \"2\" = allow all damage to projectiles"
+set g_projectiles_interact 2 "\"0\" = projectiles don't interact with each other (noclip through), \"1\" = projectiles don't interact except that blaster bolts detonate when hitting another projectile (deflect it), \"2\" = normal projectiles detonate and bouncy projectiles bounce off when hitting another projectile"
 set g_projectiles_keep_owner 1
 set g_projectiles_newton_style 0 "\"0\" = absolute velocity projectiles (like Quake), \"1\" = relative velocity projectiles, \"Newtonian\" (like Tribes 2), \"2\" = relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (NOTE: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)"
 set g_projectiles_newton_style_2_minfactor 0.8
index 9f10501ef73d3d0352d841679379c9f419a00db6..87e82862a3b6e2671cad64917e55ec7fa14b7a73 100644 (file)
@@ -52,6 +52,9 @@ void CheckEngineExtensions(void)
 
        if (!world.fullspawndata)
                LOG_WARN("Engine lacks entity fullspawndata, on Quake 3 maps some entities will malfunction.");
+
+       if (!checkextension("DP_RM_CLIPGROUP"))
+               LOG_WARN("Engine lacks DP_RM_CLIPGROUP, g_projectiles_interact < 2 won't take effect.");
 #endif
 
 #ifdef GAMEQC
index d426ae51e971b97ddc22aea65bfa1f36668368aa..6ce90db49409684f61ea055930a3210cfc42eccd 100644 (file)
@@ -11,6 +11,14 @@ void W_Blaster_Touch(entity this, entity toucher)
        vector force_xyzscale = '1 1 1';
        force_xyzscale.z = WEP_CVAR_PRI(WEP_BLASTER, force_zscale);
 
+       // slightly hacky but probably not worth adding a parameter for this special case
+       bool zero_damageforcescale = false;
+       if (autocvar_g_projectiles_interact == 1 && (toucher.flags & FL_PROJECTILE) && !toucher.damageforcescale)
+       {
+               toucher.damageforcescale = 1;
+               zero_damageforcescale = true;
+       }
+
        RadiusDamageForSource(
                this,
                (this.origin + (this.mins + this.maxs) * 0.5),
@@ -29,6 +37,9 @@ void W_Blaster_Touch(entity this, entity toucher)
                toucher
        );
 
+       if (zero_damageforcescale)
+               toucher.damageforcescale = 0;
+
        delete(this);
 }
 
index 252f83dc2a660c3b51783b56b6b93020d55d2a8d..09ad21ed4f28f99bb8c13f6630749a93fda2f737 100644 (file)
@@ -150,9 +150,18 @@ bool SUB_NoImpactCheck(entity this, entity toucher)
 
 bool WarpZone_Projectile_Touch_ImpactFilter_Callback(entity this, entity toucher)
 {
-       // owner check
        if(toucher && toucher == this.owner)
                return true;
+
+       if(autocvar_g_projectiles_interact == 1 && toucher.classname == "blasterbolt")
+       {
+               if (this.movetype == MOVETYPE_BOUNCE || this.movetype == MOVETYPE_BOUNCEMISSILE)
+                       // We'll bounce off it due to limitations so let it deflect us
+                       // to hide the problem, see PROJECTILE_MAKETRIGGER.
+                       gettouch(toucher)(toucher, this);
+               return true;
+       }
+
        if(SUB_NoImpactCheck(this, toucher))
        {
                if(this.classname == "nade")
index 779226be3dfc98ded7bb21b56042e9ac54265b40..40b576108c9997eea033aadbd0b625f156aad89c 100644 (file)
@@ -1,6 +1,7 @@
 #pragma once
 
 int autocvar_g_projectiles_damage;
+int autocvar_g_projectiles_interact = 2;
 bool autocvar_g_projectiles_keep_owner;
 float autocvar_sv_strengthsound_antispam_refire_threshold;
 float autocvar_sv_strengthsound_antispam_time;
@@ -26,7 +27,16 @@ bool WarpZone_Projectile_Touch_ImpactFilter_Callback(entity this, entity toucher
 
 #define PROJECTILE_TOUCH(e,t) MACRO_BEGIN if (WarpZone_Projectile_Touch(e,t)) return; MACRO_END
 
-#define PROJECTILE_MAKETRIGGER(e) (e).solid = SOLID_CORPSE; (e).dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE
+// FIXME: some behaviours can't be achieved or would require kludges in physics code,
+// eg we can't make electro bolts hit electro orbs only (without causing other problems) when g_projectiles_interact == 1,
+// see also WarpZone_Projectile_Touch_ImpactFilter_Callback().
+// Ideally, extend engine to support any combination of 'hit a and b but not x or y' and 'take hits from c and d but not w or z'.
+#define PROJECTILE_MAKETRIGGER(e) \
+       (e).solid = SOLID_CORPSE; \
+       (e).dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE; \
+       if (!autocvar_g_projectiles_interact || (autocvar_g_projectiles_interact == 1 && (e).classname != "blasterbolt")) \
+               (e).clipgroup = FL_PROJECTILE
+
 // when doing this, hagar can go through clones
 // #define PROJECTILE_MAKETRIGGER(e) (e).solid = SOLID_BBOX