#define CBC_ORDER_EXCLUSIVE 3 #define CBC_ORDER_FIRST 1 #define CBC_ORDER_LAST 2 #define CBC_ORDER_ANY 4 entity CallbackChain_New(string name); 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) // { // do something // return r; // } float CallbackChain_Call(entity cb); #define MUTATOR_REMOVING 0 #define MUTATOR_ADDING 1 float Mutator_Add(float(float) func); void Mutator_Remove(float(float) func); // calls error() on fail #define MUTATOR_ADD(name) Mutator_Add(MUTATOR_##name) #define MUTATOR_REMOVE(name) Mutator_Remove(MUTATOR_##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) { 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_HOOKABLE(cb) entity HOOK_##cb #define MUTATOR_CALLHOOK(cb) CallbackChain_Call(HOOK_##cb) // register all possible hooks here MUTATOR_HOOKABLE(MakePlayerObserver); MUTATOR_HOOKABLE(MakePlayerSpectator); MUTATOR_HOOKABLE(PlayerSpawn); MUTATOR_HOOKABLE(ClientDisconnect); MUTATOR_HOOKABLE(PlayerDies); entity other; entity frag_attacker; MUTATOR_HOOKABLE(GiveFragsForKill); entity frag_attacker, frag_target; float frag_score; MUTATOR_HOOKABLE(MatchEnd); MUTATOR_HOOKABLE(GetTeamCount); float ret_float; MUTATOR_HOOKABLE(SpectateCopy); entity other; MUTATOR_HOOKABLE(ForbidThrowCurrentWeapon); MUTATOR_HOOKABLE(SetStartItems); MUTATOR_HOOKABLE(BuildMutatorsString); string ret_string; MUTATOR_HOOKABLE(BuildMutatorsPrettyString); string ret_string; MUTATOR_HOOKABLE(FilterItem); // return error to request removal, or change self.items or self.weapons MUTATOR_HOOKABLE(OnEntityPreSpawn); // return error to prevent entity spawn, or modify the entity MUTATOR_HOOKABLE(PlayerPreThink);