const float MAX_STORAGE_ATTACHMENTS = 16;
float object_count;
-.string object_clipboard;
.entity object_attach;
.string material;
e.skin = 0;
e.material = string_null;
e.touch = sandbox_ObjectFunction_Touch;
+ //e.effects |= EF_SELECTABLE; // don't do this all the time, maybe just when editing objects?
if(!database)
{
else
print_to(self, "^1SANDBOX - WARNING: ^7You spawned an object, but lack a player UID. ^1Your objects are not secured and can be edited by any player!");
+ // set public object information
+ e.netname = strzone(self.netname); // name of the owner
+ e.message = strzone(strftime(TRUE, "%d-%m-%Y %H:%M:%S")); // creation time
+ e.message2 = strzone(strftime(TRUE, "%d-%m-%Y %H:%M:%S")); // last editing time
+
// set origin and direction based on player position and view angle
makevectors(self.v_angle);
WarpZone_TraceLine(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * autocvar_g_sandbox_editor_distance_spawn, MOVE_NORMAL, self);
void sandbox_ObjectRemove(entity e)
{
sandbox_ObjectAttach_Remove(e); // detach child objects
- if(e.material)
- {
- strunzone(e.material);
- e.material = string_null;
- }
- if(e.crypto_idfp)
- {
- strunzone(e.crypto_idfp);
- e.crypto_idfp = string_null;
- }
+
+ if(e.material) { strunzone(e.material); e.material = string_null; }
+ if(e.crypto_idfp) { strunzone(e.crypto_idfp); e.crypto_idfp = string_null; }
+ if(e.netname) { strunzone(e.netname); e.netname = string_null; }
+ if(e.message) { strunzone(e.message); e.message = string_null; }
+ if(e.message2) { strunzone(e.message2); e.message2 = string_null; }
remove(e);
e = world;
{
// properties stored only for the database
if(head.crypto_idfp) port_string[slot] = strcat(port_string[slot], "\"", head.crypto_idfp, "\" "); else port_string[slot] = strcat(port_string[slot], "- "); // none
+ port_string[slot] = strcat(port_string[slot], "\"", e.netname, "\" ");
+ port_string[slot] = strcat(port_string[slot], "\"", e.message, "\" ");
+ port_string[slot] = strcat(port_string[slot], "\"", e.message2, "\" ");
}
}
{
// properties stored only for the database
if(e.crypto_idfp) strunzone(e.crypto_idfp); if(argv(argv_num) != "-") e.crypto_idfp = strzone(argv(argv_num)); else e.crypto_idfp = string_null; ++argv_num;
+ if(e.netname) strunzone(e.netname); e.netname = strzone(argv(argv_num)); ++argv_num;
+ if(e.message) strunzone(e.message); e.message = strzone(argv(argv_num)); ++argv_num;
+ if(e.message2) strunzone(e.message2); e.message2 = strzone(argv(argv_num)); ++argv_num;
}
// attach last
- sandbox_ObjectAttach_Set(e, parent, tagname);
+ if(i)
+ sandbox_ObjectAttach_Set(e, parent, tagname);
}
for(i = 0; i <= MAX_STORAGE_ATTACHMENTS; ++i)
{
entity e;
float i;
+ string s;
// ---------------- COMMAND: HELP ----------------
case "help":
print_to(self, "You can use the following sandbox commands:");
print_to(self, "^7\"^2object_spawn ^3models/foo/bar.md3^7\" spawns a new object in front of the player, and gives it the specified model");
print_to(self, "^7\"^2object_remove^7\" removes the object the player is looking at. Players can only remove their own objects");
- print_to(self, "^7\"^2object_duplicate ^3value^7\" duplicates the object. 'copy' copies the object, 'paste' puts it in front of the player");
+ print_to(self, "^7\"^2object_duplicate ^3value^7\" duplicates the object, if the player has copying rights over the original");
+ print_to(self, "^Properties for ^2object_duplicate^7:");
+ print_to(self, "^3copy value ^7- copies the properties of the object to the specified client cvar");
+ print_to(self, "^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\"");
print_to(self, "^7\"^2object_attach ^3property value^7\" attaches one object to another. Players can only attach their own objects");
- print_to(self, "^7Attachment properties for ^2object_attach^7:");
+ print_to(self, "^7Properties for ^2object_attach^7:");
print_to(self, "^3get ^7- selects the object you are facing as the object to be attached");
print_to(self, "^3set value ^7- attaches the previously selected object to the object you are facing, on the specified bone");
print_to(self, "^3remove ^7- detaches all objects from the object you are facing");
print_to(self, "^7\"^2object_edit ^3property value^7\" edits the given property of the object. Players can only edit their own objects");
- print_to(self, "^7Object properties for ^2object_edit^7:");
+ print_to(self, "^7Properties for ^2object_edit^7:");
print_to(self, "^3skin value ^7- changes the skin of the object");
print_to(self, "^3alpha value ^7- sets object transparency");
print_to(self, "^3colormod \"value_x value_y value_z\" ^7- main object color");
switch(argv(2))
{
case "copy":
- // copies customizable properties of the selected object to the clipboard
+ // copies customizable properties of the selected object to the clipboard cvar
e = sandbox_ObjectEdit_Get(autocvar_g_sandbox_editor_free); // can we copy objects we can't edit?
if(e != world)
{
- if(self.object_clipboard)
- strunzone(self.object_clipboard);
- self.object_clipboard = strzone(sandbox_ObjectPort_Save(e, FALSE));
+ s = sandbox_ObjectPort_Save(e, FALSE);
+ s = strreplace("\"", "\\\"", s);
+ stuffcmd(self, strcat("set ", argv(3), " \"", s, "\""));
print_to(self, "^2SANDBOX - INFO: ^7Object copied to clipboard");
return TRUE;
return TRUE;
case "paste":
- // spawns a new object using the properties in the player's clipboard
- if(!self.object_clipboard) // no object in clipboard
+ // spawns a new object using the properties in the player's clipboard cvar
+ if(!argv(3)) // no object in clipboard
{
print_to(self, "^1SANDBOX - WARNING: ^7No object in clipboard. You must copy an object before you can paste it");
return TRUE;
print_to(self, strcat("^1SANDBOX - WARNING: ^7Cannot spawn any more objects. Up to ^3", ftos(autocvar_g_sandbox_editor_maxobjects), " ^7objects may exist at a time"));
return TRUE;
}
-
- e = sandbox_ObjectPort_Load(self.object_clipboard, FALSE);
+ e = sandbox_ObjectPort_Load(argv(3), FALSE);
print_to(self, "^2SANDBOX - INFO: ^7Object pasted successfully");
if(autocvar_g_sandbox_info > 0)
e.damageforcescale = stof(argv(3));
break;
case "material":
- if(e.material)
- strunzone(e.material);
+ if(e.material) strunzone(e.material);
if(argv(3))
{
for (i = 1; i <= 5; i++) // precache material sounds, 5 in total
break;
default:
print_to(self, "^1SANDBOX - WARNING: ^7Invalid object property. For usage information, type 'sandbox help'");
- break;
+ return TRUE;
}
+
+ // update last editing time
+ if(e.message2) strunzone(e.message2);
+ e.message2 = strzone(strftime(TRUE, "%d-%m-%Y %H:%M:%S"));
+
if(autocvar_g_sandbox_info > 1)
print(strcat("^3SANDBOX - SERVER: ^7", self.netname, " edited property ^3", argv(2), " ^7of an object at origin ^3", vtos(e.origin), "\n"));
return TRUE;
e = sandbox_ObjectEdit_Get(TRUE);
if(e != world)
{
+ // 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)
+ if(e.netname != self.netname)
+ {
+ if(e.netname) strunzone(e.netname);
+ e.netname = strzone(self.netname);
+ print_to(self, "^2SANDBOX - INFO: ^7Object owner name updated");
+ }
+
if(e.crypto_idfp == self.crypto_idfp)
{
print_to(self, "^2SANDBOX - INFO: ^7Object is already yours, nothing to claim");
return TRUE;
}
- if(e.crypto_idfp)
- strunzone(e.crypto_idfp);
- e.crypto_idfp = self.crypto_idfp;
+ if(e.crypto_idfp) strunzone(e.crypto_idfp);
+ e.crypto_idfp = strzone(self.crypto_idfp);
+
print_to(self, "^2SANDBOX - INFO: ^7Object claimed successfully");
}
print_to(self, "^1SANDBOX - WARNING: ^7Object could not be claimed. Make sure you are facing an object that you have edit rights over");
tags = strcat(tags, "^5", gettaginfo_name, "^7, ");
print_to(self, strcat("^2SANDBOX - INFO: ^7Object mesh is ^3", e.model, "^7 at animation frame ^3", ftos(e.frame), " ^7containing the following tags: ", tags));
return TRUE;
+ case "object":
+ print_to(self, strcat("^2SANDBOX - INFO: ^7Object is owned by ^7", e.netname, "^7, created ^3", e.message, "^7, last edited ^3", e.message2));
+ return TRUE;
}
}
print_to(self, "^1SANDBOX - WARNING: ^7No information could not be found. Make sure you are facing an object");
return FALSE;
}
-MUTATOR_HOOKFUNCTION(sandbox_ClientDisconnect)
-{
- // unzone the player's clipboard if it's not empty
- if(self.object_clipboard)
- {
- strunzone(self.object_clipboard);
- self.object_clipboard = string_null;
- }
-
- return FALSE;
-}
-
float autosave_time;
MUTATOR_HOOKFUNCTION(sandbox_StartFrame)
{
MUTATOR_HOOK(SV_ParseClientCommand, sandbox_PlayerCommand, CBC_ORDER_ANY);
MUTATOR_HOOK(SV_StartFrame, sandbox_StartFrame, CBC_ORDER_ANY);
MUTATOR_HOOK(PlayerPreThink, sandbox_PlayerPreThink, CBC_ORDER_ANY);
- MUTATOR_HOOK(ClientDisconnect, sandbox_ClientDisconnect, CBC_ORDER_ANY);
MUTATOR_ONADD
{