ATTRIB(XonoticSandboxToolsDialog, title, string, _("Sandbox Tools")) // ;)
ATTRIB(XonoticSandboxToolsDialog, color, vector, SKINCOLOR_DIALOG_SANDBOXTOOLS)
ATTRIB(XonoticSandboxToolsDialog, intendedWidth, float, 0.8)
- ATTRIB(XonoticSandboxToolsDialog, rows, float, 15)
+ ATTRIB(XonoticSandboxToolsDialog, rows, float, 16)
ATTRIB(XonoticSandboxToolsDialog, columns, float, 4)
ATTRIB(XonoticSandboxToolsDialog, name, string, "SandboxTools")
ENDCLASS(XonoticSandboxToolsDialog)
box.forbiddenCharacters = "\r\n\\\"$"; // don't care, isn't getting saved
box.maxLength = -127; // negative means encoded length in bytes
box.saveImmediately = 1;
+ me.TR(me);
+ me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Set solidity:"), '0 0 0', "sandbox object_edit solidity $menu_sandbox_edit_solidity", 0));
+ me.TD(me, 1, 0.75, e = makeXonoticRadioButton(1, "menu_sandbox_edit_solidity", "0", _("Non-solid")));
+ me.TD(me, 1, 0.75, e = makeXonoticRadioButton(1, "menu_sandbox_edit_solidity", "1", _("Solid")));
me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Set physics:"), '0 0 0', "sandbox object_edit physics $menu_sandbox_edit_physics", 0));
- me.TD(me, 1, 0.5, e = makeXonoticRadioButton(1, "menu_sandbox_edit_physics", "0", _("Static")));
- me.TD(me, 1, 0.5, e = makeXonoticRadioButton(1, "menu_sandbox_edit_physics", "1", _("Movable")));
- me.TD(me, 1, 0.5, e = makeXonoticRadioButton(1, "menu_sandbox_edit_physics", "2", _("Physical")));
+ me.TD(me, 1, 0.5, e = makeXonoticRadioButton(2, "menu_sandbox_edit_physics", "0", _("Static")));
+ me.TD(me, 1, 0.5, e = makeXonoticRadioButton(2, "menu_sandbox_edit_physics", "1", _("Movable")));
+ me.TD(me, 1, 0.5, e = makeXonoticRadioButton(2, "menu_sandbox_edit_physics", "2", _("Physical")));
me.TR(me);
me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Set scale:"), '0 0 0', "sandbox object_edit scale $menu_sandbox_edit_scale", 0));
me.TD(me, 1, 1.5, e = makeXonoticSlider(0.25, 2, 0.05, "menu_sandbox_edit_scale"));
ADD_CHEATS(self,cheating); \
return attempting
#define IS_CHEAT(i,argc,fr) \
- ++attempting; \
- if(!CheatsAllowed(i,argc,fr)) \
+ if((++attempting, !CheatsAllowed(i,argc,fr))) \
break
float CheatImpulse(float i)
// it goes out of range while slinging it around.
float drag;
- makevectors(self.v_angle);
- WarpZone_TraceLine(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * autocvar_g_grab_range, MOVE_NORMAL, self);
- switch(trace_ent.grab)
+ crosshair_trace_plusvisibletriggers(self);
+ if(vlen(self.origin - trace_ent.origin) <= autocvar_g_grab_range)
{
- case 0: // can't grab
- break;
- case 1: // owner can grab
- if(trace_ent.owner == self || trace_ent.realowner == self)
- drag = TRUE;
- break;
- case 2: // owner and team mates can grab
- if(!IsDifferentTeam(trace_ent.owner, self) || !IsDifferentTeam(trace_ent.realowner, self) || trace_ent.team == self.team)
+ switch(trace_ent.grab)
+ {
+ case 0: // can't grab
+ break;
+ case 1: // owner can grab
+ if(trace_ent.owner == self || trace_ent.realowner == self)
+ drag = TRUE;
+ break;
+ case 2: // owner and team mates can grab
+ if(!IsDifferentTeam(trace_ent.owner, self) || !IsDifferentTeam(trace_ent.realowner, self) || trace_ent.team == self.team)
+ drag = TRUE;
+ break;
+ case 3: // anyone can grab
drag = TRUE;
- break;
- case 3: // anyone can grab
- drag = TRUE;
- break;
- default:
- break;
+ break;
+ default:
+ break;
+ }
}
Drag(trace_ent, drag, FALSE); // execute dragging
}
self.nextthink = time;
}
+.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
- // attached objects are SOLID_NOT and don't risk getting traced
-
- 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);
+ // 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(!permissions)
}
}
-.float old_movetype;
void sandbox_ObjectAttach_Remove(entity e);
void sandbox_ObjectAttach_Set(entity e, entity parent, string s)
{
// we can't attach to an attachment, for obvious reasons
sandbox_ObjectAttach_Remove(e);
+ e.old_solid = e.solid; // persist solidity
e.old_movetype = e.movetype; // persist physics
e.movetype = MOVETYPE_FOLLOW;
e.solid = SOLID_NOT;
if(head.owner == e)
{
vector org;
- head.movetype = head.old_movetype; // restore persisted physics
- head.solid = SOLID_BBOX;
- head.takedamage = DAMAGE_AIM;
-
org = gettaginfo(head, 0);
setattachment(head, world, "");
head.owner = world;
// objects change origin and angles when detached, so apply previous position
setorigin(head, org);
head.angles = e.angles; // don't allow detached objects to spin or roll
+
+ head.solid = head.old_solid; // restore persisted solidity
+ head.movetype = head.old_movetype; // restore persisted physics
+ head.takedamage = DAMAGE_AIM;
}
}
}
{
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; }
for(head = world; (head = find(head, classname, "object")); )
{
// the main object needs to be first in the array [0] with attached objects following
- float slot, physics;
+ float slot, physics, solidity;
if(head == e) // this is the main object, place it first
{
slot = 0;
+ solidity = head.solid; // applied solidity is normal solidity for children
physics = head.movetype; // applied physics are normal physics for parents
}
else if(head.owner == e) // child object, list them in order
{
i += 1; // children start from 1
slot = i;
+ solidity = head.old_solid; // persisted solidity is normal solidity for children
physics = head.old_movetype; // persisted physics are normal physics for children
gettaginfo(head.owner, head.tag_index); // get the name of the tag our object is attached to, used further below
}
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], sprintf("\"%.9v\"", head.glowmod), " ");
port_string[slot] = strcat(port_string[slot], ftos(head.frame), " ");
port_string[slot] = strcat(port_string[slot], ftos(head.scale), " ");
+ 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, "\" ");
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.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.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, "^3glowmod \"value_x value_y value_z\" ^7- glow object color");
print_to(self, "^3frame value ^7- object animation frame, for self-animated models");
print_to(self, "^3scale value ^7- changes object scale. 0.5 is half size and 2 is double size");
+ print_to(self, "^3solidity value ^7- object collisions, 0 = non-solid, 1 = solid");
print_to(self, "^3physics value ^7- object physics, 0 = static, 1 = movable, 2 = physical");
print_to(self, "^3force value ^7- amount of force applied to objects that are shot");
print_to(self, "^3material value ^7- sets the material of the object. Default materials are: metal, stone, wood, flesh");
case "scale":
sandbox_ObjectEdit_Scale(e, stof(argv(3)));
break;
+ case "solidity":
+ switch(argv(3))
+ {
+ case "0": // non-solid
+ e.solid = SOLID_TRIGGER;
+ break;
+ case "1": // solid
+ e.solid = SOLID_BBOX;
+ break;
+ default:
+ break;
+ }
case "physics":
switch(argv(3))
{