float 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_Add(entity cb, float() func, float order);
float CallbackChain_Remove(entity cb, float() func);
// a callback function is like this:
// float mycallback(entity me)
#define MUTATOR_REMOVING 0
#define MUTATOR_ADDING 1
+#define MUTATOR_ROLLING_BACK 2
typedef float(float) mutatorfunc_t;
float Mutator_Add(mutatorfunc_t func, string name);
void Mutator_Remove(mutatorfunc_t func, string name); // calls error() on fail
#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) { if(HOOK_##cb) CallbackChain_Remove(HOOK_##cb,HOOKFUNCTION_##func); } } while(0)
+#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_HOOKABLE(cb) entity HOOK_##cb
#define MUTATOR_CALLHOOK(cb) CallbackChain_Call(HOOK_##cb)
entity frag_attacker;
entity frag_target; // same as self
float frag_deathtype;
+
+MUTATOR_HOOKABLE(PlayerJump);
+ // called when a player presses the jump key
+ // INPUT, OUTPUT:
+ float player_multijump;
MUTATOR_HOOKABLE(GiveFragsForKill);
// called when someone was fragged by "self", and is expected to change frag_score to adjust scoring for the kill
// appends ", Mutator name" to ret_string for display
// INPUT, OUTPUT:
string ret_string;
+
+MUTATOR_HOOKABLE(CustomizeWaypoint);
+ // called every frame
+ // customizes the waypoint for spectators
+ // INPUT: self = waypoint, other = player, other.enemy = spectator
MUTATOR_HOOKABLE(FilterItem);
// checks if the current item may be spawned (self.items and self.weapons may be read and written to, as well as the ammo_ fields)
float damage_save;
MUTATOR_HOOKABLE(PlayerDamage_Calculate);
- // called to adjust damage and force values which are applied to the player, used for e.g. strength damage/force multiplier or runematch runes
+ // called to adjust damage and force values which are applied to the player, used for e.g. strength damage/force multiplier
// i'm not sure if I should change this around slightly (Naming of the entities, and also how they're done in g_damage).
// INPUT:
entity frag_attacker;
float frag_deathtype;
// INPUT, OUTPUT:
float frag_damage;
+ float frag_mirrordamage;
vector frag_force;
MUTATOR_HOOKABLE(PlayerPowerups);
MUTATOR_HOOKABLE(SetModname);
// OUT
string modname; // name of the mutator/mod if it warrants showing as such in the server browser
+
+MUTATOR_HOOKABLE(Item_Spawn);
+ // called for each item being spawned on a map, including dropped weapons
+ // return 1 to remove an item
+ // INPUT
+ entity self; // the item
MUTATOR_HOOKABLE(SetWeaponreplace);
// IN
entity other; // weapon info
// IN+OUT
string ret_string;
+
+MUTATOR_HOOKABLE(Item_RespawnCountdown);
+ // called when an item is about to respawn
+ // INPUT+OUTPUT:
+ string item_name;
+ vector item_color;
+
+MUTATOR_HOOKABLE(BotShouldAttack);
+ // called when a bot checks a target to attack
+ // INPUT
+ entity checkentity;
MUTATOR_HOOKABLE(PortalTeleport);
// called whenever a player goes through a portal gun teleport
// INPUT
entity self; // the player who pressed impulse 33
+MUTATOR_HOOKABLE(VehicleSpawn);
+ // called when a vehicle initializes
+ // return TRUE to remove the vehicle
+
MUTATOR_HOOKABLE(VehicleEnter);
// called when a player enters a vehicle
// allows mutators to set special settings in this event
entity vh_player; // player
entity vh_vehicle; // vehicle
+MUTATOR_HOOKABLE(VehicleTouch);
+ // called when a player touches a vehicle
+ // return TRUE to stop player from entering the vehicle
+ // INPUT
+ entity self; // vehicle
+ entity other; // player
+
MUTATOR_HOOKABLE(VehicleExit);
// called when a player exits a vehicle
// allows mutators to set special settings in this event
// called at when a item is touched. Called early, can edit item properties.
entity self; // item
entity other; // player
+ #define MUT_ITEMTOUCH_CONTINUE 0 // return this flag to make the function continue as normal
+ #define MUT_ITEMTOUCH_RETURN 1 // return this flag to make the function return (handled entirely by mutator)
+ #define MUT_ITEMTOUCH_PICKUP 2 // 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