From: Juhu <5894800-Juhu_@users.noreply.gitlab.com>
Date: Fri, 3 Feb 2023 23:38:28 +0000 (+0100)
Subject: q3df compat: implement target_speed entity
X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=50d925c2e29a1d800197d121720d915c49bd614f;p=xonotic%2Fxonotic-data.pk3dir.git

q3df compat: implement target_speed entity
---

diff --git a/qcsrc/common/mapobjects/target/_mod.inc b/qcsrc/common/mapobjects/target/_mod.inc
index f9cc536ed..9d97d6610 100644
--- a/qcsrc/common/mapobjects/target/_mod.inc
+++ b/qcsrc/common/mapobjects/target/_mod.inc
@@ -7,4 +7,5 @@
 #include <common/mapobjects/target/spawn.qc>
 #include <common/mapobjects/target/spawnpoint.qc>
 #include <common/mapobjects/target/speaker.qc>
+#include <common/mapobjects/target/speed.qc>
 #include <common/mapobjects/target/voicescript.qc>
diff --git a/qcsrc/common/mapobjects/target/_mod.qh b/qcsrc/common/mapobjects/target/_mod.qh
index e3f4cede9..48c57c42d 100644
--- a/qcsrc/common/mapobjects/target/_mod.qh
+++ b/qcsrc/common/mapobjects/target/_mod.qh
@@ -7,4 +7,5 @@
 #include <common/mapobjects/target/spawn.qh>
 #include <common/mapobjects/target/spawnpoint.qh>
 #include <common/mapobjects/target/speaker.qh>
+#include <common/mapobjects/target/speed.qh>
 #include <common/mapobjects/target/voicescript.qh>
diff --git a/qcsrc/common/mapobjects/target/speed.qc b/qcsrc/common/mapobjects/target/speed.qc
new file mode 100644
index 000000000..7ad194bfe
--- /dev/null
+++ b/qcsrc/common/mapobjects/target/speed.qc
@@ -0,0 +1,181 @@
+#include "speed.qh"
+
+#define XYZ_ARRAY(name) float name[3]
+#define ARRAY_AS_VECTOR(a) ((a)[0] * '1 0 0' + (a)[1] * '0 1 0' + (a)[2] * '0 0 1')
+#define VECTOR_TO_ARRAY(a, e) { vector v = (e); (a)[0] = v.x; (a)[1] = v.y; (a)[2] = v.z; }
+#define FOR_XYZ(idx) for(int idx = 0; idx < 3; ++idx)
+vector target_speed_calculatevelocity(entity this, float speed, entity pushed_entity)
+{
+	bool is_percentage = boolean(this.spawnflags & SPEED_PERCENTAGE);
+	bool is_add = boolean(this.spawnflags & SPEED_ADD);
+	bool is_launcher = boolean(this.spawnflags & SPEED_LAUNCHER);
+
+	bool is_positive[3];
+	is_positive[0] = boolean(this.spawnflags & SPEED_POSITIVE_X);
+	is_positive[1] = boolean(this.spawnflags & SPEED_POSITIVE_Y);
+	is_positive[2] = boolean(this.spawnflags & SPEED_POSITIVE_Z);
+
+	bool is_negative[3];
+	is_negative[0] = boolean(this.spawnflags & SPEED_NEGATIVE_X);
+	is_negative[1] = boolean(this.spawnflags & SPEED_NEGATIVE_Y);
+	is_negative[2] = boolean(this.spawnflags & SPEED_NEGATIVE_Z);
+
+	if(!is_add)
+	{
+		speed = max(speed, 0); // speed cannot be negative except when subtracting
+	}
+
+	XYZ_ARRAY(pushvel);
+	VECTOR_TO_ARRAY(pushvel, pushed_entity.velocity);
+
+	FOR_XYZ(i)
+	{
+		if(is_launcher && is_positive[i] && is_negative[i])
+		{
+			is_positive[i] = is_negative[i] = false; // launcher can only be either positive or negative not both
+		}
+
+		if(!is_positive[i] && !is_negative[i])
+		{
+			pushvel[i] = 0; // ignore this direction
+		}
+	}
+
+	float oldspeed = vlen(ARRAY_AS_VECTOR(pushvel));
+
+	if(is_percentage)
+	{
+		speed = oldspeed * speed / 100; // the speed field is used to specify the percentage of the current speed
+	}
+
+	float launcherspeed = 0;
+
+	FOR_XYZ(i)
+	{
+		if(((pushvel[i] != 0) || is_launcher) && (is_positive[i] != is_negative[i]))
+		{
+			if(is_launcher)
+			{
+				pushvel[i] = 1; // every direction weighs the same amount on launchers, movedir does not matter
+				launcherspeed += speed;
+				if(is_add) launcherspeed += oldspeed; // add the add speed in the same variable as it goes in the same direction
+			}
+
+			if(is_positive[i])
+			{
+				pushvel[i] = copysign(pushvel[i], 1);
+			}
+			else if(is_negative[i])
+			{
+				pushvel[i] = copysign(pushvel[i], -1);
+			}
+		}
+	}
+
+	XYZ_ARRAY(oldvel);
+	VECTOR_TO_ARRAY(oldvel, pushed_entity.velocity);
+
+	if(is_launcher)
+	{
+		VECTOR_TO_ARRAY(pushvel, normalize(ARRAY_AS_VECTOR(pushvel)) * fabs(launcherspeed)); // launcher will always launch you in the correct direction even if speed is negative, fabs() is correct
+	}
+	else
+	{
+		VECTOR_TO_ARRAY(pushvel, normalize(ARRAY_AS_VECTOR(pushvel)) * speed)
+
+		if(is_add)
+		{
+			VECTOR_TO_ARRAY(pushvel, ARRAY_AS_VECTOR(pushvel) + ARRAY_AS_VECTOR(oldvel));
+		}
+	}
+
+	FOR_XYZ(i)
+	{
+		if(!is_positive[i] && !is_negative[i])
+		{
+			pushvel[i] = oldvel[i]; // preserve unaffected directions
+		}
+	}
+
+	return ARRAY_AS_VECTOR(pushvel);
+}
+#undef XYZ_ARRAY
+#undef ARRAY_AS_VECTOR
+#undef VECTOR_TO_ARRAY
+#undef FOR_XYZ
+
+REGISTER_NET_LINKED(ENT_CLIENT_TARGET_SPEED)
+
+void target_speed_use(entity this, entity actor, entity trigger)
+{
+	if(this.active != ACTIVE_ACTIVE)
+		return;
+
+	actor.velocity = target_speed_calculatevelocity(this, this.speed, actor);
+}
+
+void target_speed_reset(entity this)
+{
+	this.active = ACTIVE_ACTIVE;
+}
+
+#ifdef SVQC
+void target_speed_link(entity this);
+
+/*
+ * ENTITY PARAMETERS:
+ *
+ *   targetname:  Activating trigger points to this.
+ *   speed:       Speed value to set (default: 100).
+ */
+spawnfunc(target_speed)
+{
+	this.active = ACTIVE_ACTIVE;
+	this.setactive = generic_netlinked_setactive;
+	this.use = target_speed_use;
+	this.reset = target_speed_reset;
+
+	// FIXME: zero and unset cannot be disambiguated in xonotic
+	//if (!this.speed)
+	//	this.speed = 100;
+
+	target_speed_link(this);
+}
+
+bool target_speed_send(entity this, entity to, float sf)
+{
+	WriteHeader(MSG_ENTITY, ENT_CLIENT_TARGET_SPEED);
+
+	WriteInt24_t(MSG_ENTITY, this.spawnflags);
+	WriteByte(MSG_ENTITY, this.active);
+	WriteString(MSG_ENTITY, this.targetname);
+	WriteCoord(MSG_ENTITY, this.speed);
+
+	return true;
+}
+
+void target_speed_link(entity this)
+{
+	Net_LinkEntity(this, false, 0, target_speed_send);
+}
+
+#elif defined(CSQC)
+
+void target_speed_remove(entity this)
+{
+	strfree(this.targetname);
+}
+
+NET_HANDLE(ENT_CLIENT_TARGET_SPEED, bool isnew)
+{
+	this.spawnflags = ReadInt24_t();
+	this.active = ReadByte();
+	this.targetname = strzone(ReadString());
+	this.speed = ReadCoord();
+
+	this.use = target_speed_use;
+	this.entremove = target_speed_remove;
+
+	return true;
+}
+#endif
diff --git a/qcsrc/common/mapobjects/target/speed.qh b/qcsrc/common/mapobjects/target/speed.qh
new file mode 100644
index 000000000..f5f0319ab
--- /dev/null
+++ b/qcsrc/common/mapobjects/target/speed.qh
@@ -0,0 +1,12 @@
+#pragma once
+
+
+const int SPEED_PERCENTAGE = BIT(0);
+const int SPEED_ADD = BIT(1);
+const int SPEED_POSITIVE_X = BIT(2);
+const int SPEED_NEGATIVE_X = BIT(3);
+const int SPEED_POSITIVE_Y = BIT(4);
+const int SPEED_NEGATIVE_Y = BIT(5);
+const int SPEED_POSITIVE_Z = BIT(6);
+const int SPEED_NEGATIVE_Z = BIT(7);
+const int SPEED_LAUNCHER = BIT(8);