5 #include <common/util.qh>
6 #include <common/weapons/_all.qh>
7 #include <common/stats.qh>
8 #include <server/g_world.qh>
14 // "classname" "target_spawn"
15 // "message" "fieldname value fieldname value ..."
17 // ON_MAPLOAD = trigger on map load
19 float target_spawn_initialized;
20 .void(entity this) target_spawn_spawnfunc;
21 float target_spawn_spawnfunc_field;
22 .entity target_spawn_activator;
23 .float target_spawn_id;
24 float target_spawn_count;
26 void target_spawn_helper_setmodel(entity this)
28 _setmodel(this, this.model);
31 void target_spawn_helper_setsize(entity this)
33 setsize(this, this.mins, this.maxs);
36 void target_spawn_edit_entity(entity this, entity e, string msg, entity kt, entity t2, entity t3, entity t4, entity act, entity trigger)
38 float i, n, valuefieldpos;
39 string key, value, valuefield, valueoffset, valueoffsetrandom;
43 n = tokenize_console(msg);
45 for(i = 0; i < n-1; i += 2)
52 data.y = FIELD_STRING;
56 data = stov(db_get(TemporaryDB, strcat("/target_spawn/field/", key)));
57 if(data.y == 0) // undefined field, i.e., invalid type
59 LOG_INFO("target_spawn: invalid/unknown entity key ", key, " specified, ignored!");
63 if(substring(value, 0, 1) == "$")
65 value = substring(value, 1, strlen(value) - 1);
66 if(substring(value, 0, 1) == "$")
68 // deferred replacement
70 // useful for creating target_spawns with this!
75 valuefieldpos = strstrofs(value, "+", 0);
77 if(valuefieldpos != -1)
79 valueoffset = substring(value, valuefieldpos + 1, strlen(value) - valuefieldpos - 1);
80 value = substring(value, 0, valuefieldpos);
83 valuefieldpos = strstrofs(valueoffset, "+", 0);
84 valueoffsetrandom = "";
85 if(valuefieldpos != -1)
87 valueoffsetrandom = substring(valueoffset, valuefieldpos + 1, strlen(valueoffset) - valuefieldpos - 1);
88 valueoffset = substring(valueoffset, 0, valuefieldpos);
91 valuefieldpos = strstrofs(value, ".", 0);
93 if(valuefieldpos != -1)
95 valuefield = substring(value, valuefieldpos + 1, strlen(value) - valuefieldpos - 1);
96 value = substring(value, 0, valuefieldpos);
104 else if(value == "activator")
109 else if(value == "other")
114 else if(value == "pusher")
116 if(time < act.pushltime)
117 valueent = act.pusher;
122 else if(value == "target")
127 else if(value == "killtarget")
132 else if(value == "target2")
137 else if(value == "target3")
142 else if(value == "target4")
147 else if(value == "time")
154 LOG_INFO("target_spawn: invalid/unknown variable replacement ", value, " specified, ignored!");
161 value = ftos(etof(valueent));
167 LOG_INFO("target_spawn: try to get a field of a non-entity, ignored!");
170 data2 = stov(db_get(TemporaryDB, strcat("/target_spawn/field/", valuefield)));
171 if(data2_y == 0) // undefined field, i.e., invalid type
173 LOG_INFO("target_spawn: invalid/unknown entity key replacement ", valuefield, " specified, ignored!");
176 value = getentityfieldstring(data2_x, valueent);
179 if(valueoffset != "")
184 value = strcat(value, valueoffset);
187 value = ftos(stof(value) + stof(valueoffset));
190 value = vtos(stov(value) + stov(valueoffset));
193 LOG_INFO("target_spawn: only string, float and vector fields can do calculations, calculation ignored!");
198 if(valueoffsetrandom != "")
203 value = ftos(stof(value) + random() * stof(valueoffsetrandom));
206 data2 = stov(valueoffsetrandom);
207 value = vtos(stov(value) + random() * data2_x * '1 0 0' + random() * data2_y * '0 1 0' + random() * data2_z * '0 0 1');
210 LOG_INFO("target_spawn: only float and vector fields can do random calculations, calculation ignored!");
218 if(substring(value, 0, 1) == "_")
219 value = strcat("target_spawn_helper", value);
220 putentityfieldstring(target_spawn_spawnfunc_field, e, value);
222 e.target_spawn_spawnfunc(e);
224 // We called an external function, so we have to re-tokenize msg.
225 n = tokenize_console(msg);
229 if(data.y == FIELD_VECTOR)
230 value = strreplace("'", "", value); // why?!?
231 putentityfieldstring(data.x, e, value);
236 void target_spawn_useon(entity e, entity this, entity actor, entity trigger)
238 this.target_spawn_activator = actor;
239 target_spawn_edit_entity(
243 find(NULL, targetname, this.killtarget),
244 find(NULL, targetname, this.target2),
245 find(NULL, targetname, this.target3),
246 find(NULL, targetname, this.target4),
252 bool target_spawn_cancreate(entity this)
258 if(c == 0) // no limit?
261 ++c; // increase count to not include MYSELF
262 for(e = NULL; (e = findfloat(e, target_spawn_id, this.target_spawn_id)); --c)
265 // if c now is 0, we have AT LEAST the given count (maybe more), so don't spawn any more
271 void target_spawn_use(entity this, entity actor, entity trigger)
273 if(this.target == "")
276 if(!target_spawn_cancreate(this))
279 e.spawnfunc_checked = true;
280 target_spawn_useon(e, this, actor, trigger);
281 e.target_spawn_id = this.target_spawn_id;
283 else if(this.target == "*activator")
287 target_spawn_useon(actor, this, actor, trigger);
292 FOREACH_ENTITY_STRING(targetname, this.target,
294 target_spawn_useon(it, this, actor, trigger);
299 void target_spawn_spawnfirst(entity this)
301 entity act = this.target_spawn_activator;
302 if(this.spawnflags & ON_MAPLOAD)
303 target_spawn_use(this, act, NULL);
306 void initialize_field_db()
308 if(!target_spawn_initialized)
315 n = numentityfields();
316 for(i = 0; i < n; ++i)
318 fn = entityfieldname(i);
319 ft = entityfieldtype(i);
320 next = i * '1 0 0' + ft * '0 1 0' + '0 0 1';
321 prev = stov(db_get(TemporaryDB, strcat("/target_spawn/field/", fn)));
324 db_put(TemporaryDB, strcat("/target_spawn/field/", fn), vtos(next));
325 if(fn == "target_spawn_spawnfunc")
326 target_spawn_spawnfunc_field = i;
330 target_spawn_initialized = 1;
334 spawnfunc(target_spawn)
336 initialize_field_db();
337 this.use = target_spawn_use;
338 this.message = strzone(strreplace("'", "\"", this.message));
339 this.target_spawn_id = ++target_spawn_count;
340 InitializeEntity(this, target_spawn_spawnfirst, INITPRIO_LAST);