From: cloudwalk <cloudwalk@d7cf8633-e32d-0410-b094-e92efae38249>
Date: Tue, 26 May 2020 13:38:28 +0000 (+0000)
Subject: Implement clipgroup extension from DarkplacesRM
X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=fc4a5f1101c87081f94ad550d6b3fd1beee37b54;p=xonotic%2Fdarkplaces.git

Implement clipgroup extension from DarkplacesRM

This allows magical things to happen, such as disabling teammate collision
in Xonotic.

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12585 d7cf8633-e32d-0410-b094-e92efae38249
---

diff --git a/cl_collision.c b/cl_collision.c
index 56eac018..924d017c 100644
--- a/cl_collision.c
+++ b/cl_collision.c
@@ -227,6 +227,7 @@ trace_t CL_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int
 	// list of entities to test for collisions
 	int numtouchedicts;
 	static prvm_edict_t *touchedicts[MAX_EDICTS];
+	int clipgroup;
 
 	if (hitnetworkentity)
 		*hitnetworkentity = 0;
@@ -280,6 +281,8 @@ trace_t CL_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int
 	// precalculate passedict's owner edict pointer for comparisons
 	traceowner = passedict ? PRVM_PROG_TO_EDICT(PRVM_clientedictedict(passedict, owner)) : NULL;
 
+	clipgroup = passedict ? (int)PRVM_clientedictfloat(passedict, clipgroup) : 0;
+
 	// collide against network entities
 	if (hitnetworkbrushmodels)
 	{
@@ -381,6 +384,9 @@ skipnetworkplayers:
 			// don't clip owner against owned entities
 			if (passedictprog == PRVM_clientedictedict(touch, owner))
 				continue;
+			// don't clip against any entities in the same clipgroup (DP_RM_CLIPGROUP)
+			if (clipgroup && clipgroup == (int)PRVM_clientedictfloat(touch, clipgroup))
+				continue;
 			// don't clip points against points (they can't collide)
 			if (VectorCompare(PRVM_clientedictvector(touch, mins), PRVM_clientedictvector(touch, maxs)) && (type != MOVE_MISSILE || !((int)PRVM_clientedictfloat(touch, flags) & FL_MONSTER)))
 				continue;
@@ -442,6 +448,7 @@ trace_t CL_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_
 	// list of entities to test for collisions
 	int numtouchedicts;
 	static prvm_edict_t *touchedicts[MAX_EDICTS];
+	int clipgroup;
 	if (VectorCompare(start, end))
 		return CL_TracePoint(start, type, passedict, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, hitnetworkbrushmodels, hitnetworkplayers, hitnetworkentity, hitcsqcentities);
 
@@ -498,6 +505,8 @@ trace_t CL_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_
 	// precalculate passedict's owner edict pointer for comparisons
 	traceowner = passedict ? PRVM_PROG_TO_EDICT(PRVM_clientedictedict(passedict, owner)) : NULL;
 
+	clipgroup = passedict ? (int)PRVM_clientedictfloat(passedict, clipgroup) : 0;
+
 	// collide against network entities
 	if (hitnetworkbrushmodels)
 	{
@@ -599,6 +608,9 @@ skipnetworkplayers:
 			// don't clip owner against owned entities
 			if (passedictprog == PRVM_clientedictedict(touch, owner))
 				continue;
+			// don't clip against any entities in the same clipgroup (DP_RM_CLIPGROUP)
+			if (clipgroup && clipgroup == (int)PRVM_clientedictfloat(touch, clipgroup))
+				continue;
 			// don't clip points against points (they can't collide)
 			if (VectorCompare(PRVM_clientedictvector(touch, mins), PRVM_clientedictvector(touch, maxs)) && (type != MOVE_MISSILE || !((int)PRVM_clientedictfloat(touch, flags) & FL_MONSTER)))
 				continue;
@@ -664,6 +676,7 @@ trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, co
 	// list of entities to test for collisions
 	int numtouchedicts;
 	static prvm_edict_t *touchedicts[MAX_EDICTS];
+	int clipgroup;
 	if (VectorCompare(mins, maxs))
 	{
 		vec3_t shiftstart, shiftend;
@@ -743,6 +756,8 @@ trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, co
 	// precalculate passedict's owner edict pointer for comparisons
 	traceowner = passedict ? PRVM_PROG_TO_EDICT(PRVM_clientedictedict(passedict, owner)) : NULL;
 
+	clipgroup = passedict ? (int)PRVM_clientedictfloat(passedict, clipgroup) : 0;
+
 	// collide against network entities
 	if (hitnetworkbrushmodels)
 	{
@@ -844,6 +859,9 @@ skipnetworkplayers:
 			// don't clip owner against owned entities
 			if (passedictprog == PRVM_clientedictedict(touch, owner))
 				continue;
+			// don't clip against any entities in the same clipgroup (DP_RM_CLIPGROUP)
+			if (clipgroup && clipgroup == (int)PRVM_clientedictfloat(touch, clipgroup))
+				continue;
 			// don't clip points against points (they can't collide)
 			if (pointtrace && VectorCompare(PRVM_clientedictvector(touch, mins), PRVM_clientedictvector(touch, maxs)) && (type != MOVE_MISSILE || !((int)PRVM_clientedictfloat(touch, flags) & FL_MONSTER)))
 				continue;
diff --git a/dpdefs/dpextensions.qc b/dpdefs/dpextensions.qc
index f1e48f07..9cdeb695 100644
--- a/dpdefs/dpextensions.qc
+++ b/dpdefs/dpextensions.qc
@@ -2608,3 +2608,11 @@ float MOVETYPE_USER_FIRST = 128;
 float MOVETYPE_USER_LAST = 191;
 //description:
 //user defined movetypes can be added between the start and end points, without producing unknown movetype warnings
+
+//DP_RM_CLIPGROUP
+//idea: Akari
+//darkplaces implementation: Akari
+//field definitions:
+.float clipgroup;
+//description:
+//If two entities have this field set to the same non-zero integer value, they won't collide with each other.
diff --git a/prvm_offsets.h b/prvm_offsets.h
index 1563a051..5eada948 100644
--- a/prvm_offsets.h
+++ b/prvm_offsets.h
@@ -8,6 +8,7 @@ PRVM_DECLARE_clientfieldfloat(alpha)
 PRVM_DECLARE_clientfieldfloat(bouncefactor)
 PRVM_DECLARE_clientfieldfloat(bouncestop)
 PRVM_DECLARE_clientfieldfloat(colormap)
+PRVM_DECLARE_clientfieldfloat(clipgroup)
 PRVM_DECLARE_clientfieldfloat(dphitcontentsmask)
 PRVM_DECLARE_clientfieldfloat(drawmask)
 PRVM_DECLARE_clientfieldfloat(effects)
@@ -256,6 +257,7 @@ PRVM_DECLARE_field(classname)
 PRVM_DECLARE_field(clientcamera)
 PRVM_DECLARE_field(clientcolors)
 PRVM_DECLARE_field(clientstatus)
+PRVM_DECLARE_field(clipgroup)
 PRVM_DECLARE_field(color)
 PRVM_DECLARE_field(colormap)
 PRVM_DECLARE_field(colormod)
@@ -647,6 +649,7 @@ PRVM_DECLARE_serverfieldfloat(button16)
 PRVM_DECLARE_serverfieldfloat(buttonchat)
 PRVM_DECLARE_serverfieldfloat(buttonuse)
 PRVM_DECLARE_serverfieldfloat(clientcolors)
+PRVM_DECLARE_serverfieldfloat(clipgroup)
 PRVM_DECLARE_serverfieldfloat(colormap)
 PRVM_DECLARE_serverfieldfloat(currentammo)
 PRVM_DECLARE_serverfieldfloat(cursor_active)
diff --git a/sv_phys.c b/sv_phys.c
index 1a774216..94587293 100644
--- a/sv_phys.c
+++ b/sv_phys.c
@@ -126,6 +126,7 @@ trace_t SV_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int
 	// list of entities to test for collisions
 	int numtouchedicts;
 	static prvm_edict_t *touchedicts[MAX_EDICTS];
+	int clipgroup;
 
 	//return SV_TraceBox(start, vec3_origin, vec3_origin, end, type, passedict, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
 
@@ -176,6 +177,8 @@ trace_t SV_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int
 	// precalculate passedict's owner edict pointer for comparisons
 	traceowner = passedict ? PRVM_PROG_TO_EDICT(PRVM_serveredictedict(passedict, owner)) : 0;
 
+	clipgroup = passedict ? (int)PRVM_serveredictfloat(passedict, clipgroup) : 0;
+
 	// clip to entities
 	// because this uses World_EntitiestoBox, we know all entity boxes overlap
 	// the clip region, so we can skip culling checks in the loop below
@@ -206,6 +209,9 @@ trace_t SV_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int
 			// don't clip owner against owned entities
 			if (passedictprog == PRVM_serveredictedict(touch, owner))
 				continue;
+			// don't clip against any entities in the same clipgroup (DP_RM_CLIPGROUP)
+			if (clipgroup && clipgroup == (int)PRVM_serveredictfloat(touch, clipgroup))
+				continue;
 			// don't clip points against points (they can't collide)
 			if (VectorCompare(PRVM_serveredictvector(touch, mins), PRVM_serveredictvector(touch, maxs)) && (type != MOVE_MISSILE || !((int)PRVM_serveredictfloat(touch, flags) & FL_MONSTER)))
 				continue;
@@ -272,6 +278,7 @@ trace_t SV_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_
 	// list of entities to test for collisions
 	int numtouchedicts;
 	static prvm_edict_t *touchedicts[MAX_EDICTS];
+	int clipgroup;
 	if (VectorCompare(start, end))
 		return SV_TracePoint(start, type, passedict, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
 
@@ -325,6 +332,8 @@ trace_t SV_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_
 	// precalculate passedict's owner edict pointer for comparisons
 	traceowner = passedict ? PRVM_PROG_TO_EDICT(PRVM_serveredictedict(passedict, owner)) : 0;
 
+	clipgroup = passedict ? (int)PRVM_serveredictfloat(passedict, clipgroup) : 0;
+
 	// clip to entities
 	// because this uses World_EntitiestoBox, we know all entity boxes overlap
 	// the clip region, so we can skip culling checks in the loop below
@@ -355,6 +364,9 @@ trace_t SV_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_
 			// don't clip owner against owned entities
 			if (passedictprog == PRVM_serveredictedict(touch, owner))
 				continue;
+			// don't clip against any entities in the same clipgroup (DP_RM_CLIPGROUP)
+			if (clipgroup && clipgroup == (int)PRVM_serveredictfloat(touch, clipgroup))
+				continue;
 			// don't clip points against points (they can't collide)
 			if (VectorCompare(PRVM_serveredictvector(touch, mins), PRVM_serveredictvector(touch, maxs)) && (type != MOVE_MISSILE || !((int)PRVM_serveredictfloat(touch, flags) & FL_MONSTER)))
 				continue;
@@ -429,6 +441,7 @@ trace_t SV_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, co
 	// list of entities to test for collisions
 	int numtouchedicts;
 	static prvm_edict_t *touchedicts[MAX_EDICTS];
+	int clipgroup;
 	if (VectorCompare(mins, maxs))
 	{
 		vec3_t shiftstart, shiftend;
@@ -503,6 +516,8 @@ trace_t SV_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, co
 	// precalculate passedict's owner edict pointer for comparisons
 	traceowner = passedict ? PRVM_PROG_TO_EDICT(PRVM_serveredictedict(passedict, owner)) : 0;
 
+	clipgroup = passedict ? (int)PRVM_serveredictfloat(passedict, clipgroup) : 0;
+
 	// clip to entities
 	// because this uses World_EntitiestoBox, we know all entity boxes overlap
 	// the clip region, so we can skip culling checks in the loop below
@@ -533,6 +548,9 @@ trace_t SV_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, co
 			// don't clip owner against owned entities
 			if (passedictprog == PRVM_serveredictedict(touch, owner))
 				continue;
+			// don't clip against any entities in the same clipgroup (DP_RM_CLIPGROUP)
+			if (clipgroup && clipgroup == (int)PRVM_serveredictfloat(touch, clipgroup))
+				continue;
 			// don't clip points against points (they can't collide)
 			if (pointtrace && VectorCompare(PRVM_serveredictvector(touch, mins), PRVM_serveredictvector(touch, maxs)) && (type != MOVE_MISSILE || !((int)PRVM_serveredictfloat(touch, flags) & FL_MONSTER)))
 				continue;
diff --git a/svvm_cmds.c b/svvm_cmds.c
index fbfe70ad..0e1a8720 100644
--- a/svvm_cmds.c
+++ b/svvm_cmds.c
@@ -227,6 +227,7 @@ const char *vm_sv_extensions =
 "TENEBRAE_GFX_DLIGHTS "
 "TW_SV_STEPCONTROL "
 "ZQ_PAUSE "
+"DP_RM_CLIPGROUP "
 //"EXT_CSQC " // not ready yet
 ;