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 452 of file sv_sandbox.qc.

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

823{
825 return;
826 if(time < autosave_time)
827 return;
829
831
832 return true;
833}
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 411 of file sv_sandbox.qc.

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

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

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

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 130 of file sv_sandbox.qc.

131{
132 // attaches e to parent on string s
133
134 // we can't attach to an attachment, for obvious reasons
136
137 e.old_solid = e.solid; // persist solidity
138 e.old_movetype = e.move_movetype; // persist physics
140 e.solid = SOLID_NOT;
141 e.takedamage = DAMAGE_NO;
142
143 setattachment(e, parent, s);
144 e.owner = parent;
145}
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 97 of file sv_sandbox.qc.

98{
99 // Returns the traced entity if the player can edit it, and NULL if not.
100 // If permissions if false, the object is returned regardless of editing rights.
101 // Attached objects are SOLID_NOT and do not get traced.
102
105 return NULL; // out of trace range
106 if(trace_ent.classname != "object")
107 return NULL; // entity is not an object
108 if(!permissions)
109 return trace_ent; // don't check permissions, anyone can edit this object
110 if(trace_ent.crypto_idfp == "")
111 return trace_ent; // the player who spawned this object did not have an UID, so anyone can edit it
112 if (!(trace_ent.realowner != this && autocvar_g_sandbox_editor_free < 2))
113 return trace_ent; // object does not belong to the player, and players can only edit their own objects on this server
114 return NULL;
115}
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:547
#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 117 of file sv_sandbox.qc.

118{
119 e.scale = f;
120 if(e.scale)
121 {
123 _setmodel(e, e.model); // reset mins and maxs based on mesh
124 // apply object scaling and prevent any float precision issues like #2742
125 setsize(e, RoundPerfectVector(e.mins * e.scale), RoundPerfectVector(e.maxs * e.scale));
126 }
127}
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:209

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 67 of file sv_sandbox.qc.

68{
69 // decide if and how this object can be grabbed
70 if(autocvar_g_sandbox_readonly || MUTATOR_CALLHOOK(Sandbox_DragAllowed, this))
71 this.grab = 0; // no grabbing
73 this.grab = 1; // owner only
74 else
75 this.grab = 3; // anyone
76
77 // Object owner is stored via player UID, but we also need the owner as an entity (if the player is available on the server).
78 // Therefore, scan for all players, and update the owner as long as the player is present. We must always do this,
79 // since if the owning player disconnects, the object's owner should also be reset.
80
81 // bots can't have objects
83 if(this.crypto_idfp == it.crypto_idfp)
84 {
85 this.realowner = it;
86 break;
87 }
88 this.realowner = NULL;
89 });
90
91 this.nextthink = time;
92
94}
int grab
Definition cheats.qh:26
#define IS_PLAYER(s)
Definition player.qh:242
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:52

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 = vlen(this.velocity) + vlen(toucher.velocity);
55 if(intensity) // avoid divisions by 0
56 intensity /= 2; // average the two velocities
58 return; // impact not strong enough to do anything
59 // now offset intensity and apply it to the effects
60 intensity -= autocvar_g_sandbox_object_material_velocity_min; // start from minimum velocity, not actual velocity
61 intensity = bound(0, intensity * autocvar_g_sandbox_object_material_velocity_factor, 1);
62
63 _sound(this, CH_TRIGGER, strcat("object/impact_", this.material, "_", ftos(ceil(random() * 5)) , ".wav"), VOL_BASE * intensity, ATTEN_NORM);
64 Send_Effect_(strcat("impact_", this.material), this.origin, '0 0 0', ceil(intensity * 10)); // allow a count from 1 to 10
65}
vector velocity
void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt)
Definition all.qc:125
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 316 of file sv_sandbox.qc.

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

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

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

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 167 of file sv_sandbox.qc.

168{
169 // spawn a new object with default properties
170
171 entity e = new(object);
173 e.takedamage = DAMAGE_AIM;
174 e.damageforcescale = 1;
175 e.solid = SOLID_BBOX; // SOLID_BSP would be best, but can lag the server badly
177 e.frame = 0;
178 e.skin = 0;
179 e.material = string_null;
182 e.nextthink = time;
183 //e.effects |= EF_SELECTABLE; // don't do this all the time, maybe just when editing objects?
184
185 if(!database)
186 {
187 // set the object's owner via player UID
188 // if the player does not have an UID, the owner cannot be stored and their objects may be edited by anyone
189 if(this.crypto_idfp != "")
190 e.crypto_idfp = strzone(this.crypto_idfp);
191 else
192 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!");
193
194 // set public object information
195 e.netname = strzone(this.netname); // name of the owner
196 e.message = strzone(strftime(true, "%d-%m-%Y %H:%M:%S")); // creation time
197 e.message2 = strzone(strftime(true, "%d-%m-%Y %H:%M:%S")); // last editing time
198
199 // set origin and direction based on player position and view angle
200 makevectors(this.v_angle);
202 setorigin(e, trace_endpos);
203 e.angles_y = this.v_angle.y;
204 }
205
207
208 ++object_count;
209 return e;
210}
string netname
Definition powerups.qc:20
vector v_angle
Definition player.qh:236
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:67
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 96 of file sv_sandbox.qc.

◆ old_solid

float old_solid

Definition at line 96 of file sv_sandbox.qc.

◆ port_string

string port_string[MAX_STORAGE_ATTACHMENTS]

Definition at line 230 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().