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