Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
sv_sandbox.qc File Reference
#include "sv_sandbox.qh"
#include <server/intermission.qh>
Include dependency graph for sv_sandbox.qc:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define SANDBOX_GETARG   arg = argv(++argv_num);

Functions

 MUTATOR_HOOKFUNCTION (sandbox, SV_ParseClientCommand)
 MUTATOR_HOOKFUNCTION (sandbox, SV_StartFrame)
void sandbox_Database_Load ()
void sandbox_Database_Save ()
void sandbox_ObjectAttach_Remove (entity e)
void sandbox_ObjectAttach_Set (entity e, entity parent, string s)
entity sandbox_ObjectEdit_Get (entity this, float permissions)
void sandbox_ObjectEdit_Scale (entity e, float f)
void sandbox_ObjectFunction_Think (entity this)
void sandbox_ObjectFunction_Touch (entity this, entity toucher)
entity sandbox_ObjectPort_Load (entity this, string s, float database)
string sandbox_ObjectPort_Save (entity e, bool database)
void sandbox_ObjectRemove (entity e)
entity sandbox_ObjectSpawn (entity this, float database)

Variables

string autocvar_g_sandbox
float autocvar_g_sandbox_editor_distance_edit
float autocvar_g_sandbox_editor_distance_spawn
float autocvar_g_sandbox_editor_flood
int autocvar_g_sandbox_editor_free
int autocvar_g_sandbox_editor_maxobjects
int autocvar_g_sandbox_info
float autocvar_g_sandbox_object_material_velocity_factor
float autocvar_g_sandbox_object_material_velocity_min
float autocvar_g_sandbox_object_scale_max
float autocvar_g_sandbox_object_scale_min
bool autocvar_g_sandbox_readonly
bool autocvar_g_sandbox_storage_autoload
float autocvar_g_sandbox_storage_autosave
string autocvar_g_sandbox_storage_name
float autosave_time
IntrusiveList g_sandbox_objects
string material
entity object_attach
float object_count
float object_flood
float old_movetype
float old_solid
string port_string [MAX_STORAGE_ATTACHMENTS]
float touch_timer

Macro Definition Documentation

◆ SANDBOX_GETARG

#define SANDBOX_GETARG   arg = argv(++argv_num);

Referenced by sandbox_ObjectPort_Load().

Function Documentation

◆ MUTATOR_HOOKFUNCTION() [1/2]

MUTATOR_HOOKFUNCTION ( sandbox ,
SV_ParseClientCommand  )

Definition at line 454 of file sv_sandbox.qc.

455{
456 if(MUTATOR_RETURNVALUE) // command was already handled?
457 return;
458
459 entity player = M_ARGV(0, entity);
460 string cmd_name = M_ARGV(1, string);
461 int cmd_argc = M_ARGV(2, int);
462
463 if(cmd_name == "g_sandbox")
464 {
465 if(autocvar_g_sandbox_readonly || MUTATOR_CALLHOOK(Sandbox_EditAllowed, player))
466 {
467 print_to(player, "^2SANDBOX - INFO: ^7Sandbox mode is active, but in read-only mode. Sandbox commands cannot be used");
468 return true;
469 }
470 if(cmd_argc < 2)
471 {
472 print_to(player, "^2SANDBOX - INFO: ^7Sandbox mode is active. For usage information, type 'sandbox help'");
473 return true;
474 }
475
476 switch(argv(1))
477 {
478 entity e;
479 int j;
480 string s;
481
482 // ---------------- COMMAND: HELP ----------------
483 case "help":
484 print_to(player, "You can use the following sandbox commands:");
485 print_to(player, "^7\"^2object_spawn ^3models/foo/bar.md3^7\" spawns a new object in front of the player, and gives it the specified model");
486 print_to(player, "^7\"^2object_remove^7\" removes the object the player is looking at. Players can only remove their own objects");
487 print_to(player, "^7\"^2object_duplicate ^3value^7\" duplicates the object, if the player has copying rights over the original");
488 print_to(player, "^3copy value ^7- copies the properties of the object to the specified client cvar");
489 print_to(player, "^3paste value ^7- spawns an object with the given properties. Properties or cvars must be specified as follows; eg1: \"0 1 2 ...\", eg2: \"$cl_cvar\"");
490 print_to(player, "^7\"^2object_attach ^3property value^7\" attaches one object to another. Players can only attach their own objects");
491 print_to(player, "^3get ^7- selects the object you are facing as the object to be attached");
492 print_to(player, "^3set value ^7- attaches the previously selected object to the object you are facing, on the specified bone");
493 print_to(player, "^3remove ^7- detaches all objects from the object you are facing");
494 print_to(player, "^7\"^2object_edit ^3property value^7\" edits the given property of the object. Players can only edit their own objects");
495 print_to(player, "^3skin value ^7- changes the skin of the object");
496 print_to(player, "^3alpha value ^7- sets object transparency");
497 print_to(player, "^3colormod \"value_x value_y value_z\" ^7- main object color");
498 print_to(player, "^3glowmod \"value_x value_y value_z\" ^7- glow object color");
499 print_to(player, "^3frame value ^7- object animation frame, for self-animated models");
500 print_to(player, "^3scale value ^7- changes object scale. 0.5 is half size and 2 is double size");
501 print_to(player, "^3solidity value ^7- object collisions, 0 = non-solid, 1 = solid");
502 print_to(player, "^3physics value ^7- object physics, 0 = static, 1 = movable, 2 = physical");
503 print_to(player, "^3force value ^7- amount of force applied to objects that are shot");
504 print_to(player, "^3material value ^7- sets the material of the object. Default materials are: metal, stone, wood, flesh");
505 print_to(player, "^7\"^2object_claim^7\" sets the player as the owner of the object, if they have the right to edit it");
506 print_to(player, "^7\"^2object_info ^3value^7\" shows public information about the object");
507 print_to(player, "^3object ^7- prints general information about the object, such as owner and creation / editing date");
508 print_to(player, "^3mesh ^7- prints information about the object's mesh, including skeletal bones");
509 print_to(player, "^3attachments ^7- prints information about the object's attachments");
510 print_to(player, "^7The ^1drag object ^7key can be used to grab and carry objects. Players can only grab their own objects");
511 return true;
512
513 // ---------------- COMMAND: OBJECT, SPAWN ----------------
514 case "object_spawn":
515 if(time < player.object_flood)
516 {
517 print_to(player, strcat("^1SANDBOX - WARNING: ^7Flood protection active. Please wait ^3", ftos(player.object_flood - time), " ^7seconds beofore spawning another object"));
518 return true;
519 }
520 player.object_flood = time + autocvar_g_sandbox_editor_flood;
522 {
523 print_to(player, strcat("^1SANDBOX - WARNING: ^7Cannot spawn any more objects. Up to ^3", ftos(autocvar_g_sandbox_editor_maxobjects), " ^7objects may exist at a time"));
524 return true;
525 }
526 if(cmd_argc < 3)
527 {
528 print_to(player, "^1SANDBOX - WARNING: ^7Attempted to spawn an object without specifying a model. Please specify the path to your model file after the 'object_spawn' command");
529 return true;
530 }
531 if (!(fexists(argv(2))))
532 {
533 print_to(player, "^1SANDBOX - WARNING: ^7Attempted to spawn an object with a non-existent model. Make sure the path to your model file is correct");
534 return true;
535 }
536
537 e = sandbox_ObjectSpawn(player, false);
538 precache_model(argv(2));
539 _setmodel(e, argv(2));
540
542 LOG_INFO("^3SANDBOX - SERVER: ^7", player.netname, " spawned an object at origin ^3", vtos(e.origin));
543 return true;
544
545 // ---------------- COMMAND: OBJECT, REMOVE ----------------
546 case "object_remove":
547 e = sandbox_ObjectEdit_Get(player, true);
548 if(e != NULL)
549 {
551 LOG_INFO("^3SANDBOX - SERVER: ^7", player.netname, " removed an object at origin ^3", vtos(e.origin));
553 return true;
554 }
555
556 print_to(player, "^1SANDBOX - WARNING: ^7Object could not be removed. Make sure you are facing an object that you have edit rights over");
557 return true;
558
559 // ---------------- COMMAND: OBJECT, DUPLICATE ----------------
560 case "object_duplicate":
561 switch(argv(2))
562 {
563 case "copy":
564 // copies customizable properties of the selected object to the clipboard cvar
565 e = sandbox_ObjectEdit_Get(player, autocvar_g_sandbox_editor_free); // can we copy objects we can't edit?
566 if(e != NULL)
567 {
568 s = sandbox_ObjectPort_Save(e, false);
569 s = strreplace("\"", "\\\"", s);
570 stuffcmd(player, strcat("set ", argv(3), " \"", s, "\""));
571
572 print_to(player, "^2SANDBOX - INFO: ^7Object copied to clipboard");
573 return true;
574 }
575 print_to(player, "^1SANDBOX - WARNING: ^7Object could not be copied. Make sure you are facing an object that you have copy rights over");
576 return true;
577
578 case "paste":
579 // spawns a new object using the properties in the player's clipboard cvar
580 if(time < player.object_flood)
581 {
582 print_to(player, strcat("^1SANDBOX - WARNING: ^7Flood protection active. Please wait ^3", ftos(player.object_flood - time), " ^7seconds beofore spawning another object"));
583 return true;
584 }
585 player.object_flood = time + autocvar_g_sandbox_editor_flood;
586 if(argv(3) == "") // no object in clipboard
587 {
588 print_to(player, "^1SANDBOX - WARNING: ^7No object in clipboard. You must copy an object before you can paste it");
589 return true;
590 }
592 {
593 print_to(player, strcat("^1SANDBOX - WARNING: ^7Cannot spawn any more objects. Up to ^3", ftos(autocvar_g_sandbox_editor_maxobjects), " ^7objects may exist at a time"));
594 return true;
595 }
596 e = sandbox_ObjectPort_Load(player, argv(3), false);
597
598 print_to(player, "^2SANDBOX - INFO: ^7Object pasted successfully");
600 LOG_INFO("^3SANDBOX - SERVER: ^7", player.netname, " pasted an object at origin ^3", vtos(e.origin));
601 return true;
602 }
603 return true;
604
605 // ---------------- COMMAND: OBJECT, ATTACH ----------------
606 case "object_attach":
607 switch(argv(2))
608 {
609 case "get":
610 // select e as the object as meant to be attached
611 e = sandbox_ObjectEdit_Get(player, true);
612 if(e != NULL)
613 {
614 player.object_attach = e;
615 print_to(player, "^2SANDBOX - INFO: ^7Object selected for attachment");
616 return true;
617 }
618 print_to(player, "^1SANDBOX - WARNING: ^7Object could not be selected for attachment. Make sure you are facing an object that you have edit rights over");
619 return true;
620 case "set":
621 if(player.object_attach == NULL)
622 {
623 print_to(player, "^1SANDBOX - WARNING: ^7No object selected for attachment. Please select an object to be attached first.");
624 return true;
625 }
626
627 // attaches the previously selected object to e
628 e = sandbox_ObjectEdit_Get(player, true);
629 if(e != NULL)
630 {
631 sandbox_ObjectAttach_Set(player.object_attach, e, argv(3));
632 player.object_attach = NULL; // object was attached, no longer keep it scheduled for attachment
633 print_to(player, "^2SANDBOX - INFO: ^7Object attached successfully");
635 LOG_INFO("^3SANDBOX - SERVER: ^7", player.netname, " attached objects at origin ^3", vtos(e.origin));
636 return true;
637 }
638 print_to(player, "^1SANDBOX - WARNING: ^7Object could not be attached to the parent. Make sure you are facing an object that you have edit rights over");
639 return true;
640 case "remove":
641 // removes e if it was attached
642 e = sandbox_ObjectEdit_Get(player, true);
643 if(e != NULL)
644 {
646 print_to(player, "^2SANDBOX - INFO: ^7Child objects detached successfully");
648 LOG_INFO("^3SANDBOX - SERVER: ^7", player.netname, " detached objects at origin ^3", vtos(e.origin));
649 return true;
650 }
651 print_to(player, "^1SANDBOX - WARNING: ^7Child objects could not be detached. Make sure you are facing an object that you have edit rights over");
652 return true;
653 }
654 return true;
655
656 // ---------------- COMMAND: OBJECT, EDIT ----------------
657 case "object_edit":
658 if(argv(2) == "")
659 {
660 print_to(player, "^1SANDBOX - WARNING: ^7Too few parameters. You must specify a property to edit");
661 return true;
662 }
663
664 e = sandbox_ObjectEdit_Get(player, true);
665 if(e != NULL)
666 {
667 switch(argv(2))
668 {
669 case "skin":
670 e.skin = stof(argv(3));
671 break;
672 case "alpha":
673 e.alpha = stof(argv(3));
674 break;
675 case "color_main":
676 e.colormod = stov(argv(3));
677 break;
678 case "color_glow":
679 e.glowmod = stov(argv(3));
680 break;
681 case "frame":
682 e.frame = stof(argv(3));
683 break;
684 case "scale":
686 break;
687 case "solidity":
688 switch(argv(3))
689 {
690 case "0": // non-solid
691 e.solid = SOLID_TRIGGER;
692 break;
693 case "1": // solid
694 e.solid = SOLID_BBOX;
695 break;
696 default:
697 break;
698 }
699 case "physics":
700 switch(argv(3))
701 {
702 case "0": // static
704 break;
705 case "1": // movable
707 break;
708 case "2": // physical
710 break;
711 default:
712 break;
713 }
714 break;
715 case "force":
716 e.damageforcescale = stof(argv(3));
717 break;
718 case "material":
719 strfree(e.material);
720 if(argv(3))
721 {
722 for (j = 1; j <= 5; ++j) // precache material sounds, 5 in total
723 precache_sound(strcat("object/impact_", argv(3), "_", ftos(j), ".wav"));
724 e.material = strzone(argv(3));
725 }
726 else
727 e.material = string_null; // no material
728 break;
729 default:
730 print_to(player, "^1SANDBOX - WARNING: ^7Invalid object property. For usage information, type 'sandbox help'");
731 return true;
732 }
733
734 // update last editing time
735 strcpy(e.message2, strftime(true, "%d-%m-%Y %H:%M:%S"));
736
738 LOG_INFO("^3SANDBOX - SERVER: ^7", player.netname, " edited property ^3", argv(2), " ^7of an object at origin ^3", vtos(e.origin));
739 return true;
740 }
741
742 print_to(player, "^1SANDBOX - WARNING: ^7Object could not be edited. Make sure you are facing an object that you have edit rights over");
743 return true;
744
745 // ---------------- COMMAND: OBJECT, CLAIM ----------------
746 case "object_claim":
747 // if the player can edit an object but is not its owner, this can be used to claim that object
748 if(player.crypto_idfp == "")
749 {
750 print_to(player, "^1SANDBOX - WARNING: ^7You do not have a player UID, and cannot claim objects");
751 return true;
752 }
753 e = sandbox_ObjectEdit_Get(player, true);
754 if(e != NULL)
755 {
756 // update the owner's name
757 // Do this before checking if you're already the owner and skipping if such, so we
758 // also update the player's nickname if they changed it (but has the same player UID)
759 if(e.netname != player.netname)
760 {
761 strcpy(e.netname, player.netname);
762 print_to(player, "^2SANDBOX - INFO: ^7Object owner name updated");
763 }
764
765 if(e.crypto_idfp == player.crypto_idfp)
766 {
767 print_to(player, "^2SANDBOX - INFO: ^7Object is already yours, nothing to claim");
768 return true;
769 }
770
771 strcpy(e.crypto_idfp, player.crypto_idfp);
772
773 print_to(player, "^2SANDBOX - INFO: ^7Object claimed successfully");
774 }
775 print_to(player, "^1SANDBOX - WARNING: ^7Object could not be claimed. Make sure you are facing an object that you have edit rights over");
776 return true;
777
778 // ---------------- COMMAND: OBJECT, INFO ----------------
779 case "object_info":
780 // prints public information about the object to the player
781 e = sandbox_ObjectEdit_Get(player, false);
782 if(e != NULL)
783 {
784 switch(argv(2))
785 {
786 case "object":
787 print_to(player, strcat("^2SANDBOX - INFO: ^7Object is owned by \"^7", e.netname, "^7\", created \"^3", e.message, "^7\", last edited \"^3", e.message2, "^7\""));
788 return true;
789 case "mesh":
790 s = "";
791 FOR_EACH_TAG(e)
792 s = strcat(s, "^7\"^5", gettaginfo_name, "^7\", ");
793 print_to(player, strcat("^2SANDBOX - INFO: ^7Object mesh is \"^3", e.model, "^7\" at animation frame ^3", ftos(e.frame), " ^7containing the following tags: ", s));
794 return true;
795 case "attachments":
796 // this should show the same info as 'mesh' but for attachments
797 s = "";
798 j = 0;
799 IL_EACH(g_sandbox_objects, it.owner == e,
800 {
801 ++j; // start from 1
802 gettaginfo(e, it.tag_index);
803 s = strcat(s, "^1attachment ", ftos(j), "^7 has mesh \"^3", it.model, "^7\" at animation frame ^3", ftos(it.frame));
804 s = strcat(s, "^7 and is attached to bone \"^5", gettaginfo_name, "^7\", ");
805 });
806 if(j) // object contains attachments
807 print_to(player, strcat("^2SANDBOX - INFO: ^7Object contains the following ^1", ftos(j), "^7 attachment(s): ", s));
808 else
809 print_to(player, "^2SANDBOX - INFO: ^7Object contains no attachments");
810 return true;
811 }
812 }
813 print_to(player, "^1SANDBOX - WARNING: ^7No information could be found. Make sure you are facing an object");
814 return true;
815
816 // ---------------- COMMAND: DEFAULT ----------------
817 default:
818 print_to(player, "Invalid command. For usage information, type 'sandbox help'");
819 return true;
820 }
821 }
822}
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
#define MUTATOR_RETURNVALUE
Definition base.qh:328
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
#define M_ARGV(x, type)
Definition events.qh:17
#define FOR_EACH_TAG(v)
Definition util.qh:216
const float SOLID_TRIGGER
const float SOLID_BBOX
string gettaginfo_name
float time
ERASEABLE bool fexists(string f)
Definition file.qh:4
#define IL_EACH(this, cond, body)
#define LOG_INFO(...)
Definition log.qh:65
string cmd_name
Definition events.qh:12
int cmd_argc
Definition events.qh:13
float stof(string val,...)
vector stov(string s)
string precache_sound(string sample)
string vtos(vector v)
string ftos(float f)
string strzone(string s)
string argv(float n)
void set_movetype(entity this, int mt)
Definition movetypes.qc:4
const int MOVETYPE_NONE
Definition movetypes.qh:129
const int MOVETYPE_PHYSICS
Definition movetypes.qh:142
const int MOVETYPE_TOSS
Definition movetypes.qh:135
string string_null
Definition nil.qh:9
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
#define NULL
Definition post.qh:14
#define stuffcmd(cl,...)
Definition progsdefs.qh:23
void print_to(entity to, string input)
Definition common.qc:171
#define strfree(this)
Definition string.qh:59
#define strcpy(this, s)
Definition string.qh:52
void sandbox_ObjectRemove(entity e)
bool autocvar_g_sandbox_readonly
Definition sv_sandbox.qc:7
entity sandbox_ObjectSpawn(entity this, float database)
float autocvar_g_sandbox_editor_flood
Definition sv_sandbox.qc:11
entity sandbox_ObjectEdit_Get(entity this, float permissions)
Definition sv_sandbox.qc:98
string sandbox_ObjectPort_Save(entity e, bool database)
void sandbox_ObjectAttach_Remove(entity e)
void sandbox_ObjectEdit_Scale(entity e, float f)
float object_count
Definition sv_sandbox.qc:37
IntrusiveList g_sandbox_objects
Definition sv_sandbox.qc:21
entity sandbox_ObjectPort_Load(entity this, string s, float database)
int autocvar_g_sandbox_info
Definition sv_sandbox.qc:6
int autocvar_g_sandbox_editor_maxobjects
Definition sv_sandbox.qc:12
int autocvar_g_sandbox_editor_free
Definition sv_sandbox.qc:13
void sandbox_ObjectAttach_Set(entity e, entity parent, string s)

References argv(), autocvar_g_sandbox_editor_flood, autocvar_g_sandbox_editor_free, autocvar_g_sandbox_editor_maxobjects, autocvar_g_sandbox_info, autocvar_g_sandbox_readonly, cmd_argc, cmd_name, entity(), fexists(), FOR_EACH_TAG, ftos(), g_sandbox_objects, gettaginfo_name, IL_EACH, LOG_INFO, M_ARGV, MOVETYPE_NONE, MOVETYPE_PHYSICS, MOVETYPE_TOSS, MUTATOR_CALLHOOK, MUTATOR_RETURNVALUE, NULL, object_count, precache_sound(), print_to(), sandbox_ObjectAttach_Remove(), sandbox_ObjectAttach_Set(), sandbox_ObjectEdit_Get(), sandbox_ObjectEdit_Scale(), sandbox_ObjectPort_Load(), sandbox_ObjectPort_Save(), sandbox_ObjectRemove(), sandbox_ObjectSpawn(), set_movetype(), SOLID_BBOX, SOLID_TRIGGER, stof(), stov(), strcat(), strcpy, strfree, string_null, strzone(), stuffcmd, SV_ParseClientCommand, time, and vtos().

◆ MUTATOR_HOOKFUNCTION() [2/2]

MUTATOR_HOOKFUNCTION ( sandbox ,
SV_StartFrame  )

Definition at line 824 of file sv_sandbox.qc.

825{
827 return;
828 if(time < autosave_time)
829 return;
831
833
834 return true;
835}
void sandbox_Database_Save()
float autocvar_g_sandbox_storage_autosave
Definition sv_sandbox.qc:9
float autosave_time
Definition sv_sandbox.qc:22

References autocvar_g_sandbox_storage_autosave, autosave_time, sandbox_Database_Save(), and time.

◆ sandbox_Database_Load()

void sandbox_Database_Load ( )

Definition at line 412 of file sv_sandbox.qc.

413{
414 // loads all objects from the database file
415 string file_read, file_name;
416 float file_get, i;
417
418 file_name = strcat("sandbox/storage_", autocvar_g_sandbox_storage_name, "_", GetMapname(), ".txt");
419 file_get = fopen(file_name, FILE_READ);
420 if(file_get < 0)
421 {
423 LOG_INFO("^3SANDBOX - SERVER: ^7could not find storage file ^3", file_name, "^7, no objects were loaded");
424 return;
425 }
426 else
427 {
428 for (;;)
429 {
430 file_read = fgets(file_get);
431 if(file_read == "")
432 break;
433 if(substring(file_read, 0, 2) == "//")
434 continue;
435 if(substring(file_read, 0, 1) == "#")
436 continue;
437
438 entity e;
439 e = sandbox_ObjectPort_Load(NULL, file_read, true);
440
441 if(e.material)
442 {
443 // since objects are being loaded for the first time, precache material sounds for each
444 for (i = 1; i <= 5; ++i) // 5 sounds in total
445 precache_sound(strcat("object/impact_", e.material, "_", ftos(i), ".wav"));
446 }
447 }
449 LOG_INFO("^3SANDBOX - SERVER: ^7successfully loaded storage file ^3", file_name);
450 }
451 fclose(file_get);
452}
const float FILE_READ
string GetMapname()
string fgets(float fhandle)
void fclose(float fhandle)
string substring(string s, float start, float length)
float fopen(string filename, float mode)
string autocvar_g_sandbox_storage_name
Definition sv_sandbox.qc:8

References autocvar_g_sandbox_info, autocvar_g_sandbox_storage_name, entity(), fclose(), fgets(), FILE_READ, fopen(), ftos(), GetMapname(), LOG_INFO, NULL, precache_sound(), sandbox_ObjectPort_Load(), strcat(), and substring().

◆ sandbox_Database_Save()

void sandbox_Database_Save ( )

Definition at line 390 of file sv_sandbox.qc.

391{
392 if(MUTATOR_CALLHOOK(Sandbox_SaveAllowed))
393 return;
394
395 // saves all objects to the database file
396 string file_name;
397 float file_get;
398
399 file_name = strcat("sandbox/storage_", autocvar_g_sandbox_storage_name, "_", GetMapname(), ".txt");
400 file_get = fopen(file_name, FILE_WRITE);
401 fputs(file_get, strcat("// sandbox storage \"", autocvar_g_sandbox_storage_name, "\" for map \"", GetMapname(), "\" last updated ", strftime(true, "%d-%m-%Y %H:%M:%S")));
402 fputs(file_get, strcat(" containing ", ftos(object_count), " objects\n"));
403
404 IL_EACH(g_sandbox_objects, !it.owner, // attached objects are persisted separately, ignore them here
405 {
406 // use a line of text for each object, listing all properties
407 fputs(file_get, strcat(sandbox_ObjectPort_Save(it, true), "\n"));
408 });
409 fclose(file_get);
410}
const float FILE_WRITE
void fputs(float fhandle, string s)

References autocvar_g_sandbox_storage_name, fclose(), FILE_WRITE, fopen(), fputs(), ftos(), g_sandbox_objects, GetMapname(), IL_EACH, MUTATOR_CALLHOOK, object_count, and strcat().

Referenced by MUTATOR_HOOKFUNCTION().

◆ sandbox_ObjectAttach_Remove()

void sandbox_ObjectAttach_Remove ( entity e)

Definition at line 148 of file sv_sandbox.qc.

149{
150 // detaches any object attached to e
151
152 IL_EACH(g_sandbox_objects, it.owner == e,
153 {
154 vector org = gettaginfo(it, 0);
155 setattachment(it, NULL, "");
156 it.owner = NULL;
157
158 // objects change origin and angles when detached, so apply previous position
159 setorigin(it, org);
160 it.angles = e.angles; // don't allow detached objects to spin or roll
161
162 it.solid = it.old_solid; // restore persisted solidity
163 set_movetype(it, it.old_movetype); // restore persisted physics
164 it.takedamage = DAMAGE_AIM;
165 });
166}

References entity(), g_sandbox_objects, and IL_EACH.

Referenced by MUTATOR_HOOKFUNCTION(), sandbox_ObjectAttach_Set(), and sandbox_ObjectRemove().

◆ sandbox_ObjectAttach_Set()

void sandbox_ObjectAttach_Set ( entity e,
entity parent,
string s )

Definition at line 131 of file sv_sandbox.qc.

132{
133 // attaches e to parent on string s
134
135 // we can't attach to an attachment, for obvious reasons
137
138 e.old_solid = e.solid; // persist solidity
139 e.old_movetype = e.move_movetype; // persist physics
141 e.solid = SOLID_NOT;
142 e.takedamage = DAMAGE_NO;
143
144 setattachment(e, parent, s);
145 e.owner = parent;
146}
entity parent
Definition animhost.qc:7
const float SOLID_NOT
const int MOVETYPE_FOLLOW
Definition movetypes.qh:141
const int DAMAGE_NO
Definition subs.qh:79

References DAMAGE_NO, entity(), MOVETYPE_FOLLOW, parent, sandbox_ObjectAttach_Remove(), set_movetype(), and SOLID_NOT.

Referenced by MUTATOR_HOOKFUNCTION(), and sandbox_ObjectPort_Load().

◆ sandbox_ObjectEdit_Get()

entity sandbox_ObjectEdit_Get ( entity this,
float permissions )

Definition at line 98 of file sv_sandbox.qc.

99{
100 // Returns the traced entity if the player can edit it, and NULL if not.
101 // If permissions if false, the object is returned regardless of editing rights.
102 // Attached objects are SOLID_NOT and do not get traced.
103
106 return NULL; // out of trace range
107 if(trace_ent.classname != "object")
108 return NULL; // entity is not an object
109 if(!permissions)
110 return trace_ent; // don't check permissions, anyone can edit this object
111 if(trace_ent.crypto_idfp == "")
112 return trace_ent; // the player who spawned this object did not have an UID, so anyone can edit it
113 if (!(trace_ent.realowner != this && autocvar_g_sandbox_editor_free < 2))
114 return trace_ent; // object does not belong to the player, and players can only edit their own objects on this server
115 return NULL;
116}
entity trace_ent
vector origin
float autocvar_g_sandbox_editor_distance_edit
Definition sv_sandbox.qc:15
void crosshair_trace_plusvisibletriggers(entity pl)
Definition tracing.qc:554
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition vector.qh:8

References autocvar_g_sandbox_editor_distance_edit, autocvar_g_sandbox_editor_free, crosshair_trace_plusvisibletriggers(), entity(), NULL, origin, trace_ent, and vdist.

Referenced by MUTATOR_HOOKFUNCTION().

◆ sandbox_ObjectEdit_Scale()

void sandbox_ObjectEdit_Scale ( entity e,
float f )

Definition at line 118 of file sv_sandbox.qc.

119{
120 e.scale = f;
121 if(e.scale)
122 {
124 _setmodel(e, e.model); // reset mins and maxs based on mesh
125 // apply object scaling and prevent any float precision issues like #2742
126 setsize(e, RoundPerfectVector(e.mins * e.scale), RoundPerfectVector(e.maxs * e.scale));
127 }
128}
float bound(float min, float value, float max)
float autocvar_g_sandbox_object_scale_max
Definition sv_sandbox.qc:17
float autocvar_g_sandbox_object_scale_min
Definition sv_sandbox.qc:16
ERASEABLE vector RoundPerfectVector(vector v)
Definition vector.qh:206

References autocvar_g_sandbox_object_scale_max, autocvar_g_sandbox_object_scale_min, bound(), entity(), and RoundPerfectVector().

Referenced by MUTATOR_HOOKFUNCTION(), and sandbox_ObjectPort_Load().

◆ sandbox_ObjectFunction_Think()

void sandbox_ObjectFunction_Think ( entity this)

Definition at line 68 of file sv_sandbox.qc.

69{
70 // decide if and how this object can be grabbed
71 if(autocvar_g_sandbox_readonly || MUTATOR_CALLHOOK(Sandbox_DragAllowed, this))
72 this.grab = 0; // no grabbing
74 this.grab = 1; // owner only
75 else
76 this.grab = 3; // anyone
77
78 // Object owner is stored via player UID, but we also need the owner as an entity (if the player is available on the server).
79 // Therefore, scan for all players, and update the owner as long as the player is present. We must always do this,
80 // since if the owning player disconnects, the object's owner should also be reset.
81
82 // bots can't have objects
84 if(this.crypto_idfp == it.crypto_idfp)
85 {
86 this.realowner = it;
87 break;
88 }
89 this.realowner = NULL;
90 });
91
92 this.nextthink = time;
93
95}
int grab
Definition cheats.qh:26
#define IS_PLAYER(s)
Definition player.qh:243
float nextthink
#define CSQCMODEL_AUTOUPDATE(e)
string crypto_idfp
entity realowner
#define IS_REAL_CLIENT(v)
Definition utils.qh:17
#define FOREACH_CLIENT(cond, body)
Definition utils.qh:50

References autocvar_g_sandbox_editor_free, autocvar_g_sandbox_readonly, crypto_idfp, CSQCMODEL_AUTOUPDATE, entity(), FOREACH_CLIENT, grab, IS_PLAYER, IS_REAL_CLIENT, MUTATOR_CALLHOOK, nextthink, NULL, realowner, and time.

Referenced by sandbox_ObjectSpawn().

◆ sandbox_ObjectFunction_Touch()

void sandbox_ObjectFunction_Touch ( entity this,
entity toucher )

Definition at line 43 of file sv_sandbox.qc.

44{
45 // apply material impact effects
46
47 if(!this.material)
48 return;
49 if(this.touch_timer > time)
50 return; // don't execute each frame
51 this.touch_timer = time + 0.1;
52
53 // make particle count and sound volume depend on impact speed
54 float intensity;
55 intensity = vlen(this.velocity) + vlen(toucher.velocity);
56 if(intensity) // avoid divisions by 0
57 intensity /= 2; // average the two velocities
59 return; // impact not strong enough to do anything
60 // now offset intensity and apply it to the effects
61 intensity -= autocvar_g_sandbox_object_material_velocity_min; // start from minimum velocity, not actual velocity
62 intensity = bound(0, intensity * autocvar_g_sandbox_object_material_velocity_factor, 1);
63
64 _sound(this, CH_TRIGGER, strcat("object/impact_", this.material, "_", ftos(ceil(random() * 5)) , ".wav"), VOL_BASE * intensity, ATTEN_NORM);
65 Send_Effect_(strcat("impact_", this.material), this.origin, '0 0 0', ceil(intensity * 10)); // allow a count from 1 to 10
66}
vector velocity
void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt)
Definition all.qc:129
float ceil(float f)
float random(void)
float vlen(vector v)
entity entity toucher
Definition self.qh:72
const int CH_TRIGGER
Definition sound.qh:12
const float VOL_BASE
Definition sound.qh:36
#define _sound(e, c, s, v, a)
Definition sound.qh:43
const float ATTEN_NORM
Definition sound.qh:30
float touch_timer
Definition sv_sandbox.qc:42
float autocvar_g_sandbox_object_material_velocity_min
Definition sv_sandbox.qc:18
string material
Definition sv_sandbox.qc:40
float autocvar_g_sandbox_object_material_velocity_factor
Definition sv_sandbox.qc:19

References _sound, ATTEN_NORM, autocvar_g_sandbox_object_material_velocity_factor, autocvar_g_sandbox_object_material_velocity_min, bound(), ceil(), CH_TRIGGER, entity(), ftos(), material, origin, random(), Send_Effect_(), strcat(), time, touch_timer, toucher, velocity, vlen(), and VOL_BASE.

Referenced by sandbox_ObjectSpawn().

◆ sandbox_ObjectPort_Load()

entity sandbox_ObjectPort_Load ( entity this,
string s,
float database )

Definition at line 317 of file sv_sandbox.qc.

318{
319 // load object properties, and spawn a new object with them
320 int n, i;
321 entity e = NULL, parent = NULL;
322 string arg = string_null;
323
324 // separate objects between the ; symbols
325 n = tokenizebyseparator(s, "; ");
326 for(i = 0; i < n; ++i)
327 port_string[i] = argv(i);
328
329 // now separate and apply the properties of each object
330 for(i = 0; i < n; ++i)
331 {
332 #define SANDBOX_GETARG arg = argv(++argv_num);
333 int argv_num = -1; // starts at -1 so I don't need postincrement
334
335 string tagname = string_null;
337 e = sandbox_ObjectSpawn(this, database);
338
339 // ---------------- OBJECT PROPERTY STORAGE: LOAD ----------------
340 if(i)
341 {
342 // properties stored only for child objects
343 SANDBOX_GETARG; tagname = (arg != "") ? arg : string_null;
344 }
345 else
346 {
347 // properties stored only for parent objects
348 if(database)
349 {
350 SANDBOX_GETARG; setorigin(e, stov(arg));
351 SANDBOX_GETARG; e.angles = stov(arg);
352 }
353 parent = e; // mark parent objects as such
354 }
355 // properties stored for all objects
356 SANDBOX_GETARG; precache_model(arg); _setmodel(e, arg);
357 SANDBOX_GETARG; e.skin = stof(arg);
358 SANDBOX_GETARG; e.alpha = stof(arg);
359 SANDBOX_GETARG; e.colormod = stov(arg);
360 SANDBOX_GETARG; e.glowmod = stov(arg);
361 SANDBOX_GETARG; e.frame = stof(arg);
363 SANDBOX_GETARG; e.solid = e.old_solid = stof(arg);
364 SANDBOX_GETARG; e.old_movetype = stof(arg);
365 set_movetype(e, e.old_movetype);
366 SANDBOX_GETARG; e.damageforcescale = stof(arg);
367 strfree(e.material);
368 SANDBOX_GETARG; e.material = (arg != "") ? strzone(arg) : string_null;
369 if(database)
370 {
371 // properties stored only for the database
372 strfree(e.crypto_idfp);
373 SANDBOX_GETARG; e.crypto_idfp = (arg != "") ? strzone(arg) : string_null;
374 SANDBOX_GETARG; strcpy(e.netname, arg);
375 SANDBOX_GETARG; strcpy(e.message, arg);
376 SANDBOX_GETARG; strcpy(e.message2, arg);
377 }
378
379 // attach last
380 if(i)
381 sandbox_ObjectAttach_Set(e, parent, tagname);
382 }
383
384 for(i = 0; i <= MAX_STORAGE_ATTACHMENTS; ++i)
385 port_string[i] = string_null; // fully clear the string
386
387 return e;
388}
#define tokenize_console
#define tokenizebyseparator
#define SANDBOX_GETARG
string port_string[MAX_STORAGE_ATTACHMENTS]

References argv(), entity(), NULL, parent, port_string, SANDBOX_GETARG, sandbox_ObjectAttach_Set(), sandbox_ObjectEdit_Scale(), sandbox_ObjectSpawn(), set_movetype(), stof(), stov(), strcpy, strfree, string_null, strzone(), tokenize_console, and tokenizebyseparator.

Referenced by MUTATOR_HOOKFUNCTION(), and sandbox_Database_Load().

◆ sandbox_ObjectPort_Save()

string sandbox_ObjectPort_Save ( entity e,
bool database )

Definition at line 233 of file sv_sandbox.qc.

234{
235 // save object properties, and return them as a string
236 int o = 0;
237
238 // order doesn't really matter, as we're writing the file fresh
239 IL_EACH(g_sandbox_objects, it == e || it.owner == e, LAMBDA(
240 // the main object needs to be first in the array [0] with attached objects following
241 int slot, physics, solidity;
242 if(it == e) // this is the main object, place it first
243 {
244 slot = 0;
245 solidity = it.solid; // applied solidity is normal solidity for children
246 physics = it.move_movetype; // applied physics are normal physics for parents
247 }
248 else if(it.owner == e) // child object, list them in order
249 {
250 o += 1; // children start from 1
251 slot = o;
252 solidity = it.old_solid; // persisted solidity is normal solidity for children
253 physics = it.old_movetype; // persisted physics are normal physics for children
254 gettaginfo(it.owner, it.tag_index); // get the name of the tag our object is attached to, used further below
255 }
256 else
257 continue;
258
259 // ---------------- OBJECT PROPERTY STORAGE: SAVE ----------------
260 if(slot)
261 {
262 // properties stored only for child objects
263 if(gettaginfo_name)
264 port_string[slot] = strcat(port_string[slot], "\"", gettaginfo_name, "\" ");
265 else
266 port_string[slot] = strcat(port_string[slot], "\"\" "); // none
267 }
268 else
269 {
270 // properties stored only for parent objects
271 if(database)
272 {
273 port_string[slot] = strcat(port_string[slot], sprintf("\"%.9v\"", it.origin), " ");
274 port_string[slot] = strcat(port_string[slot], sprintf("\"%.9v\"", it.angles), " ");
275 }
276 }
277 // properties stored for all objects
278 port_string[slot] = strcat(port_string[slot], "\"", it.model, "\" ");
279 port_string[slot] = strcat(port_string[slot], ftos(it.skin), " ");
280 port_string[slot] = strcat(port_string[slot], ftos(it.alpha), " ");
281 port_string[slot] = strcat(port_string[slot], sprintf("\"%.9v\"", it.colormod), " ");
282 port_string[slot] = strcat(port_string[slot], sprintf("\"%.9v\"", it.glowmod), " ");
283 port_string[slot] = strcat(port_string[slot], ftos(it.frame), " ");
284 port_string[slot] = strcat(port_string[slot], ftos(it.scale), " ");
285 port_string[slot] = strcat(port_string[slot], ftos(solidity), " ");
286 port_string[slot] = strcat(port_string[slot], ftos(physics), " ");
287 port_string[slot] = strcat(port_string[slot], ftos(it.damageforcescale), " ");
288 if(it.material)
289 port_string[slot] = strcat(port_string[slot], "\"", it.material, "\" ");
290 else
291 port_string[slot] = strcat(port_string[slot], "\"\" "); // none
292 if(database)
293 {
294 // properties stored only for the database
295 if(it.crypto_idfp)
296 port_string[slot] = strcat(port_string[slot], "\"", it.crypto_idfp, "\" ");
297 else
298 port_string[slot] = strcat(port_string[slot], "\"\" "); // none
299 port_string[slot] = strcat(port_string[slot], "\"", e.netname, "\" ");
300 port_string[slot] = strcat(port_string[slot], "\"", e.message, "\" ");
301 port_string[slot] = strcat(port_string[slot], "\"", e.message2, "\" ");
302 }
303 ));
304
305 // now apply the array to a simple string, with the ; symbol separating objects
306 string s = "";
307 for(int j = 0; j <= MAX_STORAGE_ATTACHMENTS; ++j)
308 {
309 if(port_string[j])
310 s = strcat(s, port_string[j], "; ");
311 port_string[j] = string_null; // fully clear the string
312 }
313
314 return s;
315}
#define LAMBDA(...)
Definition misc.qh:34

References entity(), g_sandbox_objects, IL_EACH, and LAMBDA.

Referenced by MUTATOR_HOOKFUNCTION().

◆ sandbox_ObjectRemove()

void sandbox_ObjectRemove ( entity e)

Definition at line 213 of file sv_sandbox.qc.

214{
215 sandbox_ObjectAttach_Remove(e); // detach child objects
216
217 // if the object being removed has been selected for attachment by a player, unset it
218 FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it) && it.object_attach == e, { it.object_attach = NULL; });
219
220 strfree(e.material);
221 strfree(e.crypto_idfp);
222 strfree(e.netname);
223 strfree(e.message);
224 strfree(e.message2);
225 delete(e);
226 e = NULL;
227
228 object_count -= 1;
229}

References entity(), FOREACH_CLIENT, IS_PLAYER, IS_REAL_CLIENT, NULL, object_count, sandbox_ObjectAttach_Remove(), and strfree.

Referenced by MUTATOR_HOOKFUNCTION().

◆ sandbox_ObjectSpawn()

entity sandbox_ObjectSpawn ( entity this,
float database )

Definition at line 168 of file sv_sandbox.qc.

169{
170 // spawn a new object with default properties
171
172 entity e = new(object);
174 e.takedamage = DAMAGE_AIM;
175 e.damageforcescale = 1;
176 e.solid = SOLID_BBOX; // SOLID_BSP would be best, but can lag the server badly
178 e.frame = 0;
179 e.skin = 0;
180 e.material = string_null;
183 e.nextthink = time;
184 //e.effects |= EF_SELECTABLE; // don't do this all the time, maybe just when editing objects?
185
186 if(!database)
187 {
188 // set the object's owner via player UID
189 // if the player does not have an UID, the owner cannot be stored and their objects may be edited by anyone
190 if(this.crypto_idfp != "")
191 e.crypto_idfp = strzone(this.crypto_idfp);
192 else
193 print_to(this, "^1SANDBOX - WARNING: ^7You spawned an object, but lack a player UID. ^1Your objects are not secured and can be edited by any player!");
194
195 // set public object information
196 e.netname = strzone(this.netname); // name of the owner
197 e.message = strzone(strftime(true, "%d-%m-%Y %H:%M:%S")); // creation time
198 e.message2 = strzone(strftime(true, "%d-%m-%Y %H:%M:%S")); // last editing time
199
200 // set origin and direction based on player position and view angle
201 makevectors(this.v_angle);
203 setorigin(e, trace_endpos);
204 e.angles_y = this.v_angle.y;
205 }
206
208
209 object_count += 1;
210 return e;
211}
string netname
Definition powerups.qc:20
vector v_angle
Definition player.qh:237
const float MOVE_NORMAL
vector trace_endpos
vector v_forward
#define CSQCMODEL_AUTOINIT(e)
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
void WarpZone_TraceLine(vector org, vector end, float nomonsters, entity forent)
Definition common.qc:348
#define makevectors
Definition post.qh:21
vector view_ofs
Definition progsdefs.qc:151
#define setthink(e, f)
#define settouch(e, f)
Definition self.qh:73
const int DAMAGE_AIM
Definition subs.qh:81
void sandbox_ObjectFunction_Think(entity this)
Definition sv_sandbox.qc:68
float autocvar_g_sandbox_editor_distance_spawn
Definition sv_sandbox.qc:14
void sandbox_ObjectFunction_Touch(entity this, entity toucher)
Definition sv_sandbox.qc:43

References autocvar_g_sandbox_editor_distance_spawn, crypto_idfp, CSQCMODEL_AUTOINIT, DAMAGE_AIM, entity(), g_sandbox_objects, IL_PUSH(), makevectors, MOVE_NORMAL, MOVETYPE_TOSS, netname, object_count, origin, print_to(), sandbox_ObjectFunction_Think(), sandbox_ObjectFunction_Touch(), set_movetype(), setthink, settouch, SOLID_BBOX, string_null, strzone(), time, trace_endpos, v_angle, v_forward, view_ofs, and WarpZone_TraceLine().

Referenced by MUTATOR_HOOKFUNCTION(), and sandbox_ObjectPort_Load().

Variable Documentation

◆ autocvar_g_sandbox

string autocvar_g_sandbox

Definition at line 5 of file sv_sandbox.qc.

◆ autocvar_g_sandbox_editor_distance_edit

float autocvar_g_sandbox_editor_distance_edit

Definition at line 15 of file sv_sandbox.qc.

Referenced by sandbox_ObjectEdit_Get().

◆ autocvar_g_sandbox_editor_distance_spawn

float autocvar_g_sandbox_editor_distance_spawn

Definition at line 14 of file sv_sandbox.qc.

Referenced by sandbox_ObjectSpawn().

◆ autocvar_g_sandbox_editor_flood

float autocvar_g_sandbox_editor_flood

Definition at line 11 of file sv_sandbox.qc.

Referenced by MUTATOR_HOOKFUNCTION().

◆ autocvar_g_sandbox_editor_free

int autocvar_g_sandbox_editor_free

◆ autocvar_g_sandbox_editor_maxobjects

int autocvar_g_sandbox_editor_maxobjects

Definition at line 12 of file sv_sandbox.qc.

Referenced by MUTATOR_HOOKFUNCTION().

◆ autocvar_g_sandbox_info

int autocvar_g_sandbox_info

Definition at line 6 of file sv_sandbox.qc.

Referenced by MUTATOR_HOOKFUNCTION(), and sandbox_Database_Load().

◆ autocvar_g_sandbox_object_material_velocity_factor

float autocvar_g_sandbox_object_material_velocity_factor

Definition at line 19 of file sv_sandbox.qc.

Referenced by sandbox_ObjectFunction_Touch().

◆ autocvar_g_sandbox_object_material_velocity_min

float autocvar_g_sandbox_object_material_velocity_min

Definition at line 18 of file sv_sandbox.qc.

Referenced by sandbox_ObjectFunction_Touch().

◆ autocvar_g_sandbox_object_scale_max

float autocvar_g_sandbox_object_scale_max

Definition at line 17 of file sv_sandbox.qc.

Referenced by sandbox_ObjectEdit_Scale().

◆ autocvar_g_sandbox_object_scale_min

float autocvar_g_sandbox_object_scale_min

Definition at line 16 of file sv_sandbox.qc.

Referenced by sandbox_ObjectEdit_Scale().

◆ autocvar_g_sandbox_readonly

bool autocvar_g_sandbox_readonly

Definition at line 7 of file sv_sandbox.qc.

Referenced by MUTATOR_HOOKFUNCTION(), and sandbox_ObjectFunction_Think().

◆ autocvar_g_sandbox_storage_autoload

bool autocvar_g_sandbox_storage_autoload

Definition at line 10 of file sv_sandbox.qc.

◆ autocvar_g_sandbox_storage_autosave

float autocvar_g_sandbox_storage_autosave

Definition at line 9 of file sv_sandbox.qc.

Referenced by MUTATOR_HOOKFUNCTION().

◆ autocvar_g_sandbox_storage_name

string autocvar_g_sandbox_storage_name

Definition at line 8 of file sv_sandbox.qc.

Referenced by sandbox_Database_Load(), and sandbox_Database_Save().

◆ autosave_time

float autosave_time

Definition at line 22 of file sv_sandbox.qc.

Referenced by MUTATOR_HOOKFUNCTION().

◆ g_sandbox_objects

◆ material

string material

Definition at line 40 of file sv_sandbox.qc.

Referenced by sandbox_ObjectFunction_Touch().

◆ object_attach

entity object_attach

Definition at line 39 of file sv_sandbox.qc.

◆ object_count

float object_count
Initial value:
{
{
}
}
const float MAX_STORAGE_ATTACHMENTS = 16
#define MUTATOR_ONADD
Definition base.qh:309
#define IL_NEW()
void sandbox_Database_Load()
bool autocvar_g_sandbox_storage_autoload
Definition sv_sandbox.qc:10

Definition at line 37 of file sv_sandbox.qc.

Referenced by MUTATOR_HOOKFUNCTION(), sandbox_Database_Save(), sandbox_ObjectRemove(), and sandbox_ObjectSpawn().

◆ object_flood

float object_flood

Definition at line 38 of file sv_sandbox.qc.

◆ old_movetype

float old_movetype

Definition at line 97 of file sv_sandbox.qc.

◆ old_solid

float old_solid

Definition at line 97 of file sv_sandbox.qc.

◆ port_string

string port_string[MAX_STORAGE_ATTACHMENTS]

Definition at line 231 of file sv_sandbox.qc.

Referenced by sandbox_ObjectPort_Load().

◆ touch_timer

float touch_timer

Definition at line 42 of file sv_sandbox.qc.

Referenced by sandbox_ObjectFunction_Touch().