]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/mutators/sandbox.qc
Add a message for invalid commands
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / sandbox.qc
1 .string clipboard_model;
2 .float clipboard_movetype;
3
4 entity sandbox_EditObject()
5 {
6         // returns the traced entity if the player can edit it, and world if not
7
8         makevectors(self.v_angle);
9         WarpZone_TraceLine(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * autocvar_g_sandbox_editor_distance_edit, MOVE_NORMAL, self);
10         if(trace_ent.classname == "object" && trace_ent.realowner == self)
11                 return trace_ent;
12         else
13                 return world;
14 }
15
16 entity sandbox_SpawnObject()
17 {
18         // spawn a new object with default properties
19
20         entity e;
21         e = spawn();
22         e.realowner = self;
23         e.classname = "object";
24         e.takedamage = DAMAGE_NO;
25         e.movetype = MOVETYPE_TOSS;
26         e.solid = SOLID_BSP;
27
28         // set origin and direction based on player position and view angle
29         makevectors(self.v_angle);
30         WarpZone_TraceLine(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * autocvar_g_sandbox_editor_distance_spawn, MOVE_NORMAL, self);
31         setorigin(e, trace_endpos);
32         e.angles_y = self.v_angle_y;
33
34         return e;
35 }
36
37 MUTATOR_HOOKFUNCTION(sandbox_PlayerCommand)
38 {
39         if(MUTATOR_RETURNVALUE) // command was already handled?
40                 return FALSE;
41         if(cmd_name == "g_sandbox")
42         {
43                 if(cmd_argc < 2)
44                 {
45                         print_to(self, "Sandbox mode is active. For usage information, type 'sandbox help'");
46                         return TRUE;
47                 }
48
49                 entity e;
50                 if(argv(1) == "help")
51                 {
52                         print_to(self, "You can use the following sandbox commands:");
53                         print_to(self, "^7\"^2spawn_item ^3item^7\" spawns the specified item in front of the player. Only weapons are currently supported");
54                         print_to(self, "^7\"^2spawn_object ^3models/foo/bar.md3^7\" spawns a new object in front of the player, and gives it the specified model");
55                         print_to(self, "^7\"^2remove_object^7\" removes the object the player is looking at. Players can only remove their own objects");
56                         print_to(self, "^7\"^2duplicate_object_copy^7\" copies the object the player is looking at. Players can only copy their own objects");
57                         print_to(self, "^7\"^2duplicate_object_paste^7\" pastes the copied object in front of the player");
58                         print_to(self, "^7The ^1drag object ^7key can be used to grab and carry objects. Players can only grab their own objects");
59                         return TRUE;
60                 }
61                 else if(argv(1) == "spawn_item")
62                 {
63                         // only weapons are currently supported
64
65                         if(cmd_argc < 3)
66                         {
67                                 print_to(self, "WARNING: Attempted to spawn an item without specifying its type. Please specify the name of your item after the 'spawn_item' command");
68                                 return TRUE;
69                         }
70
71                         // spawn a new item
72                         float i;
73                         makevectors(self.v_angle);
74                         WarpZone_TraceLine(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * autocvar_g_sandbox_editor_distance_spawn, MOVE_NOMONSTERS, self);
75
76                         for(i = WEP_FIRST; i <= WEP_LAST; ++i)
77                         {
78                                 e = get_weaponinfo(i);
79                                 if(e.netname == argv(2))
80                                 {
81                                         W_ThrowNewWeapon(self, i, FALSE, trace_endpos, '0 0 0');
82                                         if(autocvar_g_sandbox_info)
83                                                 print(strcat(self.netname, " spawned a ^2", e.netname, "^7 at origin ", vtos(e.origin), "\n"));
84                                         return TRUE;
85                                 }
86                         }
87
88                         print_to(self, "WARNING: Attempted to spawn an invalid or unsupported item. See 'sandbox help' for allowed items");
89                         return TRUE;
90                 }
91                 else if(argv(1) == "spawn_object")
92                 {
93                         // don't allow spawning objects without a model
94                         if(cmd_argc < 3)
95                         {
96                                 print_to(self, "WARNING: Attempted to spawn an object without specifying a model. Please specify the path to your model file after the 'spawn_object' command");
97                                 return TRUE;
98                         }
99                         else if not(fexists(argv(2)))
100                         {
101                                 print_to(self, "WARNING: Attempted to spawn an object with a non-existent model. Make sure the path to your model file is correct");
102                                 return TRUE;
103                         }
104
105                         e = sandbox_SpawnObject();
106                         setmodel(e, argv(2));
107
108                         if(autocvar_g_sandbox_info)
109                                 print(strcat(self.netname, " spawned an object at origin ", vtos(e.origin), "\n"));
110
111                         return TRUE;
112                 }
113                 else if(argv(1) == "remove_object")
114                 {
115                         e = sandbox_EditObject();
116                         if(e != world)
117                         {
118                                 if(autocvar_g_sandbox_info)
119                                         print(strcat(self.netname, " removed an object at origin ", vtos(e.origin), "\n"));
120                                 remove(e);
121                                 e = world;
122                                 return TRUE;
123                         }
124
125                         print_to(self, "WARNING: Object could not be removed. Make sure you are facing an object that belongs to you");
126                         return TRUE;
127                 }
128                 else if(argv(1) == "duplicate_object_copy")
129                 {
130                         // copies customizable properties of the selected object to the clipboard
131
132                         e = sandbox_EditObject(); // you can only copy objects you can edit, so this works
133                         if(e != world)
134                         {
135                                 // -------- COPY PROPERTIES --------
136                                 self.clipboard_model = e.model;
137                                 self.clipboard_movetype = e.movetype;
138                                 // -------- COPY PROPERTIES --------
139
140                                 print_to(self, "Object copied to clipboard");
141                                 return TRUE;
142                         }
143
144                         print_to(self, "WARNING: Object could not be copied. Make sure you are facing an object that belongs to you");
145                         return TRUE;
146                 }
147                 else if(argv(1) == "duplicate_object_paste")
148                 {
149                         // spawns a new object using the properties in the player's clipboard
150
151                         if(self.clipboard_model == "") // no object in clipboard
152                         {
153                                 print_to(self, "WARNING: No object in clipboard. You must copy an object before you can paste it");
154                                 return TRUE;
155                         }
156
157                         e = sandbox_SpawnObject();
158
159                         // -------- PASTE PROPERTIES --------
160                         setmodel(e, self.clipboard_model);
161                         e.movetype = self.clipboard_movetype;
162                         // -------- PASTE PROPERTIES --------
163
164                         print_to(self, "Object pasted");
165                         if(autocvar_g_sandbox_info)
166                                 print(strcat(self.netname, " pasted an object at origin ", vtos(e.origin), "\n"));
167
168                         return TRUE;
169                 }
170                 else
171                 {
172                         print_to(self, "Invalid command. For usage information, type 'sandbox help'");
173                         return TRUE;
174                 }
175         }
176         return FALSE;
177 }
178
179 MUTATOR_HOOKFUNCTION(sandbox_PlayerPreThink)
180 {
181         // if the player is close enough to their object, they can drag it
182
183         if(autocvar_sv_cheats)
184                 return FALSE; // cheat dragging is used instead
185
186         // grab is TRUE if the object can be picked up. While an object is being carried, the Drag() function
187         // must execute for it either way, otherwise it would cause bugs if it went out of the player's trace.
188         // This also makes sure that an object can only pe picked up if in range, but does not get dropped if
189         // it goes out of range while slinging it around.
190
191         entity e;
192         float grab;
193
194         e = sandbox_EditObject();
195         if(e != world && vlen(e.origin - self.origin) <= autocvar_g_sandbox_editor_distance_edit)
196                 grab = TRUE;
197
198         if(Drag(e, grab)) // execute dragging
199         {
200                 if(autocvar_g_sandbox_info)
201                         print(strcat(self.netname, " grabbed an object at origin ", vtos(e.origin), "\n"));
202                 return TRUE;
203         }
204
205         return FALSE;
206 }
207
208 MUTATOR_DEFINITION(sandbox)
209 {
210         MUTATOR_HOOK(SV_ParseClientCommand, sandbox_PlayerCommand, CBC_ORDER_ANY);
211         MUTATOR_HOOK(PlayerPreThink, sandbox_PlayerPreThink, CBC_ORDER_ANY);
212
213         return 0;
214 }