]> git.xonotic.org Git - xonotic/xonotic.wiki.git/blob - Programming-QuakeC-stuff-in-Xonotic.md
Upload attachment scoreboardCountryflag.jpg
[xonotic/xonotic.wiki.git] / Programming-QuakeC-stuff-in-Xonotic.md
1 **Note:** The article is written as developer notes to ease developer tasks and save QuakeC terms here.
2
3 > ## Table of Contents
4 > 1. [CSQC, MENUQC, SVQC and GAMEQC blocks](#csqc-menuqc-svqc-and-gameqc-blocks)
5 > 2. [MUTATOR functions](#mutator-functions)
6 >
7 > 2.1. [How to use MUTATOR functions](#how-to-use-mutator-functions)
8 >
9 > 2.2. [List of MUTATOR functions](#list-of-mutator-functions)
10 >
11 > 3. [Weapon functions](#weapon-functions)
12 >
13 > 3.1. [A bit of introduction](#a-bit-of-introduction)
14 >
15 > 3.2. [List of weapon functions](#list-of-weapon-functions)
16 >
17 > 4. [HUD, Menu and Draw functions](#hud-menu-and-draw-functions)
18 >
19 > 5. [Gamemodes](#gamemodes)
20 >
21 > 5.1. [Samples](#samples)
22 >
23 > 6. [Effects](#effects)
24
25 # CSQC, MENUQC, SVQC and GAMEQC blocks
26
27 Xonotic uses the ***csprogs.dat*** from the server you're playing on, as it must match the server's ***progs.dat*** code (whereas your ***menu.dat*** is always your local copy).
28
29 Menu and HUD code are actually separated as they run in 2 distinct programs: ***csprogs.dat*** and ***menu.dat***
30
31 Server program is ***progs.dat***
32
33 - Code inside a **`#ifdef CSQC`** block is part of the client code and will be compiled to **csprogs.dat**
34
35 - Code inside a **`#ifdef MENUQC`** block is part of the menu code and will be compiled to **menu.dat**
36
37 - Code inside a **`#ifdef SVQC`** block is part of the menu code and will be compiled to **progs.dat**
38
39 - Also, code inside a **`#ifdef GAMEQC`** block is part of both client (not menu) and server code.
40
41 ### A bit of explanation about the use of each type of cvars
42
43 - **g_*** cvars:
44
45 Example: `g_balance_grapplehook_speed_fly` is clearly a server or game cvar (**g_*** cvars are server and game cvars), so you CAN'T declare it within a `#ifdef CSQC` block. This type of cvar only can be declared inside a **`#ifdef SVQC`** or **`#ifdef GAMEQC`** block (if possible).
46
47 - **sv_*** cvars:
48
49 Example: `sv_campcheck` is clearly a server cvar (**sv_*** cvars are server cvars), only can be declared inside a **`#ifdef SVQC`** block.
50
51 - **cl_*** cvars:
52
53 Example: `cl_chatsound` is clearly a client cvar (**cl_*** cvars are client cvars), only can be declared inside a **`#ifdef CSQC`** block.
54
55 - **hud_*** cvars:
56
57 Example: `hud_progressbar_alpha` is a client cvar (**hud_*** cvars belong to client cvars), only can be declared inside a **`#ifdef CSQC`** block.
58
59
60 <br />
61
62 # MUTATOR functions
63
64 ### How to use MUTATOR functions
65
66 You can look the following link if you're trying/testing your own mutator: [Writing your first mutator](writing-your-first-mutator)
67
68 **Attention:** to use a hook, first register your mutator using `REGISTER_MUTATOR`, then create your function using `MUTATOR_HOOKFUNCTION`.
69
70
71 - **`REGISTER_MUTATOR`**
72
73 Registers a new `MUTATOR_HOOKFUNCTION`.
74 ```c
75 REGISTER_MUTATOR(new_mutator_name, some_variable);
76 ```
77
78
79 - **`MUTATOR_HOOKFUNCTION`**
80
81 Creates a function and calls `new_mutator_name` (from `REGISTER_MUTATOR`) and one of `#define MUTATOR()` (from `qcsrc/server/mutators/events.qh` main hooks).
82
83 Example:
84 ```c
85 MUTATOR_HOOKFUNCTION(new_mutator_name, events.qh_main_hook)
86 {
87     // whatever does
88 }
89 ```
90
91 - **`MUTATOR_CALLHOOK`**
92
93 Calls some `MUTATOR_HOOKFUNCTION`.
94 ```c
95 MUTATOR_CALLHOOK(name_of_MUTATOR_HOOKFUNCTION_or_events.qh_main_hook);
96 ```
97
98 There are different versions and depends how many variables need to be called in a `MUTATOR_HOOKFUNCTION`:
99
100 1 `MUTATOR_HOOKFUNCTION` and 1 variable:
101
102 ```c
103 MUTATOR_CALLHOOK(name_of_MUTATOR_HOOKFUNCTION_or_events.qh_main_hook, some_variable);
104 ```
105
106 1 `MUTATOR_HOOKFUNCTION` and 2 variables:
107
108 ```c
109 MUTATOR_CALLHOOK(name_of_MUTATOR_HOOKFUNCTION_or_events.qh_main_hook, some_variable, some_variable);
110 ```
111
112 1 `MUTATOR_HOOKFUNCTION` and 3 variables:
113
114 ```c
115 MUTATOR_CALLHOOK(name_of_MUTATOR_HOOKFUNCTION_or_events.qh_main_hook, some_variable, some_variable, some_variable);
116 ```
117
118 1 `MUTATOR_HOOKFUNCTION` and multiple variables:
119
120 ```c
121 MUTATOR_CALLHOOK(name_of_MUTATOR_HOOKFUNCTION_or_events.qh_main_hook, some_variable, some_variable, some_variable, some_variable, ...);
122 ```
123
124 <br />
125
126 ## List of MUTATOR functions
127
128 You can look the MUTATOR functions in:
129
130 - **COMMON:** [`qcsrc/common/mutators/events.qh`](https://timepath.github.io/scratchspace/d4/d95/common_2mutators_2events_8qh.html)
131
132 - **CLIENT:** [`qcsrc/client/mutators/events.qh`](https://timepath.github.io/scratchspace/d8/d0e/client_2mutators_2events_8qh.html)
133
134 - **SERVER:** [`qcsrc/server/mutators/events.qh`](https://timepath.github.io/scratchspace/d6/ddd/server_2mutators_2events_8qh.html)
135
136 <br />
137 <br />
138
139 # Weapon functions
140
141 ## A bit of introduction
142
143 You'll need understand that weapons can be interacted with **autocvars** variables (example: `float autocvar_g_balance_someweapon_speed;`) and each weapon with .qh file where cvars are declared without the need to declare using `autocvar_blabla...`. *Think*, *touch*, *explode* and those types of functions can be declared within an *attack* function and *whatever* it is called. Note that there are also METHODs that are necessary for the weapon to work.
144
145 - **Think** function makes the weapon shot react on what to do.
146 - **Touch** function makes the weapon shot react against some element where touch (like player, monster, vehicle, ...).
147 - **Explode** function makes the weapon explosion react.
148 - **Attack/Whatever** function is where the weapon attack executes, keep in mind that it has the other functions attached to be executed.
149
150 You can look the example of this weapon code:
151 - [**devastator.qh**](https://timepath.github.io/scratchspace/d9/dfa/devastator_8qh_source.html)
152 - [**devastator.qc**](https://timepath.github.io/scratchspace/d9/d5d/devastator_8qc_source.html)
153
154 <br />
155
156 ## List of weapon functions
157
158 This is a created list of functions to modify/create weapons. There may be incomplete explanations for each function.
159
160 There are contents taken from [`qcsrc/common/weapons/all.qh`](https://timepath.github.io/scratchspace/d0/ddd/weapons_2all_8qh_source.html)
161
162 **WARNING:** The contents may content wonky code, and the interactions can change and not do the same what happens here.
163
164 <br />
165
166 - [**W_SetupShot_Dir**](https://timepath.github.io/scratchspace/d4/d3f/tracing_8qh.html#aff0ea351757ee6caf83b25d12d18656c)
167
168 ```c
169 W_SetupShot_Dir(
170         ent,
171         wepent,
172         s_forward,
173         antilag,
174         recoil,
175         snd,
176         chan,
177         maxdamage,
178         deathtype 
179 )
180 ```
181
182 - [**W_SetupProjVelocity_Explicit**](https://timepath.github.io/scratchspace/d7/d31/tracing_8qc.html#a55f8f2b1828413bfb123a5fcb61b9f8e)
183
184 ```c
185 void W_SetupProjVelocity_Explicit(
186     entity      proj,
187     vector      dir,
188     vector      upDir,
189     float       pSpeed,
190     float       pUpSpeed,
191     float       pZSpeed,
192     float       spread,
193     float       forceAbsolute 
194 )
195 ```
196
197 - [**W_MuzzleFlash**](https://timepath.github.io/scratchspace/d0/ddd/weapons_2all_8qh_source.html)(located in **`qcsrc/common/weapons/all.qh`** line 406)
198
199 In the moment when player shots the weapon, weapon flashes. 
200
201 **Note:** write **`#ifdef SVQC`** at the start of using this function, and write with **`#endif`** after declared the function (only can do this if the code needs to be executed, although maybe you need more functions/things in the code inside this).
202
203 ```c
204 void W_MuzzleFlash(Weapon thiswep, entity actor, .entity weaponentity, vector shotorg, vector shotdir);
205 ```
206
207 - [**Weapon selection functions**](https://timepath.github.io/scratchspace/d8/d6b/selection_8qh.html)
208 (located in **`qcsrc/server/weapons/selection.qh`**)
209
210 - [**Weapon decrease ammo, speed factor, rate factor, reload functions**](https://timepath.github.io/scratchspace/d5/de0/weaponsystem_8qc.html)
211 (located in **`qcsrc/server/weapons/weaponsystem.qh`**)
212
213 <br />
214
215 # HUD, Menu and Draw functions
216
217 You can look the draw functions where HUD is being drawn: 
218 - [**Draw functions and macros (`qcsrc/client/draw.qh`)**](https://timepath.github.io/scratchspace/d5/d8d/client_2draw_8qh_source.html)
219
220 More info inside the code where you can draw/print HUD and menu: 
221 - [**Globals, constants, fonts, prints, error cmds, vector stuff, conversion functions and all drawing/printing HUDs/menus/characters related (`qcsrc/dpdefs/upstream/menudefs.qc`)**](https://timepath.github.io/scratchspace/d8/de2/menudefs_8qc_source.html)
222
223 <br />
224
225 # Gamemodes
226
227 Keep in mind that to develop a gamemode, you need a map having enabled inside its *name_of_map.mapinfo* file this: `gametype shortcut_of_gamemode`. (example: `gametype tdm` (tdm is Team Deathmatch). After modifying the map file, compress the map contents, save as `.zip` and rename the extension to `.pk3`
228
229 Making gamemodes doesn't seem easy. There's a little explanation of what does each element. 
230
231 ### Generated files for gamemodes:
232
233 [`qcsrc/common/gamemodes/gamemode/_mod.inc`](https://timepath.github.io/scratchspace/d9/d67/common_2gamemodes_2__mod_8inc_source.html) generated file where the includes of each gamemode are stored.
234
235 [`qcsrc/common/gamemodes/gamemode/_mod.qh`](https://timepath.github.io/scratchspace/d7/d0b/common_2gamemodes_2__mod_8qh_source.html) generated file where the includes of each gamemode are stored.
236
237 <br />
238
239 ### Gamemode files:
240
241 - Server type:
242
243 `qcsrc/common/gamemodes/gamemode/name_of_gamemode/sv_name_of_gamemode.qc`
244
245 `qcsrc/common/gamemodes/gamemode/name_of_gamemode/sv_name_of_gamemode.qh`
246
247 <br />
248
249 - Client type:
250
251 `qcsrc/common/gamemodes/gamemode/name_of_gamemode/cl_name_of_gamemode.qc`
252
253 `qcsrc/common/gamemodes/gamemode/name_of_gamemode/cl_name_of_gamemode.qh`
254
255 <br />
256
257 - Base:
258
259 `qcsrc/common/gamemodes/gamemode/name_of_gamemode/name_of_gamemode.qc`
260
261 `qcsrc/common/gamemodes/gamemode/name_of_gamemode/name_of_gamemode.qh`
262
263 `qcsrc/common/gamemodes/gamemode/name_of_gamemode/_mod.inc` generated file where the includes of a gamemode is generated.
264
265 `qcsrc/common/gamemodes/gamemode/name_of_gamemode/_mod.qh` generated file where the includes of a gamemode is generated.
266
267 <br />
268
269 ### Optional things (if necessary):
270
271 [`qcsrc/common/ent_cs.qc`](https://timepath.github.io/scratchspace/d5/dff/ent__cs_8qc_source.html) (if an `ENTCS_PROP()` is needed for a gamemode)
272
273 [`qcsrc/common/mutators/mutator/waypoints/all.inc`](https://timepath.github.io/scratchspace/d2/d2b/mutators_2mutator_2waypoints_2all_8inc_source.html) where `REGISTER_WAYPOINT` can interact the situation of waypoints.
274
275 <br />
276
277 ### Notifications, applying BADCVAR and displaying gamemode in the menu: 
278
279 [`qcsrc/common/notifications/all.inc`](https://timepath.github.io/scratchspace/d9/d09/notifications_2all_8inc_source.html) where notifications output appears in the scenario.
280
281 [`qcsrc/common/notifications/all.qh`](https://timepath.github.io/scratchspace/dc/d8f/notifications_2all_8qh_source.html) where `CASE(CPID, NAME_OF_ELEMENT)` is needed for a gamemode.
282
283 [`qcsrc/menu/xonotic/util.qc`](https://timepath.github.io/scratchspace/df/d9b/menu_2xonotic_2util_8qc_source.html) where gamemodes can appear in the main menu (Multiplayer > Create). `GAMETYPE(MAPINFO_TYPE_NAME_OF_GAMEMODE) \`
284  
285 [`qcsrc/server/world.qc`](https://timepath.github.io/scratchspace/dd/dbe/world_8qc_source.html)  where `BADCVAR(g_*)` for each gamemode are stored.
286
287 <br />
288
289 ### Configuration files where gamemodes interact:
290
291 `xonotic-data.pk3dir/gamemodes-server.cfg` where server gamestart hooks, gametype vote hooks, respawn delay/waves/weapon_stay cvars and gamemode game/server cvars connect.
292
293 `xonotic-data.pk3dir/gamemodes-client.cfg` where client gamestart hooks cvars connect.
294
295 `xonotic-data.pk3dir/notifications.cfg` where notifications need to be activated in the scenario.
296
297 <br />
298
299 ### Menu and HUD icons:
300
301 `gfx/menu/luma/gametype_nameshortcut.tga`
302
303 `gfx/menu/luminos/gametype_nameshortcut.tga`
304
305 `gfx/menu/wickedx/gametype_nameshortcut.tga`
306
307 `gfx/menu/xaw/gametype_nameshortcut.tga`
308
309 (Example: `gametype_tdm.tga` is an icon of Team Deathmatch)
310
311 <br />
312
313 ## Samples
314
315 There are good examples of the commits and repositories of people who developed gamemodes:
316
317 - [**Lyberta's GunGame gametype commits**](https://gitlab.com/xonotic/xonotic-data.pk3dir/-/merge_requests/482/diffs)
318
319 Taken from: https://forums.xonotic.org/showthread.php?tid=7314
320
321 You can look and test the [**Lyberta's GunGame gametype repository**](https://gitlab.com/xonotic/xonotic-data.pk3dir/-/tree/Lyberta/GunGame)
322
323 - [**How Survival gamemode was developed (first commit)**](https://gitlab.com/xonotic/xonotic-data.pk3dir/-/commit/8f61a40877542ac94baa74c5ed653c77b77bd855)
324
325 It's recommended use the final product in this [**repository**](https://gitlab.com/xonotic/xonotic-data.pk3dir/-/tree/Mario/survival). Many changes have been influenced.
326
327 [**SMB modpack repository**](https://github.com/MarioSMB/modpack/tree/master/mod/common/gamemodes/survival) has added Survival gamemode and others.
328
329 # Effects
330
331 Spawns effect particle in-game.
332
333 The effects can be used with `Send_Effect(effect, org, vel, howmany)` function to test the effects from [**qcsrc/common/effects/all.inc**](https://timepath.github.io/scratchspace/d9/d95/effects_2all_8inc_source.html)
334
335 **Send_Effect** function definition is inside: [**qcsrc/common/effects/effect.qh**](https://timepath.github.io/scratchspace/d5/de6/effect_8qh_source.html)
336
337 For example, you can test the smokes, using `EFFECT_SMOKE_LARGE`:
338 ```c
339 Send_Effect(EFFECT_SMOKE_LARGE, this.origin, '0 0 0', 1);
340 ```
341
342 EFFECT list: [**qcsrc/common/effects/all.inc**](https://timepath.github.io/scratchspace/d9/d95/effects_2all_8inc_source.html)
343
344 <br />