]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/target/spawn.qc
Merge branch 'master' into Mario/qc_physics_prehax
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / triggers / target / spawn.qc
1 #if defined(CSQC)
2 #elif defined(MENUQC)
3 #elif defined(SVQC)
4         #include "../../../dpdefs/progsdefs.qh"
5     #include "../../../dpdefs/dpextensions.qh"
6     #include "../../util.qh"
7     #include "../../../server/defs.qh"
8 #endif
9
10 #ifdef SVQC
11
12 // spawner entity
13 // "classname" "target_spawn"
14 // "message" "fieldname value fieldname value ..."
15 // "spawnflags"
16 //   1 = call the spawn function
17 //   2 = trigger on map load
18
19 float target_spawn_initialized;
20 .void() target_spawn_spawnfunc;
21 float target_spawn_spawnfunc_field;
22 .entity target_spawn_activator;
23 .float target_spawn_id;
24 float target_spawn_count;
25
26 void target_spawn_helper_setmodel()
27 {
28         setmodel(self, self.model);
29 }
30
31 void target_spawn_helper_setsize()
32 {
33         setsize(self, self.mins, self.maxs);
34 }
35
36 void target_spawn_edit_entity(entity e, string msg, entity kt, entity t2, entity t3, entity t4, entity act)
37 {
38         float i, n, valuefieldpos;
39         string key, value, valuefield, valueoffset, valueoffsetrandom;
40         entity valueent;
41         vector data, data2;
42         entity oldself;
43         entity oldactivator;
44
45         n = tokenize_console(msg);
46
47         for(i = 0; i < n-1; i += 2)
48         {
49                 key = argv(i);
50                 value = argv(i+1);
51                 if(key == "$")
52                 {
53                         data.x = -1;
54                         data.y = FIELD_STRING;
55                 }
56                 else
57                 {
58                         data = stov(db_get(TemporaryDB, strcat("/target_spawn/field/", key)));
59                         if(data.y == 0) // undefined field, i.e., invalid type
60                         {
61                                 print("target_spawn: invalid/unknown entity key ", key, " specified, ignored!\n");
62                                 continue;
63                         }
64                 }
65                 if(substring(value, 0, 1) == "$")
66                 {
67                         value = substring(value, 1, strlen(value) - 1);
68                         if(substring(value, 0, 1) == "$")
69                         {
70                                 // deferred replacement
71                                 // do nothing
72                                 // useful for creating target_spawns with this!
73                         }
74                         else
75                         {
76                                 // replace me!
77                                 valuefieldpos = strstrofs(value, "+", 0);
78                                 valueoffset = "";
79                                 if(valuefieldpos != -1)
80                                 {
81                                         valueoffset = substring(value, valuefieldpos + 1, strlen(value) - valuefieldpos - 1);
82                                         value = substring(value, 0, valuefieldpos);
83                                 }
84
85                                 valuefieldpos = strstrofs(valueoffset, "+", 0);
86                                 valueoffsetrandom = "";
87                                 if(valuefieldpos != -1)
88                                 {
89                                         valueoffsetrandom = substring(valueoffset, valuefieldpos + 1, strlen(valueoffset) - valuefieldpos - 1);
90                                         valueoffset = substring(valueoffset, 0, valuefieldpos);
91                                 }
92
93                                 valuefieldpos = strstrofs(value, ".", 0);
94                                 valuefield = "";
95                                 if(valuefieldpos != -1)
96                                 {
97                                         valuefield = substring(value, valuefieldpos + 1, strlen(value) - valuefieldpos - 1);
98                                         value = substring(value, 0, valuefieldpos);
99                                 }
100
101                                 if(value == "self")
102                                 {
103                                         valueent = self;
104                                         value = "";
105                                 }
106                                 else if(value == "activator")
107                                 {
108                                         valueent = act;
109                                         value = "";
110                                 }
111                                 else if(value == "other")
112                                 {
113                                         valueent = other;
114                                         value = "";
115                                 }
116                                 else if(value == "pusher")
117                                 {
118                                         if(time < act.pushltime)
119                                                 valueent = act.pusher;
120                                         else
121                                                 valueent = world;
122                                         value = "";
123                                 }
124                                 else if(value == "target")
125                                 {
126                                         valueent = e;
127                                         value = "";
128                                 }
129                                 else if(value == "killtarget")
130                                 {
131                                         valueent = kt;
132                                         value = "";
133                                 }
134                                 else if(value == "target2")
135                                 {
136                                         valueent = t2;
137                                         value = "";
138                                 }
139                                 else if(value == "target3")
140                                 {
141                                         valueent = t3;
142                                         value = "";
143                                 }
144                                 else if(value == "target4")
145                                 {
146                                         valueent = t4;
147                                         value = "";
148                                 }
149                                 else if(value == "time")
150                                 {
151                                         valueent = world;
152                                         value = ftos(time);
153                                 }
154                                 else
155                                 {
156                                         print("target_spawn: invalid/unknown variable replacement ", value, " specified, ignored!\n");
157                                         continue;
158                                 }
159
160                                 if(valuefield == "")
161                                 {
162                                         if(value == "")
163                                                 value = ftos(num_for_edict(valueent));
164                                 }
165                                 else
166                                 {
167                                         if(value != "")
168                                         {
169                                                 print("target_spawn: try to get a field of a non-entity, ignored!\n");
170                                                 continue;
171                                         }
172                                         data2 = stov(db_get(TemporaryDB, strcat("/target_spawn/field/", valuefield)));
173                                         if(data2_y == 0) // undefined field, i.e., invalid type
174                                         {
175                                                 print("target_spawn: invalid/unknown entity key replacement ", valuefield, " specified, ignored!\n");
176                                                 continue;
177                                         }
178                                         value = getentityfieldstring(data2_x, valueent);
179                                 }
180
181                                 if(valueoffset != "")
182                                 {
183                                         switch(data.y)
184                                         {
185                                                 case FIELD_STRING:
186                                                         value = strcat(value, valueoffset);
187                                                         break;
188                                                 case FIELD_FLOAT:
189                                                         value = ftos(stof(value) + stof(valueoffset));
190                                                         break;
191                                                 case FIELD_VECTOR:
192                                                         value = vtos(stov(value) + stov(valueoffset));
193                                                         break;
194                                                 default:
195                                                         print("target_spawn: only string, float and vector fields can do calculations, calculation ignored!\n");
196                                                         break;
197                                         }
198                                 }
199
200                                 if(valueoffsetrandom != "")
201                                 {
202                                         switch(data.y)
203                                         {
204                                                 case FIELD_FLOAT:
205                                                         value = ftos(stof(value) + random() * stof(valueoffsetrandom));
206                                                         break;
207                                                 case FIELD_VECTOR:
208                                                         data2 = stov(valueoffsetrandom);
209                                                         value = vtos(stov(value) + random() * data2_x * '1 0 0' + random() * data2_y * '0 1 0' + random() * data2_z * '0 0 1');
210                                                         break;
211                                                 default:
212                                                         print("target_spawn: only float and vector fields can do random calculations, calculation ignored!\n");
213                                                         break;
214                                         }
215                                 }
216                         }
217                 }
218                 if(key == "$")
219                 {
220                         if(substring(value, 0, 1) == "_")
221                                 value = strcat("target_spawn_helper", value);
222                         putentityfieldstring(target_spawn_spawnfunc_field, e, value);
223
224                         oldself = self;
225                         oldactivator = activator;
226
227                         self = e;
228                         activator = act;
229
230                         self.target_spawn_spawnfunc();
231
232                         self = oldself;
233                         activator = oldactivator;
234
235                         // We called an external function, so we have to re-tokenize msg.
236                         n = tokenize_console(msg);
237                 }
238                 else
239                 {
240                         if(data.y == FIELD_VECTOR)
241                                 value = strreplace("'", "", value); // why?!?
242                         putentityfieldstring(data.x, e, value);
243                 }
244         }
245 }
246
247 void target_spawn_useon(entity e)
248 {
249         self.target_spawn_activator = activator;
250         target_spawn_edit_entity(
251                 e,
252                 self.message,
253                 find(world, targetname, self.killtarget),
254                 find(world, targetname, self.target2),
255                 find(world, targetname, self.target3),
256                 find(world, targetname, self.target4),
257                 activator
258         );
259 }
260
261 float target_spawn_cancreate()
262 {
263         float c;
264         entity e;
265
266         c = self.count;
267         if(c == 0) // no limit?
268                 return 1;
269
270         ++c; // increase count to not include MYSELF
271         for(e = world; (e = findfloat(e, target_spawn_id, self.target_spawn_id)); --c)
272                 ;
273
274         // if c now is 0, we have AT LEAST the given count (maybe more), so don't spawn any more
275         if(c == 0)
276                 return 0;
277         return 1;
278 }
279
280 void target_spawn_use()
281 {
282         entity e;
283
284         if(self.target == "")
285         {
286                 // spawn new entity
287                 if(!target_spawn_cancreate())
288                         return;
289                 e = spawn();
290                 target_spawn_useon(e);
291                 e.target_spawn_id = self.target_spawn_id;
292         }
293         else if(self.target == "*activator")
294         {
295                 // edit entity
296                 if(activator)
297                         target_spawn_useon(activator);
298         }
299         else
300         {
301                 // edit entity
302                 for(e = world; (e = find(e, targetname, self.target)); )
303                         target_spawn_useon(e);
304         }
305 }
306
307 void target_spawn_spawnfirst()
308 {
309         activator = self.target_spawn_activator;
310         if(self.spawnflags & 2)
311                 target_spawn_use();
312 }
313
314 void initialize_field_db()
315 {
316         if(!target_spawn_initialized)
317         {
318                 float n, i;
319                 string fn;
320                 vector prev, new;
321                 float ft;
322
323                 n = numentityfields();
324                 for(i = 0; i < n; ++i)
325                 {
326                         fn = entityfieldname(i);
327                         ft = entityfieldtype(i);
328                         new = i * '1 0 0' + ft * '0 1 0' + '0 0 1';
329                         prev = stov(db_get(TemporaryDB, strcat("/target_spawn/field/", fn)));
330                         if(prev.y == 0)
331                         {
332                                 db_put(TemporaryDB, strcat("/target_spawn/field/", fn), vtos(new));
333                                 if(fn == "target_spawn_spawnfunc")
334                                         target_spawn_spawnfunc_field = i;
335                         }
336                 }
337
338                 target_spawn_initialized = 1;
339         }
340 }
341
342 void spawnfunc_target_spawn()
343 {
344         initialize_field_db();
345         self.use = target_spawn_use;
346         self.message = strzone(strreplace("'", "\"", self.message));
347         self.target_spawn_id = ++target_spawn_count;
348         InitializeEntity(self, target_spawn_spawnfirst, INITPRIO_LAST);
349 }
350 #endif