Nuclide
Software Development Kit for id Technology (BETA)
common.h
1/*
2 * Copyright (c) 2016-2024 Vera Visions LLC.
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
13 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
14 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15*/
16
17#define bool float
18#define true 1
19#define false 0
20
21#define PROGS_TIME time
22
27var bool autocvar_g_logTimestamps = false;
28
29/* objects are really just entities. */
30typedef entity id;
31
32typedef float musictrack_t;
33
34typedef enum
35{
36 LOGLEVEL_NONE,
37 LOGLEVEL_ERRORS,
38 LOGLEVEL_WARNINGS,
39 LOGLEVEL_DEBUG,
40} logLevel_t;
41
42#define LOGLEVEL_DEFAULT LOGLEVEL_WARNINGS
43var logLevel_t autocvar_g_logLevel = LOGLEVEL_DEFAULT;
44
45#define printf(...) print(sprintf(__VA_ARGS__))
46#define conprintf(...) localcmd(sprintf(__VA_ARGS__))
47
48#ifdef DOXYGEN
50#define enumflags enum
51#endif
52
53#define ICN_SIZE 8
54
55/* I too wish this could be a macro */
56string
57imageToConsole(string imageName, int imgSize, string toolTip)
58{
59 return sprintf("^[\\img\\%s\\s\\%i\\tip\\%s^]", imageName, imgSize, toolTip);
60}
61
62#define CG_LOG imageToConsole("gfx/icon16/monitor", ICN_SIZE, "Client Game Log")
63#define CG_WARNING imageToConsole("gfx/icon16/error", ICN_SIZE, "Client Game Warning")
64#define CG_ERROR imageToConsole("gfx/icon16/exclamation", ICN_SIZE, "Client Game Error")
65
66#define SV_LOG imageToConsole("gfx/icon16/server", ICN_SIZE, "Server Game Log")
67#define SV_WARNING imageToConsole("gfx/icon16/error", ICN_SIZE, "Server Game Warning")
68#define SV_ERROR imageToConsole("gfx/icon16/exclamation", ICN_SIZE, "Server Game Error")
69
70#define UI_LOG imageToConsole("gfx/icon16/picture", ICN_SIZE, "Menu Game Log")
71#define UI_WARNING imageToConsole("gfx/icon16/error", ICN_SIZE, "Menu Game Warning")
72#define UI_ERROR imageToConsole("gfx/icon16/exclamation", ICN_SIZE, "Menu Game Error")
73
74#define RULE_LOG imageToConsole("gfx/icon16/script_go", ICN_SIZE, "RuleC Log")
75#define RULE_WARNING imageToConsole("gfx/icon16/error", ICN_SIZE, "RuleC Warning")
76#define RULE_ERROR imageToConsole("gfx/icon16/exclamation", ICN_SIZE, "RuleC Error")
77
78#define MAP_LOG imageToConsole("gfx/icon16/map_go", ICN_SIZE, "MapC Log")
79#define MAP_WARNING imageToConsole("gfx/icon16/error", ICN_SIZE, "MapC Warning")
80#define MAP_ERROR imageToConsole("gfx/icon16/exclamation", ICN_SIZE, "MapC Error")
81
82#define HUD_LOG imageToConsole("gfx/icon16/monitor_go", ICN_SIZE, "HudC Log")
83#define HUD_WARNING imageToConsole("gfx/icon16/error", ICN_SIZE, "HudC Warning")
84#define HUD_ERROR imageToConsole("gfx/icon16/exclamation", ICN_SIZE, "HudC Error")
85
86#define ADDON_LOG imageToConsole("gfx/icon16/plugin_go", ICN_SIZE, "AddonC Log")
87#define ADDON_WARNING imageToConsole("gfx/icon16/error", ICN_SIZE, "AddonC Warning")
88#define ADDON_ERROR imageToConsole("gfx/icon16/exclamation", ICN_SIZE, "AddonC Error")
89
90void
91_ncLog(string msg)
92{
93#ifdef CLIENT
94 if (autocvar_g_logTimestamps)
95 print(sprintf("%s ^9%f ^7%s\n", CG_LOG, PROGS_TIME, msg));
96 else
97 print(sprintf("%s ^7%s\n", CG_LOG, msg));
98#endif
99#ifdef SERVER
100 if (autocvar_g_logTimestamps)
101 print(sprintf("%s ^9%f ^7%s\n", SV_LOG, PROGS_TIME, msg));
102 else
103 print(sprintf("%s ^7%s\n", SV_LOG, msg));
104#endif
105#ifdef MENU
106 if (autocvar_g_logTimestamps)
107 print(sprintf("%s ^9%f ^7%s\n", UI_LOG, PROGS_TIME, msg));
108 else
109 print(sprintf("%s ^7%s\n", UI_LOG, msg));
110#endif
111#ifdef RULEC
112 if (autocvar_g_logTimestamps)
113 print(sprintf("%s ^9%f ^7%s\n", RULE_LOG, PROGS_TIME, msg));
114 else
115 print(sprintf("%s ^7%s\n", RULE_LOG, msg));
116#endif
117#ifdef MAPC
118 if (autocvar_g_logTimestamps)
119 print(sprintf("%s ^9%f ^7%s\n", MAP_LOG, PROGS_TIME, msg));
120 else
121 print(sprintf("%s ^7%s\n", MAP_LOG, msg));
122#endif
123#ifdef HUDC
124 if (autocvar_g_logTimestamps)
125 print(sprintf("%s ^9%f ^7%s\n", HUD_LOG, PROGS_TIME, msg));
126 else
127 print(sprintf("%s ^7%s\n", HUD_LOG, msg));
128#endif
129#ifdef ADDONC
130 if (autocvar_g_logTimestamps)
131 print(sprintf("%s ^9%f ^7%s\n", ADDON_LOG, PROGS_TIME, msg));
132 else
133 print(sprintf("%s ^7%s\n", ADDON_LOG, msg));
134#endif
135}
136
137void
138_ncError(string functionName, string msg)
139{
140#ifdef CLIENT
141 if (autocvar_g_logTimestamps)
142 print(sprintf("%s ^9%f ^1%s^1: %s\n", CG_ERROR, PROGS_TIME, functionName, msg));
143 else
144 print(sprintf("%s ^1%s^1: %s\n", CG_ERROR, functionName, msg));
145#endif
146#ifdef SERVER
147 if (autocvar_g_logTimestamps)
148 print(sprintf("%s ^9%f ^1%s^1: %s\n", SV_ERROR, PROGS_TIME, functionName, msg));
149 else
150 print(sprintf("%s ^1%s^1: %s\n", SV_ERROR, functionName, msg));
151#endif
152#ifdef MENU
153 if (autocvar_g_logTimestamps)
154 print(sprintf("%s ^9%f ^1%s^1: %s\n", UI_ERROR, PROGS_TIME, functionName, msg));
155 else
156 print(sprintf("%s ^1%s^1: %s\n", UI_ERROR, functionName, msg));
157#endif
158#ifdef RULEC
159 if (autocvar_g_logTimestamps)
160 print(sprintf("%s ^9%f ^1%s^1: %s\n", RULE_ERROR, PROGS_TIME, functionName, msg));
161 else
162 print(sprintf("%s ^1%s^1: %s\n", RULE_ERROR, functionName, msg));
163#endif
164#ifdef MAPC
165 if (autocvar_g_logTimestamps)
166 print(sprintf("%s ^9%f ^1%s^1: %s\n", MAP_ERROR, PROGS_TIME, functionName, msg));
167 else
168 print(sprintf("%s ^1%s^1: %s\n", MAP_ERROR, functionName, msg));
169#endif
170#ifdef HUDC
171 if (autocvar_g_logTimestamps)
172 print(sprintf("%s ^9%f ^1%s^1: %s\n", HUD_ERROR, PROGS_TIME, functionName, msg));
173 else
174 print(sprintf("%s ^1%s^1: %s\n", HUD_ERROR, functionName, msg));
175#endif
176#ifdef ADDONC
177 if (autocvar_g_logTimestamps)
178 print(sprintf("%s ^9%f ^1%s^1: %s\n", ADDON_ERROR, PROGS_TIME, functionName, msg));
179 else
180 print(sprintf("%s ^1%s^1: %s\n", ADDON_ERROR, functionName, msg));
181#endif
182}
183
184void
185_ncWarning(string functionName, string msg)
186{
187#ifdef CLIENT
188 if (autocvar_g_logTimestamps)
189 print(sprintf("%s ^9%f ^3%s^1: %s\n", CG_WARNING, PROGS_TIME, functionName, msg));
190 else
191 print(sprintf("%s ^3%s^1: %s\n", CG_WARNING, functionName, msg));
192#endif
193#ifdef SERVER
194 if (autocvar_g_logTimestamps)
195 print(sprintf("%s ^9%f ^3%s^1: %s\n", SV_WARNING, PROGS_TIME, functionName, msg));
196 else
197 print(sprintf("%s ^3%s^1: %s\n", SV_WARNING, functionName, msg));
198#endif
199#ifdef MENU
200 if (autocvar_g_logTimestamps)
201 print(sprintf("%s ^9%f ^3%s^1: %s\n", UI_WARNING, PROGS_TIME, functionName, msg));
202 else
203 print(sprintf("%s ^3%s^1: %s\n", UI_WARNING, functionName, msg));
204#endif
205#ifdef RULEC
206 if (autocvar_g_logTimestamps)
207 print(sprintf("%s ^9%f ^3%s^1: %s\n", RULE_WARNING, PROGS_TIME, functionName, msg));
208 else
209 print(sprintf("%s ^3%s^1: %s\n", RULE_WARNING, functionName, msg));
210#endif
211#ifdef MAPC
212 if (autocvar_g_logTimestamps)
213 print(sprintf("%s ^9%f ^3%s^1: %s\n", MAP_WARNING, PROGS_TIME, functionName, msg));
214 else
215 print(sprintf("%s ^3%s^1: %s\n", MAP_WARNING, functionName, msg));
216#endif
217#ifdef HUDC
218 if (autocvar_g_logTimestamps)
219 print(sprintf("%s ^9%f ^3%s^1: %s\n", HUD_WARNING, PROGS_TIME, functionName, msg));
220 else
221 print(sprintf("%s ^3%s^1: %s\n", HUD_WARNING, functionName, msg));
222#endif
223#ifdef ADDONC
224 if (autocvar_g_logTimestamps)
225 print(sprintf("%s ^9%f ^3%s^1: %s\n", ADDON_WARNING, PROGS_TIME, functionName, msg));
226 else
227 print(sprintf("%s ^3%s^1: %s\n", ADDON_WARNING, functionName, msg));
228#endif
229}
230
231void
232_NSAssert(bool condition, string function, string descr)
233{
234#ifdef CLIENT
235 if (!condition) {
236 print(strcat(CG_ERROR, " ^1Assertion failed in ", function, ", reason: ", descr, "\n"));
237 breakpoint();
238 }
239#endif
240#ifdef SERVER
241 if (!condition) {
242 print(strcat(SV_ERROR, " ^1Assertion failed in ", function, ", reason: ", descr, "\n"));
243 breakpoint();
244 }
245#endif
246#ifdef MENU
247 if (!condition) {
248 print(strcat(UI_ERROR, " ^1Assertion failed in ", function, ", reason: ", descr, "\n"));
249 }
250#endif
251#ifdef RULEC
252 if (!condition) {
253 print(strcat(RULE_ERROR, " ^1Assertion failed in ", function, ", reason: ", descr, "\n"));
254 }
255#endif
256#ifdef MAPC
257 if (!condition) {
258 print(strcat(MAP_ERROR, " ^1Assertion failed in ", function, ", reason: ", descr, "\n"));
259 }
260#endif
261#ifdef HUDC
262 if (!condition) {
263 print(strcat(HUD_ERROR, " ^1Assertion failed in ", function, ", reason: ", descr, "\n"));
264 }
265#endif
266#ifdef ADDONC
267 if (!condition) {
268 print(strcat(ADDON_ERROR, " ^1Assertion failed in ", function, ", reason: ", descr, "\n"));
269 }
270#endif
271}
272
277#define ncLog(...) if (autocvar_g_logLevel >= LOGLEVEL_DEBUG) _ncLog(sprintf(__VA_ARGS__))
278
282#define ncLogAlways(...) _ncLog(sprintf(__VA_ARGS__))
283
288#define ncError(...) if (autocvar_g_logLevel >= LOGLEVEL_ERRORS) _ncError(__FUNC__, sprintf(__VA_ARGS__))
289
294#define ncWarning(...) if (autocvar_g_logLevel >= LOGLEVEL_WARNINGS) _ncWarning(__FUNC__, sprintf(__VA_ARGS__))
295
301#define NSAssert(condition, ...) if (autocvar_g_logLevel >= LOGLEVEL_ERRORS) _NSAssert(condition, __FUNC__, sprintf(__VA_ARGS__))
302
303typedef enumflags
304{
305 SEARCH_INSENSITIVE,
306 SEARCH_FULLPACKAGE,
307 SEARCH_ALLOWDUPES,
308 SEARCH_FORCESEARCH,
309 SEARCH_MULTISEARCH,
310 SEARCH_NAMESORT
311} searchFlags_t;
312
313const entity g_entity_null = __NULL__;
314const float g_float_null = 0.0f;
315const int g_int_null = 0i;
316const string g_string_null = "";
317const vector g_vec_null = [0.0f, 0.0f, 0.0f];
318
319void
320InitPrint(string functionName)
321{
322 static int chars = 51i;
323 int charsLeft;
324 int charExtra;
325 string sideLeft = "";
326 string sideRight = "";
327
328 if (functionName == __NULL__) {
329 ncLogAlways("---------------------------------------------------");
330 return;
331 }
332
333 /* word and padding */
334 chars = chars - (int)strlen(functionName) - 2i;
335 charsLeft = chars / 2i;
336 charExtra = chars % 2i;
337
338 for (int i = 0i; i < charsLeft; i++)
339 sideLeft = strcat(sideLeft,"-");
340
341 for (int i = 0i; i < (charsLeft + charExtra); i++) {
342 sideRight = strcat(sideRight,"-");
343 }
344
345 ncLogAlways( "%s %s %s", sideLeft, functionName, sideRight);
346}
347
348#define InitStart() float local_initTime = gettime(1); InitPrint(__FUNC__)
349
350void
351_InitEnd(float oldTime, string functionName)
352{
353 float endTime = gettime(1);
354 ncLogAlways("%s loaded in %.1f seconds", functionName, (endTime - oldTime));
355 ncLogAlways("---------------------------------------------------");
356}
357
358#define InitEnd() _InitEnd(local_initTime, __FUNC__)
359
361#define entity_def(x, ...) const string x[] = { __VA_ARGS__ }
362
364#define thread(x) if (fork()) { x; abort(); }
365
366#define STRING_SET(x) ((x != __NULL__) && (x != ""))
367
368bool
369fileExists(string filePath)
370{
371 if (!STRING_SET(filePath)) {
372 return (false);
373 }
374
375 /* not present on disk */
376 if not(whichpack(filePath)) {
377 return (false);
378 }
379
380
381 return (true);
382}
383
384string
385fileExtensionFromString(string inputString)
386{
387 int modelNameLength = strlen(inputString);
388 int dotChar = -1;
389
390 for (int i = (modelNameLength - 1); i > 0; i--) {
391 if (str2chr(inputString, i) == '.') {
392 dotChar = i;
393 break;
394 }
395 }
396
397 if (dotChar != -1) {
398 return substring(inputString, dotChar + 1, -1);
399 }
400
401 return (__NULL__);
402}
403
404#define Util_ExtensionFromString fileExtensionFromString
405
406bool
407wordInString(string fullString, string wordToFind)
408{
409 int wordCount = tokenize(fullString);
410
411 for (int i = 0; i < wordCount; i++) {
412 if (wordToFind == argv(i)) {
413 return (true);
414 }
415 }
416
417 return (false);
418}
419
420
421float
422crandom(void)
423{
424 return ((random() - 0.5f) * 2.0f);
425}
426
427string
428basename(string input)
429{
430 if (!input) {
431 return "";
432 }
433
434 int c = tokenizebyseparator(input, "/", "\\ ", "!");
435 return (argv(c-1));
436}
437
438string
439dirname(string input)
440{
441 if (!input) {
442 return "";
443 }
444
445 int c = tokenizebyseparator(input, "/", "\\ ", "!");
446 string newpath = "";
447
448 for (int i = 0; i < (c-1); i++) {
449 newpath = sprintf("%s/%s", newpath, argv(i));
450 }
451
452 /* Kill the first / */
453 newpath = substring(newpath, 1, strlen(newpath)-1);
454
455 return newpath;
456}
457
458
459string
460skimFile(string filename)
461{
462 filestream fs_mapcycle;
463 string temp;
464 int mapCount = 0i;
465 string lastMap = "";
466 int nextMapID = 0i;
467
468 fs_mapcycle = fopen(filename, FILE_READ);
469
470 if (fs_mapcycle < 0) {
471 ncError("Missing file %s", filename);
472 return (__NULL__);
473 }
474
475 /* read the lines in, see if the map exists and define an enumerated alias */
476 while ((temp = fgets(fs_mapcycle))) {
477 tokenize_console(temp);
478 string mapName = argv(0);
479
480 if (STRING_SET(mapName)) {
481 return (mapName);
482 }
483
484 }
485
486 return (__NULL__);
487}
488
489void
490CallSpawnfuncByName(entity target, string className)
491{
492 entity oldSelf = self;
493 string spawnClass = strcat("spawnfunc_", className);
494 self = target;
495 callfunction(spawnClass);
496 self = oldSelf;
497}
498
499.string spawnclass;
500.float team_info;
501 // end of common
typedef enumflags
Defines the valid alignment flags for text fields.
Definition: font.h:37