From 05a4d3a3cc3437585dbbeecbb0f3e897853fb519 Mon Sep 17 00:00:00 2001
From: TimePath <andrew.hardaker1995@gmail.com>
Date: Fri, 15 May 2015 13:28:11 +1000
Subject: [PATCH] Cleanup mutators

---
 qcsrc/server/mutators/base.qc | 121 ++++++++++++++--------------------
 qcsrc/server/mutators/base.qh |  81 ++++++++++++++---------
 2 files changed, 97 insertions(+), 105 deletions(-)

diff --git a/qcsrc/server/mutators/base.qc b/qcsrc/server/mutators/base.qc
index f642a3bdf..2f78ec182 100644
--- a/qcsrc/server/mutators/base.qc
+++ b/qcsrc/server/mutators/base.qc
@@ -1,75 +1,60 @@
 #include "base.qh"
 #include "../_all.qh"
 
-.float() cbc_func;
+.bool() cbc_func;
 .entity cbc_next;
-.float cbc_order;
+.int cbc_order;
 
 entity CallbackChain_New(string name)
 {
-	entity e;
-	e = spawn();
+	entity e = spawn();
 	e.classname = "callbackchain";
 	e.netname = name;
 	return e;
 }
 
-float CallbackChain_Add(entity cb, float() func, float order)
+bool CallbackChain_Add(entity cb, bool() func, int order)
 {
-	entity e;
-	if(order & CBC_ORDER_FIRST)
-	{
-		if(order & CBC_ORDER_LAST)
-			if(cb.cbc_order & CBC_ORDER_ANY)
-				return 0;
-		if(cb.cbc_order & CBC_ORDER_FIRST)
-			return 0;
+	if (order & CBC_ORDER_FIRST) {
+		if (order & CBC_ORDER_LAST)
+			if (cb.cbc_order & CBC_ORDER_ANY)
+				return false;
+		if (cb.cbc_order & CBC_ORDER_FIRST)
+			return false;
+	} else if (order & CBC_ORDER_LAST) {
+		if (cb.cbc_order & CBC_ORDER_LAST)
+			return false;
 	}
-	else if(order & CBC_ORDER_LAST)
-	{
-		if(cb.cbc_order & CBC_ORDER_LAST)
-			return 0;
-	}
-	entity thiscb;
-	thiscb = spawn();
+	entity thiscb = spawn();
 	thiscb.classname = "callback";
 	thiscb.cbc_func = func;
 	thiscb.cbc_order = order;
-	if(order & CBC_ORDER_FIRST)
-	{
+	if (order & CBC_ORDER_FIRST) {
 		thiscb.cbc_next = cb.cbc_next;
 		cb.cbc_next = thiscb;
-	}
-	else if(order & CBC_ORDER_LAST)
-	{
-		for(e = cb; e.cbc_next; e = e.cbc_next);
+	} else if (order & CBC_ORDER_LAST) {
+		entity e = cb;
+		while (e.cbc_next) e = e.cbc_next;
 		e.cbc_next = thiscb;
-	}
-	else
-	{
+	} else {
 		// by default we execute last, but before a possible CBC_ORDER_LAST callback
-		for(e = cb; e.cbc_next && !(e.cbc_next.cbc_order & CBC_ORDER_LAST); e = e.cbc_next); // we must make sure that we insert BEFORE an CBC_ORDER_LAST mutator!
+		entity e = cb;
+		// we must make sure that we insert BEFORE an CBC_ORDER_LAST mutator!
+		while (e.cbc_next && !(e.cbc_next.cbc_order & CBC_ORDER_LAST)) e = e.cbc_next;
 		thiscb.cbc_next = e.cbc_next;
 		e.cbc_next = thiscb;
 	}
 	cb.cbc_order |= (order | CBC_ORDER_ANY);
-	return 1;
+	return true;
 }
 
-float CallbackChain_Remove(entity cb, float() func)
+int CallbackChain_Remove(entity cb, bool() func)
 {
-	float order;
-	entity e;
-	float n;
-	n = 0;
-	order = 0;
-	for(e = cb; e.cbc_next; e = e.cbc_next)
-	{
-		while(e.cbc_next.cbc_func == func)
-		{
+	int n = 0, order = 0;
+	for (entity e = cb; e.cbc_next; e = e.cbc_next) {
+		while (e.cbc_next.cbc_func == func) {
 			// remove e.cbc_next from the chain
-			entity e2;
-			e2 = e.cbc_next.cbc_next;
+			entity e2 = e.cbc_next.cbc_next;
 			remove(e.cbc_next);
 			e.cbc_next = e2;
 			++n;
@@ -81,69 +66,59 @@ float CallbackChain_Remove(entity cb, float() func)
 	return n;
 }
 
-float CallbackChain_Call(entity cb)
+bool CallbackChain_Call(entity cb)
 {
-	float r;
-	entity e;
-	r = 0;
-	for(e = cb; e.cbc_next; e = e.cbc_next)
-	{
+	bool r = false;
+	for (entity e = cb; e.cbc_next; e = e.cbc_next) {
 		CallbackChain_ReturnValue = r;
 		r |= e.cbc_next.cbc_func();
 	}
 	return r; // callbacks return an error status, so 0 is default return value
 }
 
-const float MAX_MUTATORS = 15;
+const int MAX_MUTATORS = 15;
 string loaded_mutators[MAX_MUTATORS];
-float Mutator_Add(mutatorfunc_t func, string name)
+bool Mutator_Add(mutatorfunc_t func, string name)
 {
-	int i, j;
-	j = -1;
-	for(i = 0; i < MAX_MUTATORS; ++i)
-	{
-		if(name == loaded_mutators[i])
-			return 1; // already added
+	int j = -1;
+	for (int i = 0; i < MAX_MUTATORS; ++i) {
+		if (name == loaded_mutators[i])
+			return true; // already added
 		if (!(loaded_mutators[i]))
 			j = i;
 	}
-	if(j < 0)
-	{
+	if (j < 0) {
 		backtrace("WARNING: too many mutators, cannot add any more\n");
-		return 0;
+		return false;
 	}
 	loaded_mutators[j] = name;
 
-	if(func(MUTATOR_ADDING) == 0)
-	{
+	if (!func(MUTATOR_ADDING)) {
 		// good
-		return 1;
+		return true;
 	}
 
 	backtrace("WARNING: when adding mutator: adding failed, rolling back\n");
 
-	if(func(MUTATOR_ROLLING_BACK) != 0)
-	{
+	if (func(MUTATOR_ROLLING_BACK)) {
 		// baaaaad
 		error("WARNING: when adding mutator: rolling back failed");
 	}
-	return 0;
+	return false;
 }
-void Mutator_Remove(float(float) func, string name)
+void Mutator_Remove(mutatorfunc_t func, string name)
 {
 	int i;
-	for(i = 0; i < MAX_MUTATORS; ++i)
-		if(name == loaded_mutators[i])
+	for (i = 0; i < MAX_MUTATORS; ++i)
+		if (name == loaded_mutators[i])
 			break;
-	if(i >= MAX_MUTATORS)
-	{
+	if (i >= MAX_MUTATORS) {
 		backtrace("WARNING: removing not-added mutator\n");
 		return;
 	}
 	loaded_mutators[i] = string_null;
 
-	if(func(MUTATOR_REMOVING) != 0)
-	{
+	if (func(MUTATOR_REMOVING) != 0) {
 		// baaaaad
 		error("Mutator_Remove: removing mutator failed");
 	}
diff --git a/qcsrc/server/mutators/base.qh b/qcsrc/server/mutators/base.qh
index 199cb62fb..f4d0292d2 100644
--- a/qcsrc/server/mutators/base.qh
+++ b/qcsrc/server/mutators/base.qh
@@ -1,39 +1,52 @@
 #ifndef MUTATORS_BASE_H
 #define MUTATORS_BASE_H
-const float CBC_ORDER_EXCLUSIVE = 3;
-const float CBC_ORDER_FIRST = 1;
-const float CBC_ORDER_LAST = 2;
-const float CBC_ORDER_ANY = 4;
+const int CBC_ORDER_FIRST = 1;
+const int CBC_ORDER_LAST = 2;
+const int CBC_ORDER_EXCLUSIVE = 3;
+const int CBC_ORDER_ANY = 4;
 
-float CallbackChain_ReturnValue; // read-only field of the current return value
+bool CallbackChain_ReturnValue; // read-only field of the current return value
 
 entity CallbackChain_New(string name);
-float CallbackChain_Add(entity cb, float() func, float order);
-float CallbackChain_Remove(entity cb, float() func);
+bool CallbackChain_Add(entity cb, bool() func, int order);
+int CallbackChain_Remove(entity cb, bool() func);
 // a callback function is like this:
-// float mycallback(entity me)
+// bool mycallback(entity me)
 // {
 //   do something
-//   return r;
+//   return false;
 // }
-float CallbackChain_Call(entity cb);
-
-const float MUTATOR_REMOVING = 0;
-const float MUTATOR_ADDING = 1;
-const float MUTATOR_ROLLING_BACK = 2;
-typedef float(float) mutatorfunc_t;
-float Mutator_Add(mutatorfunc_t func, string name);
+bool CallbackChain_Call(entity cb);
+
+enum {
+	MUTATOR_REMOVING,
+	MUTATOR_ADDING,
+	MUTATOR_ROLLING_BACK
+};
+typedef bool(int) mutatorfunc_t;
+bool Mutator_Add(mutatorfunc_t func, string name);
 void Mutator_Remove(mutatorfunc_t func, string name); // calls error() on fail
 
 #define MUTATOR_ADD(name) Mutator_Add(MUTATOR_##name, #name)
 #define MUTATOR_REMOVE(name) Mutator_Remove(MUTATOR_##name, #name)
-#define MUTATOR_DEFINITION(name) float MUTATOR_##name(float mode)
-#define MUTATOR_DECLARATION(name) float MUTATOR_##name(float mode)
-#define MUTATOR_HOOKFUNCTION(name) float HOOKFUNCTION_##name()
-#define MUTATOR_HOOK(cb,func,order) do { if(mode == MUTATOR_ADDING) { if(!HOOK_##cb) HOOK_##cb = CallbackChain_New(#cb); if(!CallbackChain_Add(HOOK_##cb,HOOKFUNCTION_##func,order)) { print("HOOK FAILED: ", #func, "\n"); return 1; } } else if(mode == MUTATOR_REMOVING || mode == MUTATOR_ROLLING_BACK) { if(HOOK_##cb) CallbackChain_Remove(HOOK_##cb,HOOKFUNCTION_##func); } } while(0)
-#define MUTATOR_ONADD if(mode == MUTATOR_ADDING)
-#define MUTATOR_ONREMOVE if(mode == MUTATOR_REMOVING)
-#define MUTATOR_ONROLLBACK_OR_REMOVE if(mode == MUTATOR_REMOVING || mode == MUTATOR_ROLLING_BACK)
+#define MUTATOR_DEFINITION(name) bool MUTATOR_##name(int mode)
+#define MUTATOR_DECLARATION(name) bool MUTATOR_##name(int mode)
+#define MUTATOR_HOOKFUNCTION(name) bool HOOKFUNCTION_##name()
+#define MUTATOR_HOOK(cb, func, order) do { 										\
+	MUTATOR_ONADD { 															\
+		if (!HOOK_##cb) HOOK_##cb = CallbackChain_New(#cb); 					\
+		if (!CallbackChain_Add(HOOK_##cb, HOOKFUNCTION_##func, order)) { 		\
+			print("HOOK FAILED: ", #func, "\n"); 								\
+			return true; 														\
+		} 																		\
+	} 																			\
+	MUTATOR_ONROLLBACK_OR_REMOVE { 												\
+		if (HOOK_##cb) CallbackChain_Remove(HOOK_##cb, HOOKFUNCTION_##func);	\
+	} 																			\
+} while(0)
+#define MUTATOR_ONADD if (mode == MUTATOR_ADDING)
+#define MUTATOR_ONREMOVE if (mode == MUTATOR_REMOVING)
+#define MUTATOR_ONROLLBACK_OR_REMOVE if (mode == MUTATOR_REMOVING || mode == MUTATOR_ROLLING_BACK)
 
 #define MUTATOR_HOOKABLE(cb) entity HOOK_##cb
 #define MUTATOR_CALLHOOK(cb) CallbackChain_Call(HOOK_##cb)
@@ -74,7 +87,7 @@ MUTATOR_HOOKABLE(PlayerDies);
 		entity frag_inflictor;
 		entity frag_attacker;
 		entity frag_target; // same as self
-		float frag_deathtype;
+		int frag_deathtype;
 
 MUTATOR_HOOKABLE(PlayerJump);
 	// called when a player presses the jump key
@@ -231,7 +244,7 @@ MUTATOR_HOOKABLE(PlayerPowerups);
 	// called at the end of player_powerups() in cl_client.qc, used for manipulating the values which are set by powerup items.
 	// INPUT
 //	entity self;
-	float olditems; // also technically output, but since it is at the end of the function it's useless for that :P
+	int olditems; // also technically output, but since it is at the end of the function it's useless for that :P
 
 MUTATOR_HOOKABLE(PlayerRegen);
 	// called every player think frame
@@ -254,7 +267,7 @@ MUTATOR_HOOKABLE(SV_ParseClientCommand);
 	// NOTE: THESE HOOKS MUST NEVER EVER CALL tokenize()
 	// INPUT
 	string cmd_name; // command name
-	float cmd_argc; // also, argv() can be used
+	int cmd_argc; // also, argv() can be used
 	string cmd_string; // whole command, use only if you really have to
 	/*
 		// example:
@@ -364,9 +377,11 @@ MUTATOR_HOOKABLE(ItemTouch);
 	// called at when a item is touched. Called early, can edit item properties.
 //	entity self;	// item
 //	entity other; 	// player
-	const float MUT_ITEMTOUCH_CONTINUE = 0; // return this flag to make the function continue as normal
-	const float MUT_ITEMTOUCH_RETURN = 1; // return this flag to make the function return (handled entirely by mutator)
-	const float MUT_ITEMTOUCH_PICKUP = 2; // return this flag to have the item "picked up" and taken even after mutator handled it
+enum {
+	MUT_ITEMTOUCH_CONTINUE, // return this flag to make the function continue as normal
+	MUT_ITEMTOUCH_RETURN, // return this flag to make the function return (handled entirely by mutator)
+	MUT_ITEMTOUCH_PICKUP // return this flag to have the item "picked up" and taken even after mutator handled it
+};
 
 MUTATOR_HOOKABLE(ClientConnect);
 	// called at when a player connect
@@ -379,7 +394,9 @@ MUTATOR_HOOKABLE(AccuracyTargetValid);
 	// called when a target is checked for accuracy
 //	entity frag_attacker; // attacker
 //	entity frag_target; // target
-	const float MUT_ACCADD_VALID = 0; // return this flag to make the function continue if target is a client
-	const float MUT_ACCADD_INVALID = 1; // return this flag to make the function always continue
-	const float MUT_ACCADD_INDIFFERENT = 2; // return this flag to make the function always return
+enum {
+	MUT_ACCADD_VALID, // return this flag to make the function continue if target is a client
+	MUT_ACCADD_INVALID, // return this flag to make the function always continue
+	MUT_ACCADD_INDIFFERENT // return this flag to make the function always return
+};
 #endif
-- 
2.39.5