]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/mutators/mutator/sandbox/sv_sandbox.qc
Use gender-neutral pronouns when referring to the player
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / mutators / mutator / sandbox / sv_sandbox.qc
index d80b21d5a6e0cec3b4a59f5c403b948eece5cd85..a31eee2ba49db3dba85272725628fddf4317f344 100644 (file)
@@ -1,5 +1,7 @@
 #include "sv_sandbox.qh"
 
+#include <server/intermission.qh>
+
 string autocvar_g_sandbox;
 int autocvar_g_sandbox_info;
 bool autocvar_g_sandbox_readonly;
@@ -16,6 +18,7 @@ float autocvar_g_sandbox_object_scale_max;
 float autocvar_g_sandbox_object_material_velocity_min;
 float autocvar_g_sandbox_object_material_velocity_factor;
 
+IntrusiveList g_sandbox_objects;
 float autosave_time;
 void sandbox_Database_Load();
 
@@ -23,6 +26,7 @@ REGISTER_MUTATOR(sandbox, expr_evaluate(autocvar_g_sandbox))
 {
        MUTATOR_ONADD
        {
+               g_sandbox_objects = IL_NEW();
                autosave_time = time + autocvar_g_sandbox_storage_autosave; // don't save the first server frame
                if(autocvar_g_sandbox_storage_autoload)
                        sandbox_Database_Load();
@@ -118,7 +122,8 @@ void sandbox_ObjectEdit_Scale(entity e, float f)
        {
                e.scale = bound(autocvar_g_sandbox_object_scale_min, e.scale, autocvar_g_sandbox_object_scale_max);
                _setmodel(e, e.model); // reset mins and maxs based on mesh
-               setsize(e, e.mins * e.scale, e.maxs * e.scale); // adapt bounding box size to model size
+               // apply object scaling and prevent any float precision issues like #2742
+               setsize(e, RoundPerfectVector(e.mins * e.scale), RoundPerfectVector(e.maxs * e.scale));
        }
 }
 
@@ -181,7 +186,7 @@ entity sandbox_ObjectSpawn(entity this, float database)
        if(!database)
        {
                // set the object's owner via player UID
-               // if the player does not have an UID, the owner cannot be stored and his objects may be edited by anyone
+               // if the player does not have an UID, the owner cannot be stored and their objects may be edited by anyone
                if(this.crypto_idfp != "")
                        e.crypto_idfp = strzone(this.crypto_idfp);
                else
@@ -312,8 +317,9 @@ string sandbox_ObjectPort_Save(entity e, bool database)
 entity sandbox_ObjectPort_Load(entity this, string s, float database)
 {
        // load object properties, and spawn a new object with them
-       float n, i;
+       int n, i;
        entity e = NULL, parent = NULL;
+       string arg = string_null;
 
        // separate objects between the ; symbols
        n = tokenizebyseparator(s, "; ");
@@ -323,9 +329,10 @@ entity sandbox_ObjectPort_Load(entity this, string s, float database)
        // now separate and apply the properties of each object
        for(i = 0; i < n; ++i)
        {
-               float argv_num;
+               #define SANDBOX_GETARG arg = argv(++argv_num);
+               int argv_num = -1; // starts at -1 so I don't need postincrement
+
                string tagname = string_null;
-               argv_num = 0;
                tokenize_console(port_string[i]);
                e = sandbox_ObjectSpawn(this, database);
 
@@ -333,38 +340,40 @@ entity sandbox_ObjectPort_Load(entity this, string s, float database)
                if(i)
                {
                        // properties stored only for child objects
-                       if(argv(argv_num) != "")        tagname = argv(argv_num);       else tagname = string_null;     ++argv_num;
+                       SANDBOX_GETARG; tagname = (arg != "") ? arg : string_null;
                }
                else
                {
                        // properties stored only for parent objects
                        if(database)
                        {
-                               setorigin(e, stov(argv(argv_num)));     ++argv_num;
-                               e.angles = stov(argv(argv_num));        ++argv_num;
+                               SANDBOX_GETARG; setorigin(e, stov(arg));
+                               SANDBOX_GETARG; e.angles = stov(arg);
                        }
                        parent = e; // mark parent objects as such
                }
                // properties stored for all objects
-               _setmodel(e, argv(argv_num));   ++argv_num;
-               e.skin = stof(argv(argv_num));  ++argv_num;
-               e.alpha = stof(argv(argv_num)); ++argv_num;
-               e.colormod = stov(argv(argv_num));      ++argv_num;
-               e.glowmod = stov(argv(argv_num));       ++argv_num;
-               e.frame = stof(argv(argv_num)); ++argv_num;
-               sandbox_ObjectEdit_Scale(e, stof(argv(argv_num)));      ++argv_num;
-               e.solid = e.old_solid = stof(argv(argv_num));   ++argv_num;
-               e.old_movetype = stof(argv(argv_num));  ++argv_num;
+               SANDBOX_GETARG; _setmodel(e, arg);
+               SANDBOX_GETARG; e.skin = stof(arg);
+               SANDBOX_GETARG; e.alpha = stof(arg);
+               SANDBOX_GETARG; e.colormod = stov(arg);
+               SANDBOX_GETARG; e.glowmod = stov(arg);
+               SANDBOX_GETARG; e.frame = stof(arg);
+               SANDBOX_GETARG; sandbox_ObjectEdit_Scale(e, stof(arg));
+               SANDBOX_GETARG; e.solid = e.old_solid = stof(arg);
+               SANDBOX_GETARG; e.old_movetype = stof(arg);
                set_movetype(e, e.old_movetype);
-               e.damageforcescale = stof(argv(argv_num));      ++argv_num;
-               strfree(e.material);    if(argv(argv_num) != "")        e.material = strzone(argv(argv_num));   else    e.material = string_null;       ++argv_num;
+               SANDBOX_GETARG; e.damageforcescale = stof(arg);
+               strfree(e.material);
+               SANDBOX_GETARG; e.material = (arg != "") ? strzone(arg) : string_null;
                if(database)
                {
                        // properties stored only for the database
-                       strfree(e.crypto_idfp); if(argv(argv_num) != "")        e.crypto_idfp = strzone(argv(argv_num));        else    e.crypto_idfp = string_null;    ++argv_num;
-                       strcpy(e.netname, argv(argv_num));      ++argv_num;
-                       strcpy(e.message, argv(argv_num));      ++argv_num;
-                       strcpy(e.message2, argv(argv_num));     ++argv_num;
+                       strfree(e.crypto_idfp);
+                       SANDBOX_GETARG; e.crypto_idfp = (arg != "") ? strzone(arg) : string_null;
+                       SANDBOX_GETARG; strcpy(e.netname, arg);
+                       SANDBOX_GETARG; strcpy(e.message, arg);
+                       SANDBOX_GETARG; strcpy(e.message2, arg);
                }
 
                // attach last
@@ -489,7 +498,7 @@ MUTATOR_HOOKFUNCTION(sandbox, SV_ParseClientCommand)
                                print_to(player, "^3physics value ^7- object physics, 0 = static, 1 = movable, 2 = physical");
                                print_to(player, "^3force value ^7- amount of force applied to objects that are shot");
                                print_to(player, "^3material value ^7- sets the material of the object. Default materials are: metal, stone, wood, flesh");
-                               print_to(player, "^7\"^2object_claim^7\" sets the player as the owner of the object, if he has the right to edit it");
+                               print_to(player, "^7\"^2object_claim^7\" sets the player as the owner of the object, if they have the right to edit it");
                                print_to(player, "^7\"^2object_info ^3value^7\" shows public information about the object");
                                print_to(player, "^3object ^7- prints general information about the object, such as owner and creation / editing date");
                                print_to(player, "^3mesh ^7- prints information about the object's mesh, including skeletal bones");
@@ -741,7 +750,7 @@ MUTATOR_HOOKFUNCTION(sandbox, SV_ParseClientCommand)
                                {
                                        // update the owner's name
                                        // Do this before checking if you're already the owner and skipping if such, so we
-                                       // also update the player's nickname if he changed it (but has the same player UID)
+                                       // also update the player's nickname if they changed it (but has the same player UID)
                                        if(e.netname != player.netname)
                                        {
                                                strcpy(e.netname, player.netname);