.float old_solid, old_movetype;
entity sandbox_ObjectEdit_Get(float permissions)
{
- // returns the traced entity if the player can edit it, and world if not
- // if permissions if FALSE, the object is returned regardless of editing rights
-
- // Tracing does not work for entities that use SOLID_NOT or SOLID_TRIGGER. Therefore, make all
- // objects temporarily solid while doing the trace, then revert them to their initial solidity.
- entity head;
- for(head = world; (head = find(head, classname, "object")); )
- {
- if(head.owner == world) // skip attached objects
- {
- head.old_solid = head.solid;
- head.solid = SOLID_BBOX;
- }
- }
- makevectors(self.v_angle);
- WarpZone_TraceLine(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * autocvar_g_sandbox_editor_distance_edit, MOVE_NORMAL, self);
- for(head = world; (head = find(head, classname, "object")); )
- {
- if(head.owner == world) // skip attached objects
- head.solid = head.old_solid;
- }
+ // Returns the traced entity if the player can edit it, and world if not.
+ // If permissions if FALSE, the object is returned regardless of editing rights.
+ // Attached objects are SOLID_NOT and do not get traced.
+ crosshair_trace_plusvisibletriggers(self);
+ if(vlen(self.origin - trace_ent.origin) > autocvar_g_sandbox_editor_distance_edit)
+ return world; // out of trace range
if(trace_ent.classname != "object")
return world; // entity is not an object
- if(trace_ent.owner != world)
- return world; // entity is an attached object
if(!permissions)
return trace_ent; // don't check permissions, anyone can edit this object
if(!trace_ent.crypto_idfp)
{
sandbox_ObjectAttach_Remove(e); // detach child objects
+ // if the object being removed has been selected for attachment by a player, unset it
+ entity head;
+ FOR_EACH_REALPLAYER(head) // bots can't have objects
+ {
+ if(head.object_attach == e)
+ head.object_attach = world;
+ }
+
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; }
string sandbox_ObjectPort_Save(entity e, float database)
{
// save object properties, and return them as a string
- float i;
+ float i = 0;
string s;
entity head;
if(slot)
{
// properties stored only for child objects
- if(gettaginfo_name) port_string[slot] = strcat(port_string[slot], "\"", gettaginfo_name, "\" "); else port_string[slot] = strcat(port_string[slot], "- "); // none
+ if(gettaginfo_name) port_string[slot] = strcat(port_string[slot], "\"", gettaginfo_name, "\" "); else port_string[slot] = strcat(port_string[slot], "\"\" "); // none
}
else
{
port_string[slot] = strcat(port_string[slot], ftos(solidity), " ");
port_string[slot] = strcat(port_string[slot], ftos(physics), " ");
port_string[slot] = strcat(port_string[slot], ftos(head.damageforcescale), " ");
- if(head.material) port_string[slot] = strcat(port_string[slot], "\"", head.material, "\" "); else port_string[slot] = strcat(port_string[slot], "- "); // none
+ if(head.material) port_string[slot] = strcat(port_string[slot], "\"", head.material, "\" "); else port_string[slot] = strcat(port_string[slot], "\"\" "); // none
if(database)
{
// 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
+ 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, "\" ");
}
// now apply the array to a simple string, with the ; symbol separating objects
+ s = "";
for(i = 0; i <= MAX_STORAGE_ATTACHMENTS; ++i)
{
if(port_string[i])
if(i)
{
// properties stored only for child objects
- if(argv(argv_num) != "-") tagname = argv(argv_num); else tagname = string_null; ++argv_num;
+ if(argv(argv_num) != "") tagname = argv(argv_num); else tagname = string_null; ++argv_num;
}
else
{
e.solid = e.old_solid = stof(argv(argv_num)); ++argv_num;
e.movetype = e.old_movetype = stof(argv(argv_num)); ++argv_num;
e.damageforcescale = stof(argv(argv_num)); ++argv_num;
- if(e.material) strunzone(e.material); if(argv(argv_num) != "-") e.material = strzone(argv(argv_num)); else e.material = string_null; ++argv_num;
+ if(e.material) strunzone(e.material); if(argv(argv_num) != "") e.material = strzone(argv(argv_num)); else e.material = string_null; ++argv_num;
if(database)
{
// 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.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;
print_to(self, strcat("^2SANDBOX - INFO: ^7Object is owned by \"^7", e.netname, "^7\", created \"^3", e.message, "^7\", last edited \"^3", e.message2, "^7\""));
return TRUE;
case "mesh":
- for(i = 1; gettaginfo(e, i); i++)
+ s = "";
+ FOR_EACH_TAG(e)
s = strcat(s, "^7\"^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: ", s));
return TRUE;
case "attachments":
// this should show the same info as 'mesh' but for attachments
+ s = "";
entity head;
+ i = 0;
for(head = world; (head = find(head, classname, "object")); )
{
if(head.owner == e)
return TRUE;
}
+MUTATOR_HOOKFUNCTION(sandbox_SetModname)
+{
+ modname = "Sandbox";
+ return TRUE;
+}
+
MUTATOR_DEFINITION(sandbox)
{
MUTATOR_HOOK(SV_ParseClientCommand, sandbox_PlayerCommand, CBC_ORDER_ANY);
MUTATOR_HOOK(SV_StartFrame, sandbox_StartFrame, CBC_ORDER_ANY);
+ MUTATOR_HOOK(SetModname, sandbox_SetModname, CBC_ORDER_ANY);
MUTATOR_ONADD
{