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