1 **Note:** The article is written as developer notes to ease developer tasks and save QuakeC function terms here. Some references are taken from `events.qh`.
4 # MUTATOR functions (from: `qcsrc/server/mutators/events.qh`)
8 How to use MUTATOR functions:
10 **Attention:** to use a hook, first register your mutator using `REGISTER_MUTATOR`, then create your function using `MUTATOR_HOOKFUNCTION`.
13 - **`REGISTER_MUTATOR`**
15 Registers a new `MUTATOR_HOOKFUNCTION`.
17 REGISTER_MUTATOR(new_mutator_name, some_variable);
21 - **`MUTATOR_HOOKFUNCTION`**
23 Creates a function and calls `new_mutator_name` (from `REGISTER_MUTATOR`) and one of `#define MUTATOR()` (from `qcsrc/server/mutators/events.qh` main hooks).
27 MUTATOR_HOOKFUNCTION(new_mutator_name_or_events.qh_main_hook, PlayerSpawn)
33 - **`MUTATOR_CALLHOOK`**
35 Calls some `MUTATOR_HOOKFUNCTION`.
37 MUTATOR_CALLHOOK(name_of_MUTATOR_HOOKFUNCTION_or_events.qh_main_hook);
40 There are different versions and depends how many variables need to be called in a `MUTATOR_HOOKFUNCTION`:
42 1 `MUTATOR_HOOKFUNCTION` and 1 variable:
45 MUTATOR_CALLHOOK(name_of_MUTATOR_HOOKFUNCTION_or_events.qh_main_hook, some_variable);
48 1 `MUTATOR_HOOKFUNCTION` and 2 variables:
51 MUTATOR_CALLHOOK(name_of_MUTATOR_HOOKFUNCTION_or_events.qh_main_hook, some_variable, some_variable);
54 1 `MUTATOR_HOOKFUNCTION` and 3 variables:
57 MUTATOR_CALLHOOK(name_of_MUTATOR_HOOKFUNCTION_or_events.qh_main_hook, some_variable, some_variable, some_variable);
60 1 `MUTATOR_HOOKFUNCTION` and multiple variables:
63 MUTATOR_CALLHOOK(name_of_MUTATOR_HOOKFUNCTION_or_events.qh_main_hook, some_variable, some_variable, some_variable, some_variable, ...);
70 ## List of MUTATOR functions
74 - **`MakePlayerObserver`**
76 Called when a player becomes observer, after shared setup.
78 #define EV_MakePlayerObserver(i, o) \
79 /** player */ i(entity, MUTATOR_ARGV_0_entity) \
81 MUTATOR_HOOKABLE(MakePlayerObserver, EV_MakePlayerObserver)
84 - **`PutClientInServer`**
86 Called when client spawns in server. (Not sure described)
88 #define EV_PutClientInServer(i, o) \
89 /** client wanting to spawn */ i(entity, MUTATOR_ARGV_0_entity) \
91 MUTATOR_HOOKABLE(PutClientInServer, EV_PutClientInServer);
96 Returns true to prevent a spectator/observer to spawn as player.
98 #define EV_ForbidSpawn(i, o) \
99 /** player */ i(entity, MUTATOR_ARGV_0_entity) \
101 MUTATOR_HOOKABLE(ForbidSpawn, EV_ForbidSpawn);
104 - **`AutoJoinOnConnection`**
106 Returns true if client should be put as player on connection.
108 #define EV_AutoJoinOnConnection(i, o) \
109 /** player */ i(entity, MUTATOR_ARGV_0_entity) \
111 MUTATOR_HOOKABLE(AutoJoinOnConnection, EV_AutoJoinOnConnection);
114 - **`ForbidRandomStartWeapons`**
116 Called when player spawns to determine whether to give them random start weapons. Return true to forbid giving them.
118 #define EV_ForbidRandomStartWeapons(i, o) \
119 /** player */ i(entity, MUTATOR_ARGV_0_entity) \
121 MUTATOR_HOOKABLE(ForbidRandomStartWeapons, EV_ForbidRandomStartWeapons);
126 Called when a player spawns as player, after shared setup, before his weapon is chosen (so items may be changed in here)
129 #define EV_PlayerSpawn(i, o) \
130 /** player spawning */ i(entity, MUTATOR_ARGV_0_entity) \
131 /** spot that was used, or NULL */ i(entity, MUTATOR_ARGV_1_entity) \
133 MUTATOR_HOOKABLE(PlayerSpawn, EV_PlayerSpawn);
136 - **`PlayerWeaponSelect`**
138 Called after a player's weapon is chosen so it can be overriden here.
140 #define EV_PlayerWeaponSelect(i, o) \
141 /** player spawning */ i(entity, MUTATOR_ARGV_0_entity) \
143 MUTATOR_HOOKABLE(PlayerWeaponSelect, EV_PlayerWeaponSelect);
146 - **`reset_map_global`**
150 #define EV_reset_map_global(i, o) \
152 MUTATOR_HOOKABLE(reset_map_global, EV_reset_map_global);
155 - **`reset_map_players`**
159 #define EV_reset_map_players(i, o) \
161 MUTATOR_HOOKABLE(reset_map_players, EV_reset_map_players);
164 - **`ForbidPlayerScore_Clear`**
166 Returns 1 if clearing player score shall not be allowed.
168 #define EV_ForbidPlayerScore_Clear(i, o) \
170 MUTATOR_HOOKABLE(ForbidPlayerScore_Clear, EV_ForbidPlayerScore_Clear);
173 - **`ClientDisconnect`**
175 Called when a player disconnects.
177 #define EV_ClientDisconnect(i, o) \
178 /** player */ i(entity, MUTATOR_ARGV_0_entity) \
180 MUTATOR_HOOKABLE(ClientDisconnect, EV_ClientDisconnect);
185 Called when a player dies to e.g. remove stuff he was carrying.
187 #define EV_PlayerDies(i, o) \
188 /** inflictor */ i(entity, MUTATOR_ARGV_0_entity) \
189 /** attacker */ i(entity, MUTATOR_ARGV_1_entity) \
190 /** target */ i(entity, MUTATOR_ARGV_2_entity) \
191 /** deathtype */ i(float, MUTATOR_ARGV_3_float) \
192 /** damage */ i(float, MUTATOR_ARGV_4_float) \
193 /** damage */ o(float, MUTATOR_ARGV_4_float) \
195 MUTATOR_HOOKABLE(PlayerDies, EV_PlayerDies);
200 Called after a player died.
202 #define EV_PlayerDied(i, o) \
203 /** player */ i(entity, MUTATOR_ARGV_0_entity) \
205 MUTATOR_HOOKABLE(PlayerDied, EV_PlayerDied);
208 - **`ClientObituary`**
210 Called when showing an obituary for the player. Returns true to show nothing (workarounds may be needed).
212 #define EV_ClientObituary(i, o) \
213 /** inflictor */ i(entity, MUTATOR_ARGV_0_entity) \
214 /** attacker */ i(entity, MUTATOR_ARGV_1_entity) \
215 /** target */ i(entity, MUTATOR_ARGV_2_entity) \
216 /** deathtype */ i(float, MUTATOR_ARGV_3_float) \
217 /** wep entity */ i(entity, MUTATOR_ARGV_4_entity) \
218 /** anonymous killer*/ o(bool, MUTATOR_ARGV_5_bool) \
220 MUTATOR_HOOKABLE(ClientObituary, EV_ClientObituary);
223 - **`FragCenterMessage`**
225 Allows overriding the frag centerprint messages.
227 #define EV_FragCenterMessage(i, o) \
228 /** attacker */ i(entity, MUTATOR_ARGV_0_entity) \
229 /** target */ i(entity, MUTATOR_ARGV_1_entity) \
230 /** deathtype */ i(float, MUTATOR_ARGV_2_float) \
231 /** attacker kcount*/ i(int, MUTATOR_ARGV_3_int) \
232 /** targ killcount */ i(int, MUTATOR_ARGV_4_int) \
234 MUTATOR_HOOKABLE(FragCenterMessage, EV_FragCenterMessage);
239 Called when a player dies to e.g. remove stuff he was carrying.
241 #define EV_PlayHitsound(i, o) \
242 /** victim */ i(entity, MUTATOR_ARGV_0_entity) \
243 /** attacker */ i(entity, MUTATOR_ARGV_1_entity) \
245 MUTATOR_HOOKABLE(PlayHitsound, EV_PlayHitsound);
250 Called when an item model is about to be set, allows custom paths etc.
252 #define EV_ItemModel(i, o) \
253 /** model */ i(string, MUTATOR_ARGV_0_string) \
254 /** output */ i(string, MUTATOR_ARGV_1_string) \
255 /**/ o(string, MUTATOR_ARGV_1_string) \
257 MUTATOR_HOOKABLE(ItemModel, EV_ItemModel);
262 Called when an item sound is about to be played, allows custom paths etc.
264 #define EV_ItemSound(i, o) \
265 /** sound */ i(string, MUTATOR_ARGV_0_string) \
266 /** output */ i(string, MUTATOR_ARGV_1_string) \
267 /**/ o(string, MUTATOR_ARGV_1_string) \
269 MUTATOR_HOOKABLE(ItemSound, EV_ItemSound);
272 - **`GiveFragsForKill`**
274 Called when someone was fragged by "self", and is expected to change frag_score to adjust scoring for the kill.
276 #define EV_GiveFragsForKill(i, o) \
277 /** attacker */ i(entity, MUTATOR_ARGV_0_entity) \
278 /** target */ i(entity, MUTATOR_ARGV_1_entity) \
279 /** frag score */ i(float, MUTATOR_ARGV_2_float) \
280 /** */ o(float, MUTATOR_ARGV_2_float) \
281 /** deathtype */ i(float, MUTATOR_ARGV_3_float) \
282 /** wep entity */ i(entity, MUTATOR_ARGV_4_entity) \
284 MUTATOR_HOOKABLE(GiveFragsForKill, EV_GiveFragsForKill);
289 Called when the match ends.
291 MUTATOR_HOOKABLE(MatchEnd, EV_NO_ARGS);
294 - **`TeamBalance_CheckAllowedTeams`**
296 Allows adjusting allowed teams. Return true to use the bitmask value and set non-empty string to use team entity name. Both behaviors can be active at the same time and will stack allowed teams.
298 #define EV_TeamBalance_CheckAllowedTeams(i, o) \
299 /** mask of teams */ i(float, MUTATOR_ARGV_0_float) \
300 /**/ o(float, MUTATOR_ARGV_0_float) \
301 /** team entity name */ i(string, MUTATOR_ARGV_1_string) \
302 /**/ o(string, MUTATOR_ARGV_1_string) \
303 /** player checked */ i(entity, MUTATOR_ARGV_2_entity) \
305 MUTATOR_HOOKABLE(TeamBalance_CheckAllowedTeams, EV_TeamBalance_CheckAllowedTeams);
308 - **`TeamBalance_GetTeamCounts`**
310 Returns true to manually override team counts.
312 MUTATOR_HOOKABLE(TeamBalance_GetTeamCounts, EV_NO_ARGS);
315 - **`TeamBalance_GetTeamCount`**
317 Allows overriding of team counts.
319 #define EV_TeamBalance_GetTeamCount(i, o) \
320 /** team index to count */ i(float, MUTATOR_ARGV_0_float) \
321 /** player to ignore */ i(entity, MUTATOR_ARGV_1_entity) \
322 /** number of players in a team */ o(float, MUTATOR_ARGV_2_float) \
323 /** number of bots in a team */ o(float, MUTATOR_ARGV_3_float) \
325 MUTATOR_HOOKABLE(TeamBalance_GetTeamCount, EV_TeamBalance_GetTeamCount);
328 - **`TeamBalance_FindBestTeams`**
330 Allows overriding the teams that will make the game most balanced if the player joins any of them.
332 #define EV_TeamBalance_FindBestTeams(i, o) \
333 /** player checked */ i(entity, MUTATOR_ARGV_0_entity) \
334 /** bitmask of teams */ o(float, MUTATOR_ARGV_1_float) \
336 MUTATOR_HOOKABLE(TeamBalance_FindBestTeams, EV_TeamBalance_FindBestTeams);
339 - **`TeamBalance_GetPlayerForTeamSwitch`**
341 Called during autobalance. Returns true to override the player that will be switched.
343 #define EV_TeamBalance_GetPlayerForTeamSwitch(i, o) \
344 /** source team index */ i(int, MUTATOR_ARGV_0_int) \
345 /** destination team index */ i(int, MUTATOR_ARGV_1_int) \
346 /** is looking for bot */ i(bool, MUTATOR_ARGV_2_bool) \
347 /** player to switch */ o(entity, MUTATOR_ARGV_3_entity) \
349 MUTATOR_HOOKABLE(TeamBalance_GetPlayerForTeamSwitch, EV_TeamBalance_GetPlayerForTeamSwitch);
354 Copies variables for spectating "spectatee" to "this".
356 #define EV_SpectateCopy(i, o) \
357 /** spectatee */ i(entity, MUTATOR_ARGV_0_entity) \
358 /** client */ i(entity, MUTATOR_ARGV_1_entity) \
360 MUTATOR_HOOKABLE(SpectateCopy, EV_SpectateCopy);
363 - **`FormatMessage`**
365 Called when formatting a chat message to replace fancy functions.
367 #define EV_FormatMessage(i, o) \
368 /** player */ i(entity, MUTATOR_ARGV_0_entity) \
369 /** escape */ i(string, MUTATOR_ARGV_1_string) \
370 /** replacement */ i(string, MUTATOR_ARGV_2_string) \
371 /**/ o(string, MUTATOR_ARGV_2_string) \
372 /** message */ i(string, MUTATOR_ARGV_3_string) \
374 MUTATOR_HOOKABLE(FormatMessage, EV_FormatMessage);
377 - **`PreFormatMessage`**
379 Called before any formatting is applied, handy for tweaking the message before scripts get ahold of it.
381 #define EV_PreFormatMessage(i, o) \
382 /** player */ i(entity, MUTATOR_ARGV_0_entity) \
383 /** message */ i(string, MUTATOR_ARGV_1_string) \
384 /**/ o(string, MUTATOR_ARGV_1_string) \
386 MUTATOR_HOOKABLE(PreFormatMessage, EV_PreFormatMessage);
389 - **`ForbidThrowCurrentWeapon`**
391 Returns true if throwing the current weapon shall not be allowed.
393 #define EV_ForbidThrowCurrentWeapon(i, o) \
394 /** player */ i(entity, MUTATOR_ARGV_0_entity) \
395 /** weapon entity */ i(entity, MUTATOR_ARGV_1_entity) \
397 MUTATOR_HOOKABLE(ForbidThrowCurrentWeapon, EV_ForbidThrowCurrentWeapon);
400 - **`ForbidDropCurrentWeapon`**
402 Returns true if dropping the current weapon shall not be allowed at any time including death */
404 #define EV_ForbidDropCurrentWeapon(i, o) \
405 /** player */ i(entity, MUTATOR_ARGV_0_entity) \
406 /** weapon id */ i(int, MUTATOR_ARGV_1_int) \
408 MUTATOR_HOOKABLE(ForbidDropCurrentWeapon, EV_ForbidDropCurrentWeapon);
411 - **`SetDefaultAlpha`**
413 Sets alpha value by default. (Not sure described)
415 MUTATOR_HOOKABLE(SetDefaultAlpha, EV_NO_ARGS);
427 - **`Damage_Calculate`**
429 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).
432 #define EV_Damage_Calculate(i, o) \
433 /** inflictor */ i(entity, MUTATOR_ARGV_0_entity) \
434 /** attacker */ i(entity, MUTATOR_ARGV_1_entity) \
435 /** target */ i(entity, MUTATOR_ARGV_2_entity) \
436 /** deathtype */ i(float, MUTATOR_ARGV_3_float) \
437 /** damage */ i(float, MUTATOR_ARGV_4_float) \
438 /** damage */ o(float, MUTATOR_ARGV_4_float) \
439 /** mirrordamage */ i(float, MUTATOR_ARGV_5_float) \
440 /** mirrordamage */ o(float, MUTATOR_ARGV_5_float) \
441 /** force */ i(vector, MUTATOR_ARGV_6_vector) \
442 /** force */ o(vector, MUTATOR_ARGV_6_vector) \
443 /** weapon entity */ i(entity, MUTATOR_ARGV_7_entity) \
445 MUTATOR_HOOKABLE(Damage_Calculate, EV_Damage_Calculate);
450 AND.... STILL in process