Nuclide
Software Development Kit for id Technology (BETA)
Loading...
Searching...
No Matches
defs.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/* networking helpers */
18#define NETWORKED_INT(x) int x; int x ##_net;
19#define NETWORKED_FLOAT(x) float x; float x ##_net;
20#define NETWORKED_VECTOR(x) vector x; vector x ##_net;
21#define NETWORKED_ENT(x) entity x; entity x ##_net;
22#define NETWORKED_STRING(x) string x; string x ##_net;
23#define NETWORKED_BOOL(x) bool x; bool x ##_net;
24#define NETWORKED_MODELINDEX(x) float x; float x ##_net;
25
26#define NETWORKED_INT_N(x) int x ##_net;
27#define NETWORKED_FLOAT_N(x) float x ##_net;
28#define NETWORKED_VECTOR_N(x) vector x ##_net;
29#define NETWORKED_STRING_N(x) string x ##_net;
30
31#define PREDICTED_INT(x) int x; int x ##_net;
32#define PREDICTED_FLOAT(x) float x; float x ##_net;
33#define PREDICTED_VECTOR(x) vector x; vector x ##_net;
34#define PREDICTED_ENT(x) entity x; entity x ##_net;
35#define PREDICTED_STRING(x) string x; string x ##_net;
36#define PREDICTED_BOOL(x) bool x; bool x ##_net;
37
38#define PREDICTED_INT_N(x) int x ##_net;
39#define PREDICTED_FLOAT_N(x) float x ##_net;
40#define PREDICTED_VECTOR_N(x) vector x ##_net;
41#define PREDICTED_STRING_N(x) string x ##_net;
42
43#ifdef CLIENT
44var bool autocvar_net_showArrivals = false;
45
46#define NSENTITY_READENTITY(x, y) \
47 { \
48 local x x ##_e = ( x )self;\
49 local float x ##receivedFlags;\
50 if (y == true) { \
51 self.classname = strcat("spawnfunc_", #x); \
52 callfunction(self.classname); \
53 if (autocvar_net_showArrivals)\
54 ncError("New entity appeared to client: %S", self.classname);\
55 x ##_e.Spawned();\
56 } \
57 x ##receivedFlags = readfloat();\
58 x ##_e.ReceiveEntity( y, x ##receivedFlags );\
59 x ##_e.Relink();\
60 x ##_e._ReceiveComplete( y, x ##receivedFlags );\
61 }
62#else
63
64#endif
65
66#define NETWORKED_DEFAULT(x, y) x ##_net = x = y;
67
68#define ROLL_BACK(x) x = x ##_net;
69#define SAVE_STATE(x) x ##_net = x;
70#define SAVE_STATE_FIELD(x, y) x ##_net[y] = x[y];
71#define ATTR_CHANGED(x) (x ##_net != x)
72#define VEC_CHANGED(x,y) (x ##_net[y] != x[y])
73
74#ifndef MAX_AMMO_TYPES
75#define MAX_AMMO_TYPES 16i
76#endif
77
78noref const float SVC_TEMPENTITY = 23;
79
80#ifdef CLIENT
81string __fullspawndata;
82#endif
83
84#include "system/cloader.h"
85#include "audio/soundDef.h"
86#include "environment/effects.h"
87
88#ifdef CLIENT
89#include "../gs-entbase/client/defs.h"
90#else
91#include "../gs-entbase/server/defs.h"
92#endif
93
94#include "environment/Decal.h"
95
96#include "audio/sentences.h"
97
98#include "system/IO.h"
99#include "system/Dict.h"
100#include "audio/SoundDict.h"
101#include "system/Trigger.h"
102#include "system/Entity.h"
103#include "system/Timer.h"
104#include "system/RenderableEntity.h"
105#include "environment/SurfacePropEntity.h"
106#include "physics/Ragdoll.h"
107#include "environment/Mover.h"
108#include "physics/PhysicsConstraint.h"
109#include "physics/PhysicsEntity.h"
110#include "triggers/BrushTrigger.h"
111#include "triggers/PointTrigger.h"
112#include "game/Item.h"
113#include "game/Dispenser.h"
114#include "game/Weapon.h"
115#include "game/Actor.h"
116#include "ai/Monster.h"
117#include "ai/SquadMonster.h"
118#include "ai/TalkMonster.h"
119#include "game/SpawnPoint.h"
120#include "audio/SoundScape.h"
121#include "game/Attack.h"
122#include "game/Projectile.h"
123#include "environment/Spraylogo.h"
124#include "physics/Portal.h"
125#include "audio/Sound.h"
126#include "physics/Debris.h"
127#include "input/XRSpace.h"
128#include "input/XRInput.h"
129#include "input/XRManager.h"
130#include "../botlib/Bot.h"
131#include "game/Client.h"
132#include "game/Spectator.h"
133#include "physics/pmove.h"
134#include "game/Player.h"
135
136#include "physics/Vehicle.h"
137
138#include "environment/materials.h"
139#include "environment/damage.h"
140#include "game/entities.h"
141#include "game/hitmesh.h"
142#include "environment/propdata.h"
143#include "environment/surfaceproperties.h"
144#include "environment/decalgroups.h"
145#include "environment/bodyque.h"
146#include "game/motd.h"
147#include "system/util.h"
148#include "game/ammo.h"
149#include "system/activities.h"
150
151#define BSPVER_PREREL 28
152#define BSPVER_Q1 29
153#define BSPVER_HL 30
154#define BSPVER_Q2 38
155#define BSPVER_Q2W 69
156#define BSPVER_Q3 46
157#define BSPVER_RTCW 47
158#define BSPVER_RBSP 1
159
160#define CLASSEXPORT(a,b) void a(void) { if (!isfunction(#b)) { self.classname = strcat("spawnfunc_", #b); } else { self.classname = #b; } callfunction(self.classname); }
161
162const vector VEC_HULL_MIN = [-16,-16,-36];
163const vector VEC_HULL_MAX = [16,16,36];
164const vector VEC_CHULL_MIN = [-16,-16,-18];
165const vector VEC_CHULL_MAX = [16,16,18];
166
167#include "input/input.h"
168
169/* sendflags */
170#define UPDATE_ALL 16777215
171
172#define clamp(d,min,max) bound(min,d,max)
173
174enumflags
175{
176 SEARCH_INSENSITIVE,
177 SEARCH_FULLPACKAGE,
178 SEARCH_ALLOWDUPES,
179 SEARCH_FORCESEARCH,
180 SEARCH_MULTISEARCH,
181 SEARCH_NAMESORT
182};
183
184.vector m_pmoveBaseVelocity;
185.float gflags;
186.float vw_index;
187.float identity;
188.bool _isWeapon;
189.bool _isItem;
190
191void
192Empty(void)
193{
194
195}
196
197void Util_Destroy(void);
198string Util_TimeToString(float fTime);
199bool Util_IsTeamplay(void);
200bool Util_IsPaused(void);
201
202void
203crossprint(string m)
204{
205#ifdef CLIENT
206 print(strcat("CLIENT: ", m));
207#else
208 print(strcat("SERVER: ", m));
209#endif
210}
211
212#if 0
213__wrap string
214precache_model(string m)
215{
216 if (!STRING_SET(m)) {
217 return ("");
218 }
219
220 return prior(m);
221}
222#endif
223
224__wrap string
225precache_sound(string sample)
226{
227 if (sample != "") /* not empty */
228 if not(whichpack(strcat("sound/", sample))) { /* not present on disk */
229 ncError("SFX sample %S does not exist.", sample);
230 return "misc/missing.wav";
231 }
232
233 return prior(sample);
234}
235
236/* this could probably be a lot better, use this from now on so that it can be improved later */
237noref float input_sequence;
238float
239pseudorandom()
240{
241 float seed = (float)input_sequence % 5.0f;
242 seed += (float)input_sequence % 8.0f;
243 seed += (float)input_sequence % 4.0f;
244 seed += (float)input_sequence % 13.0f;
245 seed += (float)input_sequence % 70.0f;
246
247 /* like the engine its random(), never return 0, never return 1 */
248 return bound(0.01, (seed) / 100.0f, 0.99f);
249}
250
251#if 0
252__wrap void
253WriteByte(float to, float val)
254{
255 breakpoint();
256 prior(to, val);
257}
258
259__wrap void
260WriteChar(float to, float val)
261{
262 breakpoint();
263 prior(to, val);
264}
265
266__wrap void
267WriteShort(float to, float val)
268{
269 breakpoint();
270 prior(to, val);
271}
272
273__wrap void
274WriteLong(float to, float val)
275{
276 breakpoint();
277 prior(to, val);
278}
279
280__wrap void
281WriteCoord(float to, float val)
282{
283 breakpoint();
284 prior(to, val);
285}
286
287__wrap void
288WriteAngle(float to, float val)
289{
290 breakpoint();
291 prior(to, val);
292}
293
294__wrap void
295WriteString(float to, string val)
296{
297 breakpoint();
298 prior(to, val);
299}
300
301__wrap void
302WriteEntity(float to, entity val)
303{
304 breakpoint();
305 prior(to, val);
306}
307#endif
308
309__wrap void
310setmodel(entity ent, string mname)
311{
312 if (mname != "") /* not empty */
313 if (substring(mname, 0, 1) != "*") /* not a brush */
314 if not(whichpack(mname)) /* not present on disk */
315 return prior(ent, "models/error.vvm");
316
317 return prior(ent, mname);
318}
319
320.float removed;
321__wrap void
322remove(entity target)
323{
324 /* it's an ncEntity sub-class */
325 if (target.identity) {
326 ncEntity ent = (ncEntity)target;
327
328 /* if we're calling remove() on it and not .Destroy()... it's being uncleanly removed! */
329 if (ent.removed == 0) {
330 ent.OnRemoveEntity();
331 breakpoint();
332 print(sprintf("^1WARNING: Entity %d of class %s uncleanly removed!\n", num_for_edict(ent), ent.classname));
333 ent.removed = 1;
334 }
335 }
336
337 prior(target);
338}
339
340__wrap void
341traceline(vector v1, vector v2, float flags, entity ent)
342{
343#ifdef SERVER
344 if (autocvar(com_showTracers, 0) == 1) {
345 WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
346 WriteByte(MSG_MULTICAST, EV_TRACEDEBUG);
347 WriteCoord(MSG_MULTICAST, v1[0]);
348 WriteCoord(MSG_MULTICAST, v1[1]);
349 WriteCoord(MSG_MULTICAST, v1[2]);
350 WriteCoord(MSG_MULTICAST, v2[0]);
351 WriteCoord(MSG_MULTICAST, v2[1]);
352 WriteCoord(MSG_MULTICAST, v2[2]);
353 msg_entity = world;
354 multicast(v1, MULTICAST_PVS_R);
355 }
356#endif
357
358#ifdef CLIENT
359 // TODO
360#endif
361 prior(v1, v2, flags, ent);
362}
363
364#ifdef SERVER
365string Skill_GetStringValue(string, string);
366#endif
367
368string
369unpackStringCommand(string commandString)
370{
371#ifdef SERVER
372 /* is this supposed to be read from a skill cvar? */
373 if (substring(commandString, 0, 6) == "skill:") {
374 return Skill_GetStringValue(substring(commandString, 6, -1), "");
375 }
376 /* is this supposed to be read from a skill cvar? */
377 if (substring(commandString, 0, 5) == "cvar:") {
378 return cvar_string(substring(commandString, 5, -1));
379 }
380#endif
381
382 return Constants_LookUp(commandString, commandString);
383}
384
385#ifdef NO_LEGACY
386void
387readcmd(string foo)
388{
389 localcmd(foo);
390}
391#else
392void(string cmd) readcmd = #0:readcmd;
393#endif
394
395/* This is required because people who use Hammer do awful things
396 to get their models to update. We get a multitude of juicy
397 hacks and symbols that Half-Life's engine strips and now we have to
398 replicate this behaviour. Be thankful this is not done in-engine for
399 every game/mod ever.
400*/
401string Util_FixModel(string mdl)
402{
403 if (!STRING_SET(mdl)) {
404 return "";
405 }
406 mdl = strreplace("\\", "/", mdl);
407
408 /* don't allow empty directories, some Source maps have them. */
409 mdl = strreplace("//", "/", mdl);
410
411 int c = tokenizebyseparator(mdl, "/", "\\ ", "!");
412 string newpath = "";
413
414 for (int i = 0; i < c; i++) {
415 newpath = sprintf("%s/%s", newpath, argv(i));
416 }
417
418 /* Kill the first / */
419 newpath = substring(newpath, 1, strlen(newpath)-1);
420
421 /* Now we need to fix \/ because I hate people */
422 c = tokenizebyseparator(newpath, "\\/");
423 mdl = "";
424 for (int i = 0; i < c; i++) {
425 mdl = sprintf("%s/%s", mdl, argv(i));
426 }
427 /* Kill the first / again */
428 mdl = substring(mdl, 1, strlen(mdl)-1);
429
430 if (substring(mdl, 0, 1) == "/")
431 mdl = substring(mdl, 1, -1);
432
433 mdl = strreplace("/ ", "/", mdl);
434
435 return mdl;
436}
437
441string
442Util_ChangeExtension(string baseString, string newExtension)
443{
444 float stringOffset = 0;
445 string tempString = "";
446 float foundOffset = 0;
447
448 while ((tempString = substring(baseString, stringOffset, 1))) {
449 if (tempString == ".")
450 foundOffset = stringOffset;
451 if (tempString == "")
452 break;
453 if not (tempString)
454 break;
455
456 stringOffset++;
457 }
458
459 /* no extension found? append to the end then. */
460 if (foundOffset == 0) {
461 return strcat(baseString, ".", newExtension);
462 }
463
464 return strcat(substring(baseString, 0, foundOffset), ".", newExtension);
465}
466
467bool
468Util_IsSingleplayer(void)
469{
470#ifdef SERVER
471 /* playerslots 1 is always singleplayer */
472 if (cvar("sv_playerslots") == 1)
473 return true;
474
475 /* only when coop is 1, only in multiplayer */
476 if (cvar("coop") == 1 && cvar("sv_playerslots") > 1)
477 return true;
478#endif
479
480 /* else we're multiplayer */
481 return false;
482}
483
484float
485crandom(void)
486{
487 return ((random() - 0.5f) * 2.0f);
488}
489
490string
491dirname(string input)
492{
493 if (!input) {
494 return "";
495 }
496
497 int c = tokenizebyseparator(input, "/", "\\ ", "!");
498 string newpath = "";
499
500 for (int i = 0; i < (c-1); i++) {
501 newpath = sprintf("%s/%s", newpath, argv(i));
502 }
503
504 /* Kill the first / */
505 newpath = substring(newpath, 1, strlen(newpath)-1);
506
507 return newpath;
508}
509
510string
511textfile_to_string(string filename)
512{
513 string fileContents = __NULL__;
514
515 filestream fileHandle = fopen(filename, FILE_READ);
516 string temp;
517
518 if (fileHandle != -1) {
519 while ((temp = fgets(fileHandle))) {
520 fileContents = strcat(fileContents, temp, "\n");
521 }
522 } else {
523 fileContents = __NULL__;
524 }
525
526 return fileContents;
527}
528
529/* moved from src/botlib/route.qc */
530/* Get's a velocity vector with which we can successfully jump from one place to another */
531vector
532Route_GetJumpVelocity(vector vecFrom, vector vecTo, float flGravMod)
533{
534#if 1
535 float flHeight, flGravity, flTime, flDistance, flDir;
536 vector vecJump = [0,0,0];
537
538 if (flGravMod <= 0.0)
539 flGravMod = 1.0f;
540
541 flGravity = serverkeyfloat("phy_gravity") * flGravMod;
542 flHeight = vecTo[2] - vecFrom[2];
543
544 /* this may not be a much verticality to this jump, use distance instead */
545 if (flHeight <= 0) {
546 flHeight = vlen(vecTo - vecFrom);
547 flTime = flHeight / flGravity;
548 } else {
549 flTime = sqrt(flHeight / (flGravity * 0.5f));
550 if (flTime <= 0) {
551 return [0,0,0];
552 }
553 }
554
555 vecJump = vecTo - vecFrom;
556 vecJump[2] = 0;
557 flDistance = vlen(normalize(vecJump));
558
559 flDir = flDistance / flTime;
560 vecJump *= flDir;
561 vecJump[2] = flTime * flGravity;
562#else
563 vector vecJump = [0,0,0];
564 float flDist = vlen(vecTo - vecFrom);
565 makevectors(vectoangles(vecTo - vecFrom));
566 vecJump = v_forward * flDist;
567 vecJump[2] = 280;
568#endif
569 return vecJump;
570}
571
572void
573DebugBox(vector absPos, vector minSize, vector maxSize, vector boxColor, float boxAlpha)
574{
575 vector a, b, c, d;
576 vector w, x, y, z;
577
578 a[0] = absPos[0] + minSize[0];
579 a[1] = absPos[1] + maxSize[1];
580
581 b[0] = absPos[0] + maxSize[0];
582 b[1] = absPos[1] + maxSize[1];
583
584 c[0] = absPos[0] + maxSize[0];
585 c[1] = absPos[1] + minSize[1];
586
587 d[0] = absPos[0] + minSize[0];
588 d[1] = absPos[1] + minSize[1];
589
590 a[2] = absPos[2] + maxSize[2];
591 c[2] = absPos[2] + maxSize[2];
592 d[2] = absPos[2] + maxSize[2];
593 b[2] = absPos[2] + maxSize[2];
594
595 w = a;
596 x = b;
597 y = c;
598 z = d;
599
600 w[2] = absPos[2] + minSize[2];
601 x[2] = absPos[2] + minSize[2];
602 y[2] = absPos[2] + minSize[2];
603 z[2] = absPos[2] + minSize[2];
604
605 /* top */
606 R_BeginPolygon("", 0, 0);
607 R_PolygonVertex(a, [1,1], boxColor, boxAlpha);
608 R_PolygonVertex(b, [0,1], boxColor, boxAlpha);
609 R_PolygonVertex(c, [0,0], boxColor, boxAlpha);
610 R_PolygonVertex(d, [1,0], boxColor, boxAlpha);
611 R_EndPolygon();
612
613 /* front */
614 R_BeginPolygon("", 0, 0);
615 R_PolygonVertex(d, [1,1], boxColor * 0.9f, boxAlpha);
616 R_PolygonVertex(c, [0,1], boxColor * 0.9f, boxAlpha);
617 R_PolygonVertex(y, [0,0], boxColor * 0.9f, boxAlpha);
618 R_PolygonVertex(z, [1,0], boxColor * 0.9f, boxAlpha);
619 R_EndPolygon();
620
621 /* back */
622 R_BeginPolygon("", 0, 0);
623 R_PolygonVertex(w, [1,1], boxColor * 0.9f, boxAlpha);
624 R_PolygonVertex(x, [0,1], boxColor * 0.9f, boxAlpha);
625 R_PolygonVertex(b, [0,0], boxColor * 0.9f, boxAlpha);
626 R_PolygonVertex(a, [1,0], boxColor * 0.9f, boxAlpha);
627 R_EndPolygon();
628
629 /* left */
630 R_BeginPolygon("", 0, 0);
631 R_PolygonVertex(a, [1,1], boxColor * 0.8f, boxAlpha);
632 R_PolygonVertex(d, [0,1], boxColor * 0.8f, boxAlpha);
633 R_PolygonVertex(z, [0,0], boxColor * 0.8f, boxAlpha);
634 R_PolygonVertex(w, [1,0], boxColor * 0.8f, boxAlpha);
635 R_EndPolygon();
636
637 /* right */
638 R_BeginPolygon("", 0, 0);
639 R_PolygonVertex(c, [1,1], boxColor * 0.8f, boxAlpha);
640 R_PolygonVertex(b, [0,1], boxColor * 0.8f, boxAlpha);
641 R_PolygonVertex(x, [0,0], boxColor * 0.8f, boxAlpha);
642 R_PolygonVertex(y, [1,0], boxColor * 0.8f, boxAlpha);
643 R_EndPolygon();
644
645 /* bottom */
646 R_BeginPolygon("", 0, 0);
647 R_PolygonVertex(z, [1,1], boxColor, boxAlpha);
648 R_PolygonVertex(y, [0,1], boxColor, boxAlpha);
649 R_PolygonVertex(x, [0,0], boxColor, boxAlpha);
650 R_PolygonVertex(w, [1,0], boxColor, boxAlpha);
651 R_EndPolygon();
652}
653
654/* doxygen definitions */
655
659
663
667
671
681
686
691
709
720
ncEntity is the lowest of the user-accessible entity class.
Definition Entity.h:75
string Constants_LookUp(string constName, string returnValue)
Look up a name and retrieve its value.
Definition cloader.qc:84
vector Route_GetJumpVelocity(vector, vector, float)
Definition defs.h:532
float flags
Definition soundDef.h:114