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