47 this.cbc_order = order;
72 node.cbc_next = this.cbc_next;
76 while (it) {
prev = it, it = it.cbc_next; }
78 else this.cbc_next = node;
85 else this.cbc_next = node;
98 else this.cbc_next =
next;
110 for (
Callback it = this.cbc_next; it; it = it.cbc_next) {
112 r |= it.cbc.cbc_func();
118#define _MUTATOR_HANDLE_NOP(type, id)
119#define _MUTATOR_HANDLE_PARAMS(type, id) , type in_##id
120#define _MUTATOR_HANDLE_PREPARE(type, id) id = in_##id;
121#define _MUTATOR_HANDLE_PUSHTMP(type, id) TC(type, id); type tmp_##id = id;
122#define _MUTATOR_HANDLE_PUSHOUT(type, id) type out_##id = id;
123#define _MUTATOR_HANDLE_POPTMP(type, id) id = tmp_##id;
124#define _MUTATOR_HANDLE_POPOUT(type, id) id = out_##id;
129#define MUTATOR_HOOKABLE(id, params) _MUTATOR_HOOKABLE(id, params)
130#define _MUTATOR_HOOKABLE(id, params) \
131 CallbackChain HOOK_##id; \
132 bool __Mutator_Send_##id(int params(_MUTATOR_HANDLE_PARAMS, _MUTATOR_HANDLE_NOP)) { \
133 params(_MUTATOR_HANDLE_PUSHTMP, _MUTATOR_HANDLE_NOP) \
134 params(_MUTATOR_HANDLE_PREPARE, _MUTATOR_HANDLE_NOP) \
135 bool ret = CallbackChain_Call(HOOK_##id); \
136 params(_MUTATOR_HANDLE_NOP, _MUTATOR_HANDLE_PUSHOUT) \
137 params(_MUTATOR_HANDLE_POPTMP, _MUTATOR_HANDLE_NOP) \
138 params(_MUTATOR_HANDLE_NOP, _MUTATOR_HANDLE_POPOUT) \
141 ACCUMULATE void RegisterHooks() { HOOK_##id = NEW(CallbackChain, #id); }
143#define MUTATOR_CALLHOOK(id, ...) _MUTATOR_CALLHOOK(id, __VA_ARGS__)
145 #define _MUTATOR_CALLHOOK(id, ...) APPLY(__Mutator_Send_##id, 0 P99_IF_EMPTY(__VA_ARGS__)()(, __VA_ARGS__))
147 #define _MUTATOR_CALLHOOK(id, ...) APPLY(__Mutator_Send_##id, 0, ##__VA_ARGS__)
179 returns(this.message, icon_path_from_menuskin(this.m_icon));
192#define _MUTATOR_IS_ENABLED(this) this.mutatorcheck()
193#define MUTATOR_IS_ENABLED(this) _MUTATOR_IS_ENABLED(MUTATOR_##this)
228 FOREACH(Mutators, it.registered_id == s, { Mutator_Add(it); ++added; });
230 if (added > 1)
LOG_WARNF(
"Added more than one mutator for %s", s);
252 backtrace(
"WARNING: when adding mutator: adding failed, rolling back\n");
255 error(
"WARNING: when adding mutator: rolling back failed");
264 backtrace(
"WARNING: removing not-added mutator\n");
272 error(
"Mutator_Remove: removing mutator failed");
280#define _REGISTER_MUTATOR(id, dependence, cname) \
281 bool MUTATORFUNC_##id##_hooks(int mode) { return = false; } \
282 bool MUTATORFUNC_##id(int mode) { \
284 bool ret = MUTATORFUNC_##id##_hooks(mode); if (ret) return ret; \
286 bool MUTATOR_##id##_check() { return dependence; } \
287 REGISTER(Mutators, MUTATOR, id, m_id, NEW(cname)) \
290 this.mutatorfunc = MUTATORFUNC_##id; \
291 this.mutatorcheck = MUTATOR_##id##_check; \
293 ACCUMULATE bool MUTATORFUNC_##id(int mode)
295#define REGISTER_MUTATOR(...) EVAL(OVERLOAD(REGISTER_MUTATOR, __VA_ARGS__))
296#define REGISTER_MUTATOR_2(id, dependence) _REGISTER_MUTATOR(id, dependence, Mutator)
297#define REGISTER_MUTATOR_3(id, dependence, cname) _REGISTER_MUTATOR(id, dependence, cname)
309#define MUTATOR_ONADD if (mode == MUTATOR_ADDING)
310#define MUTATOR_ONREMOVE if (mode == MUTATOR_REMOVING)
311#define MUTATOR_ONROLLBACK_OR_REMOVE if (mode == MUTATOR_REMOVING || mode == MUTATOR_ROLLING_BACK)
313#define MUTATOR_STATIC() MACRO_BEGIN \
317 error("This is a gametype and it cannot be added at runtime."); \
321 LOG_INFO("This is a gametype and it cannot be removed at runtime."); \
326#define MUTATOR_ADD(name) Mutator_Add(MUTATOR_##name)
327#define MUTATOR_REMOVE(name) Mutator_Remove(MUTATOR_##name)
328#define MUTATOR_RETURNVALUE CallbackChain_ReturnValue
330#define _MUTATOR_CALLBACK(name, func) \
331 Callback CB_##name; \
333 ACCUMULATE void RegisterCallbacks() { CB_##name = NEW(Callback, func); }
335#define MUTATOR_HOOKFUNCTION(...) \
336 EVAL_MUTATOR_HOOKFUNCTION(OVERLOAD(MUTATOR_HOOKFUNCTION, __VA_ARGS__))
337#define EVAL_MUTATOR_HOOKFUNCTION(...) __VA_ARGS__
339#define MUTATOR_HOOKFUNCTION_2(mut, cb) \
340 MUTATOR_HOOKFUNCTION_3(mut, cb, CBC_ORDER_ANY)
342#define MUTATOR_HOOKFUNCTION_3(mut, cb, order) \
343 _MUTATOR_CALLBACK(mut##_##cb, mut##_##cb) \
344 ACCUMULATE bool MUTATORFUNC_##mut##_hooks(int mode) { MUTATOR_HOOK(cb, mut##_##cb, order); } \
345 bool mut##_##cb() { return = false; } \
346 ACCUMULATE bool mut##_##cb()
351 LOG_INFO(
"HOOK FAILED: ", cb,
":", func);
354#define MUTATOR_HOOK(cb, func, order) MACRO_BEGIN \
356 if (!CallbackChain_Add(HOOK_##cb, CB_##func, order)) { \
357 _mutPrintFail(#cb, #func); \
361 MUTATOR_ONROLLBACK_OR_REMOVE { \
362 CallbackChain_Remove(HOOK_##cb, CB_##func); \
void Mutator_Remove(Mutator mut)
const int CBC_ORDER_FIRST
bool Mutator_SendEntity(entity this, entity to, int sf)
server mutators activate corresponding client mutators for all clients
#define _MUTATOR_IS_ENABLED(this)
const int CBC_ORDER_EXCLUSIVE
void _mutPrintFail(string cb, string func)
void NET_Mutator_Remove(entity this)
bool CallbackChain_ReturnValue
bool Mutator_Add(Mutator mut)
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
CallbackNode::CallbackNode(Callback it, int order)
ATTRIB(CallbackNode, cbc, Callback)
Callback chains contain zero or more callbacks.
bool CallbackChain_Call(CallbackChain this)
bool CallbackChain_Add(CallbackChain this, Callback cb, int order)
int CallbackChain_Remove(CallbackChain this, Callback cb)
ATTRIB(CallbackChain, cbc_next, CallbackNode)
CallbackChain(string _name)
Callbacks may be added to zero or more callback chains.
ATTRIB(Callback, cbc_func, bool())
a callback function is like this: bool mycallback() { do something return false; }
ATTRIB(Mutator, message, string)
#define FOREACH(list, cond, body)
#define NET_HANDLE(id, param)
void Net_UnlinkEntity(entity e)
#define WriteHeader(to, id)
#define REGISTER_NET_LINKED(id)
void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
#define WITH(type, name, value, block)
#define make_pure(e)
direct use is
#define METHOD(cname, name, prototype)
#define CONSTRUCTOR(cname,...)
#define CONSTRUCT(cname,...)
string registered_id
registered item identifier
#define REGISTRY(id, max)
Declare a new registry.
#define REGISTRY_DEFINE_GET(id, null)
#define STATIC_INIT_LATE(func)
directly after STATIC_INIT
#define STATIC_INIT(func)
during worldspawn