4 #include <common/util.qh>
5 #include <server/defs.qh>
11 // "classname" "target_spawn"
12 // "message" "fieldname value fieldname value ..."
14 // 1 = call the spawn function
15 // 2 = trigger on map load
17 float target_spawn_initialized;
18 .void(entity this) target_spawn_spawnfunc;
19 float target_spawn_spawnfunc_field;
20 .entity target_spawn_activator;
21 .float target_spawn_id;
22 float target_spawn_count;
24 void target_spawn_helper_setmodel(entity this)
26 _setmodel(this, this.model);
29 void target_spawn_helper_setsize(entity this)
31 setsize(this, this.mins, this.maxs);
34 void target_spawn_edit_entity(entity this, entity e, string msg, entity kt, entity t2, entity t3, entity t4, entity act, entity trigger)
36 float i, n, valuefieldpos;
37 string key, value, valuefield, valueoffset, valueoffsetrandom;
41 n = tokenize_console(msg);
43 for(i = 0; i < n-1; i += 2)
50 data.y = FIELD_STRING;
54 data = stov(db_get(TemporaryDB, strcat("/target_spawn/field/", key)));
55 if(data.y == 0) // undefined field, i.e., invalid type
57 LOG_INFO("target_spawn: invalid/unknown entity key ", key, " specified, ignored!\n");
61 if(substring(value, 0, 1) == "$")
63 value = substring(value, 1, strlen(value) - 1);
64 if(substring(value, 0, 1) == "$")
66 // deferred replacement
68 // useful for creating target_spawns with this!
73 valuefieldpos = strstrofs(value, "+", 0);
75 if(valuefieldpos != -1)
77 valueoffset = substring(value, valuefieldpos + 1, strlen(value) - valuefieldpos - 1);
78 value = substring(value, 0, valuefieldpos);
81 valuefieldpos = strstrofs(valueoffset, "+", 0);
82 valueoffsetrandom = "";
83 if(valuefieldpos != -1)
85 valueoffsetrandom = substring(valueoffset, valuefieldpos + 1, strlen(valueoffset) - valuefieldpos - 1);
86 valueoffset = substring(valueoffset, 0, valuefieldpos);
89 valuefieldpos = strstrofs(value, ".", 0);
91 if(valuefieldpos != -1)
93 valuefield = substring(value, valuefieldpos + 1, strlen(value) - valuefieldpos - 1);
94 value = substring(value, 0, valuefieldpos);
102 else if(value == "activator")
107 else if(value == "other")
112 else if(value == "pusher")
114 if(time < act.pushltime)
115 valueent = act.pusher;
120 else if(value == "target")
125 else if(value == "killtarget")
130 else if(value == "target2")
135 else if(value == "target3")
140 else if(value == "target4")
145 else if(value == "time")
152 LOG_INFO("target_spawn: invalid/unknown variable replacement ", value, " specified, ignored!\n");
159 value = ftos(etof(valueent));
165 LOG_INFO("target_spawn: try to get a field of a non-entity, ignored!\n");
168 data2 = stov(db_get(TemporaryDB, strcat("/target_spawn/field/", valuefield)));
169 if(data2_y == 0) // undefined field, i.e., invalid type
171 LOG_INFO("target_spawn: invalid/unknown entity key replacement ", valuefield, " specified, ignored!\n");
174 value = getentityfieldstring(data2_x, valueent);
177 if(valueoffset != "")
182 value = strcat(value, valueoffset);
185 value = ftos(stof(value) + stof(valueoffset));
188 value = vtos(stov(value) + stov(valueoffset));
191 LOG_INFO("target_spawn: only string, float and vector fields can do calculations, calculation ignored!\n");
196 if(valueoffsetrandom != "")
201 value = ftos(stof(value) + random() * stof(valueoffsetrandom));
204 data2 = stov(valueoffsetrandom);
205 value = vtos(stov(value) + random() * data2_x * '1 0 0' + random() * data2_y * '0 1 0' + random() * data2_z * '0 0 1');
208 LOG_INFO("target_spawn: only float and vector fields can do random calculations, calculation ignored!\n");
216 if(substring(value, 0, 1) == "_")
217 value = strcat("target_spawn_helper", value);
218 putentityfieldstring(target_spawn_spawnfunc_field, e, value);
220 e.target_spawn_spawnfunc(e);
222 // We called an external function, so we have to re-tokenize msg.
223 n = tokenize_console(msg);
227 if(data.y == FIELD_VECTOR)
228 value = strreplace("'", "", value); // why?!?
229 putentityfieldstring(data.x, e, value);
234 void target_spawn_useon(entity e, entity this, entity actor, entity trigger)
236 this.target_spawn_activator = actor;
237 target_spawn_edit_entity(
241 find(world, targetname, this.killtarget),
242 find(world, targetname, this.target2),
243 find(world, targetname, this.target3),
244 find(world, targetname, this.target4),
250 bool target_spawn_cancreate(entity this)
256 if(c == 0) // no limit?
259 ++c; // increase count to not include MYSELF
260 for(e = world; (e = findfloat(e, target_spawn_id, this.target_spawn_id)); --c)
263 // if c now is 0, we have AT LEAST the given count (maybe more), so don't spawn any more
269 void target_spawn_use(entity this, entity actor, entity trigger)
271 if(this.target == "")
274 if(!target_spawn_cancreate(this))
277 e.spawnfunc_checked = true;
278 target_spawn_useon(e, this, actor, trigger);
279 e.target_spawn_id = this.target_spawn_id;
281 else if(this.target == "*activator")
285 target_spawn_useon(actor, this, actor, trigger);
290 for(entity e = world; (e = find(e, targetname, this.target)); )
291 target_spawn_useon(e, this, actor, trigger);
295 void target_spawn_spawnfirst(entity this)
297 entity act = this.target_spawn_activator;
298 if(this.spawnflags & 2)
299 target_spawn_use(this, act, NULL);
302 void initialize_field_db()
304 if(!target_spawn_initialized)
311 n = numentityfields();
312 for(i = 0; i < n; ++i)
314 fn = entityfieldname(i);
315 ft = entityfieldtype(i);
316 next = i * '1 0 0' + ft * '0 1 0' + '0 0 1';
317 prev = stov(db_get(TemporaryDB, strcat("/target_spawn/field/", fn)));
320 db_put(TemporaryDB, strcat("/target_spawn/field/", fn), vtos(next));
321 if(fn == "target_spawn_spawnfunc")
322 target_spawn_spawnfunc_field = i;
326 target_spawn_initialized = 1;
330 spawnfunc(target_spawn)
332 initialize_field_db();
333 this.use = target_spawn_use;
334 this.message = strzone(strreplace("'", "\"", this.message));
335 this.target_spawn_id = ++target_spawn_count;
336 InitializeEntity(this, target_spawn_spawnfirst, INITPRIO_LAST);