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
72 - **`MakePlayerObserver`**
74 Called when a player becomes observer, after shared setup.
76 #define EV_MakePlayerObserver(i, o) \
77 /** player */ i(entity, MUTATOR_ARGV_0_entity) \
79 MUTATOR_HOOKABLE(MakePlayerObserver, EV_MakePlayerObserver)
82 - **`PutClientInServer`**
84 Called when client spawns in server. (Not sure described)
86 #define EV_PutClientInServer(i, o) \
87 /** client wanting to spawn */ i(entity, MUTATOR_ARGV_0_entity) \
89 MUTATOR_HOOKABLE(PutClientInServer, EV_PutClientInServer);
94 Returns true to prevent a spectator/observer to spawn as player.
96 #define EV_ForbidSpawn(i, o) \
97 /** player */ i(entity, MUTATOR_ARGV_0_entity) \
99 MUTATOR_HOOKABLE(ForbidSpawn, EV_ForbidSpawn);
102 - **`AutoJoinOnConnection`**
104 Returns true if client should be put as player on connection.
106 #define EV_AutoJoinOnConnection(i, o) \
107 /** player */ i(entity, MUTATOR_ARGV_0_entity) \
109 MUTATOR_HOOKABLE(AutoJoinOnConnection, EV_AutoJoinOnConnection);
112 - **`ForbidRandomStartWeapons`**
114 Called when player spawns to determine whether to give them random start weapons. Return true to forbid giving them.
116 #define EV_ForbidRandomStartWeapons(i, o) \
117 /** player */ i(entity, MUTATOR_ARGV_0_entity) \
119 MUTATOR_HOOKABLE(ForbidRandomStartWeapons, EV_ForbidRandomStartWeapons);
124 Called when a player spawns as player, after shared setup, before his weapon is chosen (so items may be changed in here)
127 #define EV_PlayerSpawn(i, o) \
128 /** player spawning */ i(entity, MUTATOR_ARGV_0_entity) \
129 /** spot that was used, or NULL */ i(entity, MUTATOR_ARGV_1_entity) \
131 MUTATOR_HOOKABLE(PlayerSpawn, EV_PlayerSpawn);
134 - **`PlayerWeaponSelect`**
136 Called after a player's weapon is chosen so it can be overriden here.
138 #define EV_PlayerWeaponSelect(i, o) \
139 /** player spawning */ i(entity, MUTATOR_ARGV_0_entity) \
141 MUTATOR_HOOKABLE(PlayerWeaponSelect, EV_PlayerWeaponSelect);
144 - **`reset_map_global`**
148 #define EV_reset_map_global(i, o) \
150 MUTATOR_HOOKABLE(reset_map_global, EV_reset_map_global);
153 - **`reset_map_players`**
157 #define EV_reset_map_players(i, o) \
159 MUTATOR_HOOKABLE(reset_map_players, EV_reset_map_players);
162 - **`ForbidPlayerScore_Clear`**
164 Returns 1 if clearing player score shall not be allowed.
166 #define EV_ForbidPlayerScore_Clear(i, o) \
168 MUTATOR_HOOKABLE(ForbidPlayerScore_Clear, EV_ForbidPlayerScore_Clear);
171 - **`ClientDisconnect`**
173 Called when a player disconnects.
175 #define EV_ClientDisconnect(i, o) \
176 /** player */ i(entity, MUTATOR_ARGV_0_entity) \
178 MUTATOR_HOOKABLE(ClientDisconnect, EV_ClientDisconnect);
183 Called when a player dies to e.g. remove stuff he was carrying.
185 #define EV_PlayerDies(i, o) \
186 /** inflictor */ i(entity, MUTATOR_ARGV_0_entity) \
187 /** attacker */ i(entity, MUTATOR_ARGV_1_entity) \
188 /** target */ i(entity, MUTATOR_ARGV_2_entity) \
189 /** deathtype */ i(float, MUTATOR_ARGV_3_float) \
190 /** damage */ i(float, MUTATOR_ARGV_4_float) \
191 /** damage */ o(float, MUTATOR_ARGV_4_float) \
193 MUTATOR_HOOKABLE(PlayerDies, EV_PlayerDies);
198 Called after a player died.
200 #define EV_PlayerDied(i, o) \
201 /** player */ i(entity, MUTATOR_ARGV_0_entity) \
203 MUTATOR_HOOKABLE(PlayerDied, EV_PlayerDied);
206 - **`ClientObituary`**
208 Called when showing an obituary for the player. Returns true to show nothing (workarounds may be needed).
210 #define EV_ClientObituary(i, o) \
211 /** inflictor */ i(entity, MUTATOR_ARGV_0_entity) \
212 /** attacker */ i(entity, MUTATOR_ARGV_1_entity) \
213 /** target */ i(entity, MUTATOR_ARGV_2_entity) \
214 /** deathtype */ i(float, MUTATOR_ARGV_3_float) \
215 /** wep entity */ i(entity, MUTATOR_ARGV_4_entity) \
216 /** anonymous killer*/ o(bool, MUTATOR_ARGV_5_bool) \
218 MUTATOR_HOOKABLE(ClientObituary, EV_ClientObituary);
221 - **`FragCenterMessage`**
223 Allows overriding the frag centerprint messages.
225 #define EV_FragCenterMessage(i, o) \
226 /** attacker */ i(entity, MUTATOR_ARGV_0_entity) \
227 /** target */ i(entity, MUTATOR_ARGV_1_entity) \
228 /** deathtype */ i(float, MUTATOR_ARGV_2_float) \
229 /** attacker kcount*/ i(int, MUTATOR_ARGV_3_int) \
230 /** targ killcount */ i(int, MUTATOR_ARGV_4_int) \
232 MUTATOR_HOOKABLE(FragCenterMessage, EV_FragCenterMessage);
237 Called when a player dies to e.g. remove stuff he was carrying.
239 #define EV_PlayHitsound(i, o) \
240 /** victim */ i(entity, MUTATOR_ARGV_0_entity) \
241 /** attacker */ i(entity, MUTATOR_ARGV_1_entity) \
243 MUTATOR_HOOKABLE(PlayHitsound, EV_PlayHitsound);
248 Called when an item model is about to be set, allows custom paths etc.
250 #define EV_ItemModel(i, o) \
251 /** model */ i(string, MUTATOR_ARGV_0_string) \
252 /** output */ i(string, MUTATOR_ARGV_1_string) \
253 /**/ o(string, MUTATOR_ARGV_1_string) \
255 MUTATOR_HOOKABLE(ItemModel, EV_ItemModel);
260 Called when an item sound is about to be played, allows custom paths etc.
262 #define EV_ItemSound(i, o) \
263 /** sound */ i(string, MUTATOR_ARGV_0_string) \
264 /** output */ i(string, MUTATOR_ARGV_1_string) \
265 /**/ o(string, MUTATOR_ARGV_1_string) \
267 MUTATOR_HOOKABLE(ItemSound, EV_ItemSound);
270 - **`GiveFragsForKill`**
272 Called when someone was fragged by "self", and is expected to change frag_score to adjust scoring for the kill.
274 #define EV_GiveFragsForKill(i, o) \
275 /** attacker */ i(entity, MUTATOR_ARGV_0_entity) \
276 /** target */ i(entity, MUTATOR_ARGV_1_entity) \
277 /** frag score */ i(float, MUTATOR_ARGV_2_float) \
278 /** */ o(float, MUTATOR_ARGV_2_float) \
279 /** deathtype */ i(float, MUTATOR_ARGV_3_float) \
280 /** wep entity */ i(entity, MUTATOR_ARGV_4_entity) \
282 MUTATOR_HOOKABLE(GiveFragsForKill, EV_GiveFragsForKill);
287 Called when the match ends.
289 MUTATOR_HOOKABLE(MatchEnd, EV_NO_ARGS);
292 - **`TeamBalance_CheckAllowedTeams`**
294 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.
296 #define EV_TeamBalance_CheckAllowedTeams(i, o) \
297 /** mask of teams */ i(float, MUTATOR_ARGV_0_float) \
298 /**/ o(float, MUTATOR_ARGV_0_float) \
299 /** team entity name */ i(string, MUTATOR_ARGV_1_string) \
300 /**/ o(string, MUTATOR_ARGV_1_string) \
301 /** player checked */ i(entity, MUTATOR_ARGV_2_entity) \
303 MUTATOR_HOOKABLE(TeamBalance_CheckAllowedTeams, EV_TeamBalance_CheckAllowedTeams);
311 - **`Damage_Calculate`**
313 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).
316 #define EV_Damage_Calculate(i, o) \
317 /** inflictor */ i(entity, MUTATOR_ARGV_0_entity) \
318 /** attacker */ i(entity, MUTATOR_ARGV_1_entity) \
319 /** target */ i(entity, MUTATOR_ARGV_2_entity) \
320 /** deathtype */ i(float, MUTATOR_ARGV_3_float) \
321 /** damage */ i(float, MUTATOR_ARGV_4_float) \
322 /** damage */ o(float, MUTATOR_ARGV_4_float) \
323 /** mirrordamage */ i(float, MUTATOR_ARGV_5_float) \
324 /** mirrordamage */ o(float, MUTATOR_ARGV_5_float) \
325 /** force */ i(vector, MUTATOR_ARGV_6_vector) \
326 /** force */ o(vector, MUTATOR_ARGV_6_vector) \
327 /** weapon entity */ i(entity, MUTATOR_ARGV_7_entity) \
329 MUTATOR_HOOKABLE(Damage_Calculate, EV_Damage_Calculate);
334 AND.... STILL in process