]> git.xonotic.org Git - xonotic/xonotic.wiki.git/blob - Functions-and-other-programming-QuakeC-things-in-Xonotic.md
Added more MUTATOR functions
[xonotic/xonotic.wiki.git] / Functions-and-other-programming-QuakeC-things-in-Xonotic.md
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`.
2
3
4 # MUTATOR functions (from: `qcsrc/server/mutators/events.qh`)
5
6 ### Introduction
7
8 How to use MUTATOR functions:
9
10 **Attention:** to use a hook, first register your mutator using `REGISTER_MUTATOR`, then create your function using `MUTATOR_HOOKFUNCTION`.
11
12
13 - **`REGISTER_MUTATOR`**
14
15 Registers a new `MUTATOR_HOOKFUNCTION`.
16 ```c
17 REGISTER_MUTATOR(new_mutator_name, some_variable);
18 ```
19
20
21 - **`MUTATOR_HOOKFUNCTION`**
22
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).
24
25 Example:
26 ```c
27 MUTATOR_HOOKFUNCTION(new_mutator_name_or_events.qh_main_hook, PlayerSpawn)
28 {
29     // whatever does
30 }
31 ```
32
33 - **`MUTATOR_CALLHOOK`**
34
35 Calls some `MUTATOR_HOOKFUNCTION`.
36 ```c
37 MUTATOR_CALLHOOK(name_of_MUTATOR_HOOKFUNCTION_or_events.qh_main_hook);
38 ```
39
40 There are different versions and depends how many variables need to be called in a `MUTATOR_HOOKFUNCTION`:
41
42 1 `MUTATOR_HOOKFUNCTION` and 1 variable:
43
44 ```c
45 MUTATOR_CALLHOOK(name_of_MUTATOR_HOOKFUNCTION_or_events.qh_main_hook, some_variable);
46 ```
47
48 1 `MUTATOR_HOOKFUNCTION` and 2 variables:
49
50 ```c
51 MUTATOR_CALLHOOK(name_of_MUTATOR_HOOKFUNCTION_or_events.qh_main_hook, some_variable, some_variable);
52 ```
53
54 1 `MUTATOR_HOOKFUNCTION` and 3 variables:
55
56 ```c
57 MUTATOR_CALLHOOK(name_of_MUTATOR_HOOKFUNCTION_or_events.qh_main_hook, some_variable, some_variable, some_variable);
58 ```
59
60 1 `MUTATOR_HOOKFUNCTION` and multiple variables:
61
62 ```c
63 MUTATOR_CALLHOOK(name_of_MUTATOR_HOOKFUNCTION_or_events.qh_main_hook, some_variable, some_variable, some_variable, some_variable, ...);
64 ```
65
66 <br />
67 <br />
68
69
70 ## List of MUTATOR functions
71
72 **Warning:** 
73
74 - **`MakePlayerObserver`**
75
76 Called when a player becomes observer, after shared setup.
77 ```c
78 #define EV_MakePlayerObserver(i, o) \
79     /** player */ i(entity, MUTATOR_ARGV_0_entity) \
80     /**/
81 MUTATOR_HOOKABLE(MakePlayerObserver, EV_MakePlayerObserver)
82 ```
83
84 - **`PutClientInServer`**
85
86 Called when client spawns in server. (Not sure described)
87 ```c
88 #define EV_PutClientInServer(i, o) \
89         /** client wanting to spawn */ i(entity, MUTATOR_ARGV_0_entity) \
90     /**/
91 MUTATOR_HOOKABLE(PutClientInServer, EV_PutClientInServer);
92 ```
93
94 - **`ForbidSpawn`**
95
96 Returns true to prevent a spectator/observer to spawn as player.
97 ```c
98  #define EV_ForbidSpawn(i, o) \
99     /** player */ i(entity, MUTATOR_ARGV_0_entity) \
100     /**/
101 MUTATOR_HOOKABLE(ForbidSpawn, EV_ForbidSpawn);
102 ```
103
104 - **`AutoJoinOnConnection`**
105
106 Returns true if client should be put as player on connection.
107 ```c
108 #define EV_AutoJoinOnConnection(i, o) \
109     /** player */ i(entity, MUTATOR_ARGV_0_entity) \
110     /**/
111 MUTATOR_HOOKABLE(AutoJoinOnConnection, EV_AutoJoinOnConnection);
112 ```
113
114 - **`ForbidRandomStartWeapons`**
115
116 Called when player spawns to determine whether to give them random start weapons. Return true to forbid giving them.
117 ```c
118 #define EV_ForbidRandomStartWeapons(i, o) \
119         /** player */ i(entity, MUTATOR_ARGV_0_entity) \
120     /**/
121 MUTATOR_HOOKABLE(ForbidRandomStartWeapons, EV_ForbidRandomStartWeapons);
122 ```
123
124 - **`PlayerSpawn`**
125
126 Called when a player spawns as player, after shared setup, before his weapon is chosen (so items may be changed in here)
127
128 ```c
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) \
132     /**/
133 MUTATOR_HOOKABLE(PlayerSpawn, EV_PlayerSpawn);
134 ```
135
136 - **`PlayerWeaponSelect`**
137
138 Called after a player's weapon is chosen so it can be overriden here.
139 ```c
140 #define EV_PlayerWeaponSelect(i, o) \
141         /** player spawning */ i(entity, MUTATOR_ARGV_0_entity) \
142     /**/
143 MUTATOR_HOOKABLE(PlayerWeaponSelect, EV_PlayerWeaponSelect);
144 ```
145
146 - **`reset_map_global`**
147
148 Called in reset_map.
149 ```c
150 #define EV_reset_map_global(i, o) \
151     /**/
152 MUTATOR_HOOKABLE(reset_map_global, EV_reset_map_global);
153 ```
154
155 - **`reset_map_players`**
156
157 Called in reset_map.
158 ```c
159 #define EV_reset_map_players(i, o) \
160     /**/
161 MUTATOR_HOOKABLE(reset_map_players, EV_reset_map_players);
162 ```
163
164 - **`ForbidPlayerScore_Clear`**
165
166 Returns 1 if clearing player score shall not be allowed.
167 ```c
168 #define EV_ForbidPlayerScore_Clear(i, o) \
169     /**/
170 MUTATOR_HOOKABLE(ForbidPlayerScore_Clear, EV_ForbidPlayerScore_Clear);
171 ```
172
173 - **`ClientDisconnect`**
174
175 Called when a player disconnects.
176 ```c
177 #define EV_ClientDisconnect(i, o) \
178     /** player */ i(entity, MUTATOR_ARGV_0_entity) \
179     /**/
180 MUTATOR_HOOKABLE(ClientDisconnect, EV_ClientDisconnect);
181 ```
182
183 - **`PlayerDies`**
184
185 Called when a player dies to e.g. remove stuff he was carrying.
186 ```c
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) \
194     /**/
195 MUTATOR_HOOKABLE(PlayerDies, EV_PlayerDies);
196 ```
197
198 - **`PlayerDied`**
199
200 Called after a player died.
201 ```c
202 #define EV_PlayerDied(i, o) \
203     /** player                  */ i(entity, MUTATOR_ARGV_0_entity) \
204     /**/
205 MUTATOR_HOOKABLE(PlayerDied, EV_PlayerDied);
206 ```
207
208 - **`ClientObituary`**
209
210 Called when showing an obituary for the player. Returns true to show nothing (workarounds may be needed).
211 ```c
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) \
219     /**/
220 MUTATOR_HOOKABLE(ClientObituary, EV_ClientObituary);
221 ```
222
223 - **`FragCenterMessage`**
224
225 Allows overriding the frag centerprint messages.
226 ```c
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) \
233     /**/
234 MUTATOR_HOOKABLE(FragCenterMessage, EV_FragCenterMessage);
235 ```
236
237 - **`PlayHitsound`**
238
239 Called when a player dies to e.g. remove stuff he was carrying.
240 ```c
241 #define EV_PlayHitsound(i, o) \
242     /** victim */ i(entity, MUTATOR_ARGV_0_entity) \
243     /** attacker */ i(entity, MUTATOR_ARGV_1_entity) \
244     /**/
245 MUTATOR_HOOKABLE(PlayHitsound, EV_PlayHitsound);
246 ```
247
248 - **`ItemModel`**
249
250 Called when an item model is about to be set, allows custom paths etc.
251 ```c
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) \
256     /**/
257 MUTATOR_HOOKABLE(ItemModel, EV_ItemModel);
258 ```
259
260 - **`ItemSound`**
261
262 Called when an item sound is about to be played, allows custom paths etc.
263 ```c
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) \
268     /**/
269 MUTATOR_HOOKABLE(ItemSound, EV_ItemSound);
270 ```
271
272 - **`GiveFragsForKill`**
273
274 Called when someone was fragged by "self", and is expected to change frag_score to adjust scoring for the kill.
275 ```c
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) \
283     /**/
284 MUTATOR_HOOKABLE(GiveFragsForKill, EV_GiveFragsForKill);
285 ```
286
287 - **`MatchEnd`**
288
289 Called when the match ends.
290 ```c
291 MUTATOR_HOOKABLE(MatchEnd, EV_NO_ARGS);
292 ```
293
294 - **`TeamBalance_CheckAllowedTeams`**
295
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.
297 ```c
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) \
304     /**/
305 MUTATOR_HOOKABLE(TeamBalance_CheckAllowedTeams, EV_TeamBalance_CheckAllowedTeams);
306 ```
307
308 - **`TeamBalance_GetTeamCounts`**
309
310 Returns true to manually override team counts.
311 ```c
312 MUTATOR_HOOKABLE(TeamBalance_GetTeamCounts, EV_NO_ARGS);
313 ```
314
315 - **`TeamBalance_GetTeamCount`**
316
317 Allows overriding of team counts.
318 ```c
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) \
324     /**/
325 MUTATOR_HOOKABLE(TeamBalance_GetTeamCount, EV_TeamBalance_GetTeamCount);
326 ```
327
328 - **`TeamBalance_FindBestTeams`**
329
330 Allows overriding the teams that will make the game most balanced if the player joins any of them.
331 ```c
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) \
335     /**/
336 MUTATOR_HOOKABLE(TeamBalance_FindBestTeams, EV_TeamBalance_FindBestTeams);
337 ```
338
339 - **`TeamBalance_GetPlayerForTeamSwitch`**
340
341 Called during autobalance. Returns true to override the player that will be switched.
342 ```c
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) \
348     /**/
349 MUTATOR_HOOKABLE(TeamBalance_GetPlayerForTeamSwitch, EV_TeamBalance_GetPlayerForTeamSwitch);
350 ```
351
352 - **`SpectateCopy`**
353
354 Copies variables for spectating "spectatee" to "this".
355 ```c
356 #define EV_SpectateCopy(i, o) \
357     /** spectatee   */ i(entity, MUTATOR_ARGV_0_entity) \
358     /** client      */ i(entity, MUTATOR_ARGV_1_entity) \
359     /**/
360 MUTATOR_HOOKABLE(SpectateCopy, EV_SpectateCopy);
361 ```
362
363 - **`FormatMessage`**
364
365 Called when formatting a chat message to replace fancy functions.
366 ```c
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) \
373     /**/
374 MUTATOR_HOOKABLE(FormatMessage, EV_FormatMessage);
375 ```
376
377 - **`PreFormatMessage`**
378
379 Called before any formatting is applied, handy for tweaking the message before scripts get ahold of it.
380 ```c
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) \
385     /**/
386 MUTATOR_HOOKABLE(PreFormatMessage, EV_PreFormatMessage);
387 ```
388
389 - **`ForbidThrowCurrentWeapon`**
390
391 Returns true if throwing the current weapon shall not be allowed.
392 ```c
393 #define EV_ForbidThrowCurrentWeapon(i, o) \
394     /** player        */ i(entity, MUTATOR_ARGV_0_entity) \
395     /** weapon entity */ i(entity, MUTATOR_ARGV_1_entity) \
396     /**/
397 MUTATOR_HOOKABLE(ForbidThrowCurrentWeapon, EV_ForbidThrowCurrentWeapon);
398 ```
399
400 - **`ForbidDropCurrentWeapon`**
401
402 Returns true if dropping the current weapon shall not be allowed at any time including death */
403 ```c
404 #define EV_ForbidDropCurrentWeapon(i, o) \
405     /** player */        i(entity, MUTATOR_ARGV_0_entity) \
406     /** weapon id */     i(int, MUTATOR_ARGV_1_int) \
407     /**/
408 MUTATOR_HOOKABLE(ForbidDropCurrentWeapon, EV_ForbidDropCurrentWeapon);
409 ```
410
411 - **`SetDefaultAlpha`**
412
413 Sets alpha value by default. (Not sure described)
414 ```c
415 MUTATOR_HOOKABLE(SetDefaultAlpha, EV_NO_ARGS);
416 ```
417
418
419
420
421
422
423 <br />
424 <br />
425
426
427 - **`Damage_Calculate`**
428
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).
430
431 ```c
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) \
444     /**/
445 MUTATOR_HOOKABLE(Damage_Calculate, EV_Damage_Calculate);
446 ```
447 <br />
448 <br />
449
450 AND.... STILL in process