]> icculus.org git repositories - divverent/darkplaces.git/blob - dpdefs/progsdefs.qc
change default snd_soundradius back to 1000, matching Quake
[divverent/darkplaces.git] / dpdefs / progsdefs.qc
1 /*
2 ==============================================================================
3
4                         SOURCE FOR GLOBALVARS_T C STRUCTURE
5                         MUST NOT BE MODIFIED, OR CRC ERRORS WILL APPEAR
6
7 ==============================================================================
8 */
9
10 //
11 // system globals
12 //
13 entity          self;
14 entity          other;
15 entity          world;
16 float           time;
17 float           frametime;
18
19 float           force_retouch;          // force all entities to touch triggers
20                                                                 // next frame.  this is needed because
21                                                                 // non-moving things don't normally scan
22                                                                 // for triggers, and when a trigger is
23                                                                 // created (like a teleport trigger), it
24                                                                 // needs to catch everything.
25                                                                 // decremented each frame, so set to 2
26                                                                 // to guarantee everything is touched
27 string          mapname;
28
29 float           deathmatch;
30 float           coop;
31 float           teamplay;
32
33 float           serverflags;            // propagated from level to level, used to
34                                                                 // keep track of completed episodes
35
36 float           total_secrets;
37 float           total_monsters;
38
39 float           found_secrets;          // number of secrets found
40 float           killed_monsters;        // number of monsters killed
41
42
43 // spawnparms are used to encode information about clients across server
44 // level changes
45 float           parm1, parm2, parm3, parm4, parm5, parm6, parm7, parm8, parm9, parm10, parm11, parm12, parm13, parm14, parm15, parm16;
46
47 //
48 // global variables set by built in functions
49 //
50 vector          v_forward, v_up, v_right;       // set by makevectors()
51
52 // set by traceline / tracebox
53 float           trace_allsolid;
54 float           trace_startsolid;
55 float           trace_fraction;
56 vector          trace_endpos;
57 vector          trace_plane_normal;
58 float           trace_plane_dist;
59 entity          trace_ent;
60 float           trace_inopen;
61 float           trace_inwater;
62
63 entity          msg_entity;                             // destination of single entity writes
64
65 //
66 // required prog functions
67 //
68 void()          main;                                           // only for testing
69
70 void()          StartFrame;
71
72 void()          PlayerPreThink;
73 void()          PlayerPostThink;
74
75 void()          ClientKill;
76 void()          ClientConnect;
77 void()          PutClientInServer;              // call after setting the parm1... parms
78 void()          ClientDisconnect;
79
80 void()          SetNewParms;                    // called when a client first connects to
81                                                                         // a server. sets parms so they can be
82                                                                         // saved off for restarts
83
84 void()          SetChangeParms;                 // call to set parms for self so they can
85                                                                         // be saved for a level transition
86
87
88 //================================================
89 void            end_sys_globals;                // flag for structure dumping
90 //================================================
91
92 /*
93 ==============================================================================
94
95                         SOURCE FOR ENTVARS_T C STRUCTURE
96                         MUST NOT BE MODIFIED, OR CRC ERRORS WILL APPEAR
97
98 ==============================================================================
99 */
100
101 //
102 // system fields (*** = do not set in prog code, maintained by C code)
103 //
104 .float          modelindex;             // *** model index in the precached list
105 .vector         absmin, absmax; // *** origin + mins / maxs
106
107 .float          ltime;                  // local time for entity
108 .float          movetype;
109 .float          solid;
110
111 .vector         origin;                 // ***
112 .vector         oldorigin;              // ***
113 .vector         velocity;
114 .vector         angles;
115 .vector         avelocity;
116
117 .vector         punchangle;             // temp angle adjust from damage or recoil
118
119 .string         classname;              // spawn function
120 .string         model;
121 .float          frame;
122 .float          skin;
123 .float          effects;
124
125 .vector         mins, maxs;             // bounding box extents reletive to origin
126 .vector         size;                   // maxs - mins
127
128 .void()         touch;
129 .void()         use;
130 .void()         think;
131 .void()         blocked;                // for doors or plats, called when can't push other
132
133 .float          nextthink;
134 .entity         groundentity;
135
136 // stats
137 .float          health;
138 .float          frags;
139 .float          weapon;                 // one of the IT_SHOTGUN, etc flags
140 .string         weaponmodel;
141 .float          weaponframe;
142 .float          currentammo;
143 .float          ammo_shells, ammo_nails, ammo_rockets, ammo_cells;
144
145 .float          items;                  // bit flags
146
147 .float          takedamage;
148 .entity         chain;
149 .float          deadflag;
150
151 .vector         view_ofs;                       // add to origin to get eye point
152
153
154 .float          button0;                // fire
155 .float          button1;                // use
156 .float          button2;                // jump
157
158 .float          impulse;                // weapon changes
159
160 .float          fixangle;
161 .vector         v_angle;                // view / targeting angle for players
162 .float          idealpitch;             // calculated pitch angle for lookup up slopes
163
164
165 .string         netname;
166
167 .entity         enemy;
168
169 .float          flags;
170
171 .float          colormap;
172 .float          team;
173
174 .float          max_health;             // players maximum health is stored here
175
176 .float          teleport_time;  // don't back up
177
178 .float          armortype;              // save this fraction of incoming damage
179 .float          armorvalue;
180
181 .float          waterlevel;             // 0 = not in, 1 = feet, 2 = wast, 3 = eyes
182 .float          watertype;              // a contents value
183
184 .float          ideal_yaw;
185 .float          yaw_speed;
186
187 .entity         aiment;
188
189 .entity         goalentity;             // a movetarget or an enemy
190
191 .float          spawnflags;
192
193 .string         target;
194 .string         targetname;
195
196 // damage is accumulated through a frame. and sent as one single
197 // message, so the super shotgun doesn't generate huge messages
198 .float          dmg_take;
199 .float          dmg_save;
200 .entity         dmg_inflictor;
201
202 .entity         owner;          // who launched a missile
203 .vector         movedir;        // mostly for doors, but also used for waterjump
204
205 .string         message;                // trigger messages
206
207 .float          sounds;         // either a cd track number or sound number
208
209 .string         noise, noise1, noise2, noise3;  // contains names of wavs to play
210
211 //================================================
212 void            end_sys_fields;                 // flag for structure dumping
213 //================================================
214
215 /*
216 ==============================================================================
217
218                                 CONSTANT DEFINITIONS
219
220 ==============================================================================
221 */
222
223
224 //
225 // constants
226 //
227
228 float   FALSE                                   = 0;
229 float   TRUE                                    = 1;
230
231 // edict.flags
232 float   FL_FLY                                  = 1;
233 float   FL_SWIM                                 = 2;
234 float   FL_CLIENT                               = 8;    // set for all client edicts
235 float   FL_INWATER                              = 16;   // for enter / leave water splash
236 float   FL_MONSTER                              = 32;
237 float   FL_GODMODE                              = 64;   // player cheat
238 float   FL_NOTARGET                             = 128;  // player cheat
239 float   FL_ITEM                                 = 256;  // extra wide size for bonus items
240 float   FL_ONGROUND                             = 512;  // standing on something
241 float   FL_PARTIALGROUND                = 1024; // not all corners are valid
242 float   FL_WATERJUMP                    = 2048; // player jumping out of water
243 float   FL_JUMPRELEASED                 = 4096; // for jump debouncing
244
245 // edict.movetype values
246 float   MOVETYPE_NONE                   = 0;    // never moves
247 //float MOVETYPE_ANGLENOCLIP    = 1;
248 //float MOVETYPE_ANGLECLIP              = 2;
249 float   MOVETYPE_WALK                   = 3;    // players only
250 float   MOVETYPE_STEP                   = 4;    // discrete, not real time unless fall
251 float   MOVETYPE_FLY                    = 5;
252 float   MOVETYPE_TOSS                   = 6;    // gravity
253 float   MOVETYPE_PUSH                   = 7;    // no clip to world, push and crush
254 float   MOVETYPE_NOCLIP                 = 8;
255 float   MOVETYPE_FLYMISSILE             = 9;    // fly with extra size against monsters
256 float   MOVETYPE_BOUNCE                 = 10;
257 float   MOVETYPE_BOUNCEMISSILE  = 11;   // bounce with extra size
258
259 // edict.solid values
260 float   SOLID_NOT                               = 0;    // no interaction with other objects
261 float   SOLID_TRIGGER                   = 1;    // touch on edge, but not blocking
262 float   SOLID_BBOX                              = 2;    // touch on edge, block
263 float   SOLID_SLIDEBOX                  = 3;    // touch on edge, but not an onground
264 float   SOLID_BSP                               = 4;    // bsp clip, touch on edge, block
265
266 // range values
267 float   RANGE_MELEE                             = 0;
268 float   RANGE_NEAR                              = 1;
269 float   RANGE_MID                               = 2;
270 float   RANGE_FAR                               = 3;
271
272 // deadflag values
273
274 float   DEAD_NO                                 = 0;
275 float   DEAD_DYING                              = 1;
276 float   DEAD_DEAD                               = 2;
277 float   DEAD_RESPAWNABLE                = 3;
278 float   DEAD_RESPAWNING                 = 4; // dead, waiting for buttons to be released
279
280 // takedamage values
281
282 float   DAMAGE_NO                               = 0;
283 float   DAMAGE_YES                              = 1;
284 float   DAMAGE_AIM                              = 2;
285
286 // items
287 float   IT_AXE                                  = 4096;
288 float   IT_SHOTGUN                              = 1;
289 float   IT_SUPER_SHOTGUN                = 2;
290 float   IT_NAILGUN                              = 4;
291 float   IT_SUPER_NAILGUN                = 8;
292 float   IT_GRENADE_LAUNCHER             = 16;
293 float   IT_ROCKET_LAUNCHER              = 32;
294 float   IT_LIGHTNING                    = 64;
295 float   IT_EXTRA_WEAPON                 = 128;
296
297 float   IT_SHELLS                               = 256;
298 float   IT_NAILS                                = 512;
299 float   IT_ROCKETS                              = 1024;
300 float   IT_CELLS                                = 2048;
301
302 float   IT_ARMOR1                               = 8192;
303 float   IT_ARMOR2                               = 16384;
304 float   IT_ARMOR3                               = 32768;
305 float   IT_SUPERHEALTH                  = 65536;
306
307 float   IT_KEY1                                 = 131072;
308 float   IT_KEY2                                 = 262144;
309
310 float   IT_INVISIBILITY                 = 524288;
311 float   IT_INVULNERABILITY              = 1048576;
312 float   IT_SUIT                                 = 2097152;
313 float   IT_QUAD                                 = 4194304;
314
315 // point content values
316
317 float   CONTENT_EMPTY                   = -1;
318 float   CONTENT_SOLID                   = -2;
319 float   CONTENT_WATER                   = -3;
320 float   CONTENT_SLIME                   = -4;
321 float   CONTENT_LAVA                    = -5;
322 float   CONTENT_SKY                             = -6;
323
324 float   STATE_TOP               = 0;
325 float   STATE_BOTTOM    = 1;
326 float   STATE_UP                = 2;
327 float   STATE_DOWN              = 3;
328
329 vector  VEC_ORIGIN = '0 0 0';
330 vector  VEC_HULL_MIN = '-16 -16 -24';
331 vector  VEC_HULL_MAX = '16 16 32';
332
333 vector  VEC_HULL2_MIN = '-32 -32 -24';
334 vector  VEC_HULL2_MAX = '32 32 64';
335
336 // protocol bytes
337 float   SVC_TEMPENTITY          = 23;
338 float   SVC_KILLEDMONSTER       = 27;
339 float   SVC_FOUNDSECRET         = 28;
340 float   SVC_INTERMISSION        = 30;
341 float   SVC_FINALE                      = 31;
342 float   SVC_CDTRACK                     = 32;
343 float   SVC_SELLSCREEN          = 33;
344
345
346 float   TE_SPIKE                = 0;
347 float   TE_SUPERSPIKE   = 1;
348 float   TE_GUNSHOT              = 2;
349 float   TE_EXPLOSION    = 3;
350 float   TE_TAREXPLOSION = 4;
351 float   TE_LIGHTNING1   = 5;
352 float   TE_LIGHTNING2   = 6;
353 float   TE_WIZSPIKE             = 7;
354 float   TE_KNIGHTSPIKE  = 8;
355 float   TE_LIGHTNING3   = 9;
356 float   TE_LAVASPLASH   = 10;
357 float   TE_TELEPORT             = 11;
358
359 // sound channels
360 // channel 0 never willingly overrides
361 // other channels (1-7) allways override a playing sound on that channel
362 float   CHAN_AUTO               = 0;
363 float   CHAN_WEAPON             = 1;
364 float   CHAN_VOICE              = 2;
365 float   CHAN_ITEM               = 3;
366 float   CHAN_BODY               = 4;
367
368 float   ATTN_NONE               = 0;
369 float   ATTN_NORM               = 1;
370 float   ATTN_IDLE               = 2;
371 float   ATTN_STATIC             = 3;
372
373 // update types
374
375 float   UPDATE_GENERAL  = 0;
376 float   UPDATE_STATIC   = 1;
377 float   UPDATE_BINARY   = 2;
378 float   UPDATE_TEMP             = 3;
379
380 // entity effects
381
382 float   EF_BRIGHTFIELD  = 1;
383 float   EF_MUZZLEFLASH  = 2;
384 float   EF_BRIGHTLIGHT  = 4;
385 float   EF_DIMLIGHT     = 8;
386
387
388 // messages
389 float   MSG_BROADCAST   = 0;            // unreliable to all
390 float   MSG_ONE                 = 1;            // reliable to one (msg_entity)
391 float   MSG_ALL                 = 2;            // reliable to all
392 float   MSG_INIT                = 3;            // write to the init string
393
394 //================================================
395
396 //
397 // globals
398 //
399 float   movedist;
400 float   gameover;               // set when a rule exits
401
402 string  string_null;    // null string, nothing should be held here
403 //float empty_float;
404
405 entity  newmis;                 // launch_spike sets this after spawning it
406
407 entity  activator;              // the entity that activated a trigger or brush
408
409 entity  damage_attacker;        // set by T_Damage
410 float   framecount;
411
412 float           skill;
413
414 //================================================
415
416 //
417 // world fields (FIXME: make globals)
418 //
419 //.string               wad;
420 .string         map;
421 .float          worldtype;      // 0=medieval 1=metal 2=base
422
423 //================================================
424
425 .string         killtarget;
426
427 //
428 // quakeed fields
429 //
430 .float          light_lev;              // not used by game, but parsed by light util
431 .float          style;
432
433
434 //
435 // monster ai
436 //
437 .void()         th_stand;
438 .void()         th_walk;
439 .void()         th_run;
440 .float()        th_missile; // LordHavoc: changed from void() to float(), returns true if attacking
441 .void()         th_melee;
442 .void(entity attacker, float damage, float damgtype, string dethtype)           th_pain;
443 .void()         th_die;
444
445 .entity         oldenemy;               // mad at this player before taking damage
446
447 .float          speed;
448
449 .float  lefty;
450
451 .float  search_time;
452 .float  attack_state;
453
454 float   AS_STRAIGHT             = 1;
455 float   AS_SLIDING              = 2;
456 float   AS_MELEE                = 3;
457 float   AS_MISSILE              = 4;
458
459 //
460 // player only fields
461 //
462 //.float                walkframe;
463
464 .float          attack_finished;
465 .float          pain_finished;
466
467 .float          invincible_finished;
468 .float          invisible_finished;
469 .float          super_damage_finished;
470 .float          radsuit_finished;
471 .float          spawnshieldtime;
472
473 .float          invincible_time, invincible_sound;
474 .float          invisible_time, invisible_sound;
475 .float          super_time, super_sound;
476 .float          rad_time;
477 .float          fly_sound;
478
479 //.float                axhitme;
480
481 .float          show_hostile;   // set to time+0.2 whenever a client fires a
482                                                         // weapon or takes damage.  Used to alert
483                                                         // monsters that otherwise would let the player go
484 .float          jump_flag;              // player jump flag
485 .float          swim_flag;              // player swimming sound flag
486 .float          air_finished;   // when time > air_finished, start drowning
487 .float          bubble_count;   // keeps track of the number of bubbles
488 .string         deathtype;              // keeps track of how the player died
489
490 //
491 // object stuff
492 //
493 .string         mdl;
494 .vector         mangle;                 // angle at start
495
496 .vector         oldorigin;              // only used by secret door
497
498 .float          t_length, t_width;
499
500
501 //
502 // doors, etc
503 //
504 .vector         dest, dest1, dest2;
505 .float          wait;                   // time from firing to restarting
506 .float          delay;                  // time from activation to firing
507 .entity         trigger_field;  // door's trigger entity
508 .string         noise4;
509
510 //
511 // monsters
512 //
513 .float          pausetime;
514 .entity         movetarget;
515
516
517 //
518 // doors
519 //
520 .float          aflag;
521 .float          dmg;                    // damage done by door when hit
522
523 //
524 // misc
525 //
526 .float          cnt;                    // misc flag
527
528 //
529 // subs
530 //
531 .void()         think1;
532 //.vector               finaldest, finalangle;
533
534 //
535 // triggers
536 //
537 .float          count;                  // for counting triggers
538
539
540 //
541 // plats / doors / buttons
542 //
543 .float          lip;
544 .float          state;
545 .vector         pos1, pos2;             // top and bottom positions
546 .float          height;
547
548 //
549 // sounds
550 //
551 .float          waitmin, waitmax;
552 //.float                distance;
553 //.float                volume;
554
555
556
557
558 //===========================================================================
559
560
561 //
562 // builtin functions
563 //
564
565 void(vector ang)        makevectors             = #1;           // sets v_forward, etc globals
566 void(entity e, vector o) setorigin      = #2;
567 void(entity e, string m) setmodel       = #3;           // set movetype and solid first
568 void(entity e, vector min, vector max) setsize = #4;
569 // #5 was removed
570 void() break                                            = #6;
571 float() random                                          = #7;           // returns 0 - 1
572 void(entity e, float chan, string samp, float vol, float atten) sound = #8;
573 vector(vector v) normalize                      = #9;
574 void(string e, ...) error                               = #10;
575 void(string e, ...) objerror                            = #11;
576 float(vector v) vlen                            = #12;
577 float(vector v) vectoyaw                        = #13;
578 entity() spawn                                          = #14;
579 void(entity e) remove                           = #15;
580
581 // sets trace_* globals
582 // nomonsters can be:
583 // An entity will also be ignored for testing if forent == test,
584 // forent->owner == test, or test->owner == forent
585 // a forent of world is ignored
586 void(vector v1, vector v2, float nomonsters, entity forent) traceline = #16;
587
588 entity() checkclient                            = #17;  // returns a client to look for
589 entity(entity start, .string fld, string match) find = #18;
590 string(string s) precache_sound         = #19;
591 string(string s) precache_model         = #20;
592 void(entity client, string s, ...)stuffcmd = #21;
593 entity(vector org, float rad) findradius = #22;
594 void(string s, ...) bprint                              = #23;
595 void(entity client, string s, ...) sprint = #24;
596 void(string s, ...) dprint                              = #25;
597 string(float f) ftos                            = #26;
598 string(vector v) vtos                           = #27;
599 void() coredump                                         = #28;          // prints all edicts
600 void() traceon                                          = #29;          // turns statment trace on
601 void() traceoff                                         = #30;
602 void(entity e) eprint                           = #31;          // prints an entire edict
603 float(float yaw, float dist) walkmove   = #32;  // returns TRUE or FALSE
604 // #33 was removed
605 float() droptofloor= #34;       // TRUE if landed on floor
606 void(float style, string value) lightstyle = #35;
607 float(float v) rint                                     = #36;          // round to nearest int
608 float(float v) floor                            = #37;          // largest integer <= v
609 float(float v) ceil                                     = #38;          // smallest integer >= v
610 // #39 was removed
611 float(entity e) checkbottom                     = #40;          // true if self is on ground
612 float(vector v) pointcontents           = #41;          // returns a CONTENT_*
613 // #42 was removed
614 float(float f) fabs = #43;
615 vector(entity e, float speed) aim = #44;                // returns the shooting vector
616 float(string s) cvar = #45;                                             // return cvar.value
617 void(string s, ...) localcmd = #46;                                     // put string into local que
618 entity(entity e) nextent = #47;                                 // for looping through all ents
619 void(vector o, vector d, float color, float count) particle = #48;// start a particle effect
620 void() ChangeYaw = #49;                                         // turn towards self.ideal_yaw
621                                                                                         // at self.yaw_speed
622 // #50 was removed
623 vector(vector v) vectoangles                    = #51;
624
625 //
626 // direct client message generation
627 //
628 void(float to, float f) WriteByte               = #52;
629 void(float to, float f) WriteChar               = #53;
630 void(float to, float f) WriteShort              = #54;
631 void(float to, float f) WriteLong               = #55;
632 void(float to, float f) WriteCoord              = #56;
633 void(float to, float f) WriteAngle              = #57;
634 void(float to, string s, ...) WriteString       = #58;
635 void(float to, entity s) WriteEntity    = #59;
636
637 //
638 // broadcast client message generation
639 //
640
641 // void(float f) bWriteByte             = #59;
642 // void(float f) bWriteChar             = #60;
643 // void(float f) bWriteShort            = #61;
644 // void(float f) bWriteLong             = #62;
645 // void(float f) bWriteCoord            = #63;
646 // void(float f) bWriteAngle            = #64;
647 // void(string s) bWriteString  = #65;
648 // void(entity e) bWriteEntity = #66;
649
650 void(float step) movetogoal                             = #67;
651
652 string(string s) precache_file          = #68;  // no effect except for -copy
653 void(entity e) makestatic               = #69;
654 void(string s) changelevel = #70;
655
656 //#71 was removed
657
658 void(string var, string val) cvar_set = #72;    // sets cvar.value
659
660 void(entity client, string s, ...) centerprint = #73;   // sprint, but in middle
661
662 void(vector pos, string samp, float vol, float atten) ambientsound = #74;
663
664 string(string s) precache_model2        = #75;          // registered version only
665 string(string s) precache_sound2        = #76;          // registered version only
666 string(string s) precache_file2         = #77;          // registered version only
667
668 void(entity e) setspawnparms            = #78;          // set parm1... to the
669                                                                                                 // values at level start
670                                                                                                 // for coop respawn
671
672 //============================================================================
673
674 //
675 // subs.qc
676 //
677 void(vector tdest, float tspeed, void() func) SUB_CalcMove;
678 void(entity ent, vector tdest, float tspeed, void() func) SUB_CalcMoveEnt;
679 void(vector destangle, float tspeed, void() func) SUB_CalcAngleMove;
680 void()  SUB_CalcMoveDone;
681 void() SUB_CalcAngleMoveDone;
682 void() SUB_Null;
683 void() SUB_UseTargets;
684 void() SUB_Remove;
685
686 //
687 //      combat.qc
688 //
689
690
691
692 float(entity targ, entity inflictor) CanDamage;
693
694
695
696
697
698 //void(vector org, entity en, vector dir, float holetype) newbullethole;
699
700
701 //void(float msg, vector a) WriteVec =
702 //{
703 //      WriteCoord(msg, a_x);
704 //      WriteCoord(msg, a_y);
705 //      WriteCoord(msg, a_z);
706 //};
707
708 float() crandom =
709 {
710         return 2*(random() - 0.5);
711 };
712
713 vector(vector m1, vector m2) randompos =
714 {
715         local vector v;
716         m2 = m2 - m1;
717         v_x = m2_x * random() + m1_x;
718         v_y = m2_y * random() + m1_y;
719         v_z = m2_z * random() + m1_z;
720         return  v;
721 };
722
723 // LordHavoc: made this a builtin function
724 /*
725 vector() randomvec =
726 {
727         local vector v;
728         do
729         {
730                 v_x = random() - 0.5; // scaled up in the return()
731                 v_y = random() - 0.5;
732                 v_z = random() - 0.5;
733         }
734         while (vlen(v) > 0.25);
735         return(v * 2);
736 };
737 */
738
739 vector() randomvec2 =
740 {
741         local vector v;
742         v_x = random() - 0.5; // scale doesn't matter because it's normalized
743         v_y = random() - 0.5;
744         v_z = random() - 0.5;
745         v = normalize(v);
746         return(v);
747 };
748
749 vector() randomdirvec =
750 {
751         local vector v;
752         do
753         {
754                 do
755                 {
756                         v_x = random() - 0.5;
757                         v_y = random() - 0.5;
758                         v_z = random() - 0.5;
759                 }
760                 while (vlen(v) > 0.25);
761         }
762         while (vlen(v) < 0.1);
763         return normalize(v);
764 };
765
766 /*
767 float(float a) sqrt = // now this IS silly (using vlen to do square root)
768 {
769         local vector v;
770         v_x = a;
771         return (vlen(v));
772 };
773 */
774
775 // returns an empty point near the location if it's in a solid
776 // (useful for explosions)
777 vector (vector org) findbetterlocation =
778 {
779         local vector v;
780         local float c;
781         if (pointcontents(org) != CONTENT_SOLID)
782                 return org;
783         c = 0;
784         while (c < 20)
785         {
786                 c = c + 1;
787 // 4.1 to get it to choose +2 occasionally (rather than a 1 in 32768 chance)
788                 v_x = org_x + random() * 4.1 - 2;
789                 v_y = org_y + random() * 4.1 - 2;
790                 v_z = org_z + random() * 4.1 - 2;
791                 if (pointcontents(v) != CONTENT_SOLID)
792                         return v;
793         }
794         return org; // failed to find an empty point
795 };
796
797 // adjusts the entity's origin to move it out of a solid
798 // (useful for projectiles with no size, so they explode in open air)
799 // note this is mostly useless on entities bigger than that
800 // (unless they happen to have their origin on the surface of a wall)
801 void (entity e) findbetterlocation2 =
802 {
803         local vector v, org;
804         local float c;
805         if (pointcontents(e.origin) != CONTENT_SOLID)
806                 return;
807         org = e.origin;
808         c = 0;
809         while (c < 20)
810         {
811                 c = c + 1;
812 // 4.1 to get it to choose 4 occasionally (rather than a 1 in 32768 chance)
813                 v_x = org_x + random() * 4.1 - 2;
814                 v_y = org_y + random() * 4.1 - 2;
815                 v_z = org_z + random() * 4.1 - 2;
816                 if (pointcontents(v) != CONTENT_SOLID)
817                 {
818                         setorigin(e, v);
819                         return;
820                 }
821         }
822         return; // failed to find an empty point
823 };
824
825 // returns a point at least 12 units away from walls
826 // (useful for explosion animations, although the blast is performed where it really happened)
827 vector (vector org) findbetterlocation3 =
828 {
829         local vector v2;
830         traceline(org, org - '12 0 0' , TRUE, world);if (trace_fraction < 1) {v2 = trace_endpos;traceline(v2, v2 + '12 0 0' , TRUE, world);if (trace_fraction >= 1) org = v2 + '12 0 0' ;}
831         traceline(org, org - '-12 0 0', TRUE, world);if (trace_fraction < 1) {v2 = trace_endpos;traceline(v2, v2 + '-12 0 0', TRUE, world);if (trace_fraction >= 1) org = v2 + '-12 0 0';}
832         traceline(org, org - '0 12 0' , TRUE, world);if (trace_fraction < 1) {v2 = trace_endpos;traceline(v2, v2 + '0 12 0' , TRUE, world);if (trace_fraction >= 1) org = v2 + '0 12 0' ;}
833         traceline(org, org - '0 -12 0', TRUE, world);if (trace_fraction < 1) {v2 = trace_endpos;traceline(v2, v2 + '0 -12 0', TRUE, world);if (trace_fraction >= 1) org = v2 + '0 -12 0';}
834         traceline(org, org - '0 0 12' , TRUE, world);if (trace_fraction < 1) {v2 = trace_endpos;traceline(v2, v2 + '0 0 12' , TRUE, world);if (trace_fraction >= 1) org = v2 + '0 0 12' ;}
835         traceline(org, org - '0 0 -12', TRUE, world);if (trace_fraction < 1) {v2 = trace_endpos;traceline(v2, v2 + '0 0 -12', TRUE, world);if (trace_fraction >= 1) org = v2 + '0 0 -12';}
836         return org;
837 };
838
839 vector (vector org) findbetterlocation4 =
840 {
841         local vector v2;
842         traceline(org, org - '5 0 0' , TRUE, world);if (trace_fraction < 1) {v2 = trace_endpos;traceline(v2, v2 + '5 0 0' , TRUE, world);if (trace_fraction >= 1) org = v2 + '5 0 0' ;}
843         traceline(org, org - '-5 0 0', TRUE, world);if (trace_fraction < 1) {v2 = trace_endpos;traceline(v2, v2 + '-5 0 0', TRUE, world);if (trace_fraction >= 1) org = v2 + '-5 0 0';}
844         traceline(org, org - '0 5 0' , TRUE, world);if (trace_fraction < 1) {v2 = trace_endpos;traceline(v2, v2 + '0 5 0' , TRUE, world);if (trace_fraction >= 1) org = v2 + '0 5 0' ;}
845         traceline(org, org - '0 -5 0', TRUE, world);if (trace_fraction < 1) {v2 = trace_endpos;traceline(v2, v2 + '0 -5 0', TRUE, world);if (trace_fraction >= 1) org = v2 + '0 -5 0';}
846         traceline(org, org - '0 0 5' , TRUE, world);if (trace_fraction < 1) {v2 = trace_endpos;traceline(v2, v2 + '0 0 5' , TRUE, world);if (trace_fraction >= 1) org = v2 + '0 0 5' ;}
847         traceline(org, org - '0 0 -5', TRUE, world);if (trace_fraction < 1) {v2 = trace_endpos;traceline(v2, v2 + '0 0 -5', TRUE, world);if (trace_fraction >= 1) org = v2 + '0 0 -5';}
848         return org;
849 };
850
851 /*
852 void(vector v1, vector v2, vector m1, vector m2) lh_traceagainstbox =
853 {
854         local vector b, dir, delta, dironx, dirony, dironz;
855         local float completedist, r;
856         trace_endpos = v2;
857         trace_fraction = 1;
858         if (vlen(v2 - v1) < 0.1) // too short, might do a divide by zero
859                 return;
860         // throw out the complete misses
861         if (v1_x <= m1_x) if (v2_x <= m1_x) return;
862         if (v1_x >= m2_x) if (v2_x >= m2_x) return;
863         if (v1_y <= m1_y) if (v2_y <= m1_y) return;
864         if (v1_y >= m2_y) if (v2_y >= m2_y) return;
865         if (v1_z <= m1_z) if (v2_z <= m1_z) return;
866         if (v1_z >= m2_z) if (v2_z >= m2_z) return;
867         // starting inside the box?
868         if (v1_x >= m1_x) if (v1_x < m2_x) if (v1_y >= m1_y) if (v1_y < m2_y) if (v1_z >= m1_z) if (v1_z < m2_z) return;
869         delta = v2 - v1;
870         dir = normalize(delta);
871         completedist = vlen(v2 - v1);
872         if (delta_x < -0.001 || delta_x > 0.001)
873         {
874                 dironx_x = 1;if (delta_x < 0) dironx_x = -1;
875                 dironx_y = delta_y / delta_x;
876                 dironx_z = delta_z / delta_x;
877         }
878         else
879         {
880                 dironx_x = 1;if (delta_x < 0) dironx_x = -1;
881                 dironx_y = 0;
882                 dironx_z = 0;
883         }
884         if (delta_y < -0.001 || delta_y > 0.001)
885         {
886                 dirony_x = delta_x / delta_y;
887                 dirony_y = 1;if (delta_y < 0) dirony_y = -1;
888                 dirony_z = delta_z / delta_y;
889         }
890         else
891         {
892                 dirony_x = 0;
893                 dirony_y = 1;if (delta_y < 0) dirony_y = -1;
894                 dirony_z = 0;
895         }
896         if (delta_z < -0.001 || delta_z > 0.001)
897         {
898                 dironz_x = delta_x / delta_z;
899                 dironz_y = delta_y / delta_z;
900                 dironz_z = 1;if (delta_z < 0) dironz_z = -1;
901         }
902         else
903         {
904                 dironz_x = 0;
905                 dironz_y = 0;
906                 dironz_z = 1;if (delta_z < 0) dironz_z = -1;
907         }
908         b = v1;
909         r = floor(random() * 1000);
910         if (dir_x > 0)
911         {
912                 if (b_x < m1_x)
913                 {
914                         b = b + dironx * (m1_x - b_x);
915                         trace_fraction = vlen(b - v1) / completedist;
916                 }
917         }
918         else
919         {
920                 if (b_x > m2_x)
921                 {
922                         b = b - dironx * (m2_x - b_x);
923                         trace_fraction = vlen(b - v1) / completedist;
924                 }
925         }
926         trace_endpos = b;
927         if (trace_fraction > 1) trace_fraction = 1;
928         if (dir_y > 0)
929         {
930                 if (b_y < m1_y)
931                 {
932                         b = b + dirony * (m1_y - b_y);
933                         trace_fraction = vlen(b - v1) / completedist;
934                 }
935         }
936         else
937         {
938                 if (b_y > m2_y)
939                 {
940                         b = b - dirony * (m2_y - b_y);
941                         trace_fraction = vlen(b - v1) / completedist;
942                 }
943         }
944         trace_endpos = b;
945         if (trace_fraction > 1) trace_fraction = 1;
946         if (dir_z > 0)
947         {
948                 if (b_z < m1_z)
949                 {
950                         b = b + dironz * (m1_z - b_z);
951                         trace_fraction = vlen(b - v1) / completedist;
952                 }
953         }
954         else
955         {
956                 if (b_z > m2_z)
957                 {
958                         b = b - dironz * (m2_z - b_z);
959                         trace_fraction = vlen(b - v1) / completedist;
960                 }
961         }
962         trace_endpos = b;
963         if (trace_fraction > 1) trace_fraction = 1;
964 };
965 */
966
967 .float cantrigger;
968
969 void(float n) bprintfloat =
970 {
971         local string s;
972         s = ftos(n);
973         bprint(s);
974 };
975
976 void(vector n) bprintvector =
977 {
978         local string s;
979         s = vtos(n);
980         bprint(s);
981 };
982
983 void(float n) dprintfloat =
984 {
985         local string s;
986         s = ftos(n);
987         dprint(s);
988 };
989
990 void(vector n) dprintvector =
991 {
992         local string s;
993         s = vtos(n);
994         dprint(s);
995 };
996
997 string deathstring1, deathstring2, deathstring3, deathstring4;
998
999 float DTYPE_OTHER = 0;
1000 float DTYPE_PLAYER = 1;
1001 float DTYPE_WORLD = 2;
1002 float DTYPE_TEAMKILL = 3;
1003 float DTYPE_SUICIDE = 4;
1004
1005 void(entity targ, entity attacker, string dmsg, float dtype) Obituary_Generic =
1006 {
1007         deathstring1 = targ.netname;
1008         deathstring2 = dmsg;
1009         deathstring3 = "";
1010         deathstring4 = "";
1011 };
1012
1013 // called by various obit functions to give a generic message for cases they do not handle
1014 void(entity targ, entity attacker, string dmsg, float dtype) Obituary_Fallback =
1015 {
1016         if (dtype == DTYPE_OTHER)
1017         {
1018                 deathstring1 = targ.netname;
1019                 deathstring2 = dmsg;
1020                 deathstring3 = "";
1021                 deathstring4 = "";
1022         }
1023         else if (dtype == DTYPE_SUICIDE)
1024         {
1025                 deathstring1 = targ.netname;
1026                 deathstring2 = " became bored with life";
1027                 deathstring3 = "";
1028                 deathstring4 = "";
1029         }
1030         else if (dtype == DTYPE_PLAYER)
1031         {
1032                 deathstring1 = targ.netname;
1033                 deathstring2 = " was killed by ";
1034                 deathstring3 = attacker.netname;
1035                 deathstring4 = "";
1036         }
1037         else if (dtype == DTYPE_TEAMKILL)
1038         {
1039                 deathstring1 = targ.netname;
1040                 deathstring2 = " was mowed down by his teammate ";
1041                 deathstring3 = attacker.netname;
1042                 deathstring4 = "";
1043         }
1044         else if (dtype == DTYPE_WORLD)
1045         {
1046                 deathstring1 = targ.netname;
1047                 deathstring2 = " died of unknown causes";
1048                 deathstring3 = "";
1049                 deathstring4 = "";
1050         }
1051 };
1052
1053 float GAME_QUAKE = 0;
1054 float GAME_NEXUIZ = 1;
1055 float game;
1056
1057 float darkmode;
1058
1059 float IT_WEAPON1                      = 4096;
1060 float IT_WEAPON2                      = 1;
1061 float IT_WEAPON3                      = 2;
1062 float IT_WEAPON4                      = 4;
1063 float IT_WEAPON5                      = 8;
1064 float IT_WEAPON6                      = 16;
1065 float IT_WEAPON7                      = 32;
1066 float IT_WEAPON8                      = 64;
1067 float IT_WEAPON9                      = 128;
1068 float IT_WEAPON10                     = 8388608;
1069
1070 // see modecheck.qc for deathmatch and teamplay settings
1071
1072 // added for Dark Places
1073 float CHAN_SPEECH             = 5;
1074 float CHAN_FOOT               = 6;
1075 float CHAN_WEAPON2            = 7;
1076
1077 // .gravity field added in Quake 1.07 (Scourge of Armagon)
1078 .float gravity;
1079
1080 .float          bodyhealth;             // used by corpse code
1081 .float          iscorpse;               // used by corpse code
1082
1083 .vector dest, dest1, dest2, dest3, dest4;//, dest5;
1084
1085
1086 .entity flame;                  // the flame burning this thing
1087
1088 .float doobits;         // set if this should do obit on death
1089
1090 //.vector bodymins, bodymaxs, headmins, headmaxs;
1091
1092 .vector rotate;
1093 .string group;
1094
1095 // counts of how many keys this player/bot has
1096 .float keys_silver;
1097 .float keys_gold;
1098
1099 .float havocattack;
1100 .float havocpickup;
1101 .float(entity player, entity item) pickupevalfunc; // returns rating for item considering player's condition (don't pick up health if it's not needed, etc)
1102 .float shoulddodge;
1103 .float dangerrating;
1104
1105 // called whenever damage is done, if not supplied there is no visible effect.
1106 .void(vector org, float bodydamage, float armordamage, vector vel, float damgtype) bleedfunc;
1107
1108 // several counters
1109 .float count1, count2, count3, count4, count5, count6, cnt1, cnt2;
1110
1111 .void(entity t, entity a, string m, float dtyp) obitfunc1;
1112 .entity realowner;
1113
1114 float maxclients; // set by worldspawn code
1115 float numdecors;
1116 float maxdecors;
1117 .float createdtime;
1118 .void() th_gib;
1119
1120 //void(vector org, entity en, vector dir, float splattype, float importance) newbloodsplat;
1121 void(vector org, float bodydamage, float armordamage, vector vel, float damgtype) genericbleedfunc;
1122
1123
1124
1125
1126 // damage stuff
1127
1128 void(entity targ, entity inflictor, entity attacker, float damage, float bdamage, string dt, float damgtype, vector damgpoint, vector force, void(entity t, entity a, string m, float dtyp) obitfunc) T_Damage;
1129 void(entity inflictor, entity attacker, float damage, float force, float radius, entity ignore, string dethtype, float damgtype, void(entity t, entity a, string m, float dtyp) obitfunc) T_RadiusDamage;
1130
1131
1132 // resistances to 4 kinds of damage:
1133 .float resist_bullet, resist_explosive, resist_energy, resist_fire, resist_ice, resist_axe;
1134 // every monster can have resistances
1135 // note: -1 means immune, as 0.0 can't be used
1136
1137 // kill message
1138 .string deathtype;
1139 // copied from .deathtype for the attacker
1140 // a map entity can gain alot of meaning by
1141 // adding a kill message in the deathtype key
1142 // such as ' was chopped to bits'
1143 // or ' fell into the abyss'
1144 // if you set a deathtype for a monster
1145 // in a map key it will override the normal
1146 // kill message for that monster
1147 // so you could have some hell knights that
1148 // say ' was slain by one of the palace guards'
1149 // and many other ways to add meaning to a map
1150 .string deathmsg;
1151
1152 .float regenthink; // next time player will regen some health
1153 .float isdecor;
1154 .float radiusdamage_amount; // damage counter
1155 .vector radiusdamage_force; // direction and power of blast kick
1156 .float radiusdamage_hit; // 1 if it was hit, reset to 0 afterward
1157 .vector radiusdamage_lasthit; // location
1158 .float radiusdamage_ownerdamagescale; // if set on inflictor this will scale damage to owner (overriding default of 0.5)
1159 vector raddamage_lasthit;
1160
1161 .float frozen;
1162 .float thawtime;
1163 .float thawedeffects;
1164 .void() thawedtouch;
1165 .float thawedmovetype;
1166 .void() thawedthink;
1167 .float thawedthinkdelay;
1168
1169 .void() knockedloosefunc; // called when kinetically disturbed
1170 .float forcescale; // used for damage force calculations (shambler has lower forcescale than player for instance)
1171
1172 // how much bleeding 'matters' to this entity, a percentage between
1173 // bodydamage (-1 = 0% as 0 doesn't work) and healthdamage (1.0 = 100%)
1174 // for instance a player is 100% and a zombie is 0% (bleeding doesn't matter)
1175 .float bleedratio;
1176 .float(entity e, float healthdamage, float damage, float damgtype, string dethtype) damagemodifier;
1177
1178 .void() th_gib;
1179
1180 .float health; // if this goes below 1 the thing is dead
1181 .float bodyhealth; // used for gibbing
1182 .float healthregen; // regenerate this much health per second
1183 .float healthlostthisframe; // reset by iscreature code each frame
1184
1185 // adjustable monster damage settings
1186 float monsterdamagescale;
1187 float monsterresistancescale;
1188 // adjustable player damage settings
1189 float playerdamagescale;
1190
1191 void(entity targ, entity attacker, string dmsg, float dtype, void(entity t, entity a, string m, float dtyp) obitfunc) ClientObituary;
1192
1193 void() monster_death_use;