]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/target_spawn.qc
forgot this one
[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
34         n = tokenize_sane(self.message);
35         self.target_spawn_activator = activator;
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 = activator;
99                                         value = "";
100                                 }
101                                 else if(value == "pusher")
102                                 {
103                                         if(time < activator.pushltime)
104                                                 valueent = activator.pusher;
105                                         else
106                                                 valueent = world;
107                                         value = "";
108                                 }
109                                 else if(value == "target")
110                                 {
111                                         valueent = e;
112                                         value = "";
113                                 }
114                                 else if(value == "time")
115                                 {
116                                         valueent = world;
117                                         value = ftos(time);
118                                 }
119                                 else
120                                 {
121                                         print("target_spawn: invalid/unknown variable replacement ", value, " specified, ignored!\n");
122                                         continue;
123                                 }
124
125                                 if(valuefield == "")
126                                 {
127                                         if(value == "")
128                                                 value = ftos(num_for_edict(valueent));
129                                 }
130                                 else
131                                 {
132                                         if(value != "")
133                                         {
134                                                 print("target_spawn: try to get a field of a non-entity, ignored!\n");
135                                                 continue;
136                                         }
137                                         data2 = stov(db_get(TemporaryDB, strcat("/target_spawn/field/", valuefield)));
138                                         if(data2_y == 0) // undefined field, i.e., invalid type
139                                         {
140                                                 print("target_spawn: invalid/unknown entity key replacement ", valuefield, " specified, ignored!\n");
141                                                 continue;
142                                         }
143                                         value = getentityfieldstring(data2_x, valueent);
144                                 }
145
146                                 if(valueoffset != "")
147                                 {
148                                         switch(data_y)
149                                         {
150                                                 case FIELD_STRING:
151                                                         value = strcat(value, valueoffset);
152                                                         break;
153                                                 case FIELD_FLOAT:
154                                                         value = ftos(stof(value) + stof(valueoffset));
155                                                         break;
156                                                 case FIELD_VECTOR:
157                                                         value = vtos(stov(value) + stov(valueoffset));
158                                                         break;
159                                                 default:
160                                                         print("target_spawn: only string, float and vector fields can do calculations, calculation ignored!\n");
161                                                         break;
162                                         }
163                                 }
164
165                                 if(valueoffsetrandom != "")
166                                 {
167                                         switch(data_y)
168                                         {
169                                                 case FIELD_FLOAT:
170                                                         value = ftos(stof(value) + random() * stof(valueoffsetrandom));
171                                                         break;
172                                                 case FIELD_VECTOR:
173                                                         data2 = stov(valueoffsetrandom);
174                                                         value = vtos(stov(value) + random() * data2_x * '1 0 0' + random() * data2_y * '0 1 0' + random() * data2_z * '0 0 1');
175                                                         break;
176                                                 default:
177                                                         print("target_spawn: only float and vector fields can do random calculations, calculation ignored!\n");
178                                                         break;
179                                         }
180                                 }
181                         }
182                 }
183                 if(key == "$")
184                 {
185                         if(substring(value, 0, 1) == "_")
186                                 value = strcat("target_spawn_helper", value);
187                         putentityfieldstring(target_spawn_spawnfunc_field, e, value);
188
189                         oldself = self;
190                         oldactivator = activator;
191
192                         self = e;
193                         activator = oldself.target_spawn_activator;
194
195                         self.target_spawn_spawnfunc();
196
197                         self = oldself;
198                         activator = oldactivator;
199                 }
200                 else
201                 {
202                         if(data_y == FIELD_VECTOR)
203                                 value = strreplace("'", "", value); // why?!?
204                         putentityfieldstring(data_x, e, value);
205                 }
206         }
207 }
208
209 float target_spawn_cancreate()
210 {
211         float c;
212         entity e;
213
214         c = self.count;
215         if(c == 0) // no limit?
216                 return 1;
217
218         ++c; // increase count to not include MYSELF
219         for(e = world; (e = findfloat(e, target_spawn_id, self.target_spawn_id)); --c)
220                 ;
221         
222         // if c now is 0, we have AT LEAST the given count (maybe more), so don't spawn any more
223         if(c == 0)
224                 return 0;
225         return 1;
226 }
227
228 void target_spawn_use()
229 {
230         entity e;
231
232         if(self.target == "")
233         {
234                 // spawn new entity
235                 if(!target_spawn_cancreate())
236                         return;
237                 e = spawn();
238                 target_spawn_useon(e);
239                 e.target_spawn_id = self.target_spawn_id;
240         }
241         else
242         {
243                 // edit entity
244                 for(e = world; (e = find(e, targetname, self.target)); )
245                         target_spawn_useon(e);
246         }
247 }
248
249 void target_spawn_spawnfirst()
250 {
251         activator = self.target_spawn_activator;
252         if(self.spawnflags & 2)
253                 target_spawn_use();
254 }
255
256 void initialize_field_db()
257 {
258         if(!target_spawn_initialized)
259         {
260                 float n, i;
261                 string fn;
262                 vector prev, new;
263                 float ft;
264
265                 n = numentityfields();
266                 for(i = 0; i < n; ++i)
267                 {
268                         fn = entityfieldname(i);
269                         ft = entityfieldtype(i);
270                         new = i * '1 0 0' + ft * '0 1 0' + '0 0 1';
271                         prev = stov(db_get(TemporaryDB, strcat("/target_spawn/field/", fn)));
272                         if(prev_y == 0)
273                         {
274                                 db_put(TemporaryDB, strcat("/target_spawn/field/", fn), vtos(new));
275                                 if(fn == "target_spawn_spawnfunc")
276                                         target_spawn_spawnfunc_field = i;
277                         }
278                 }
279
280                 target_spawn_initialized = 1;
281         }
282 }
283
284 void spawnfunc_target_spawn()
285 {
286         initialize_field_db();
287         self.use = target_spawn_use;
288         self.message = strzone(strreplace("'", "\"", self.message));
289         self.target_spawn_id = ++target_spawn_count;
290         InitializeEntity(self, target_spawn_spawnfirst, INITPRIO_LAST);
291 }
292
293
294 void trigger_relay_if_use()
295 {
296         float n;
297         n = self.count;
298
299         // TODO make this generic AND faster than nextent()ing through all, if somehow possible
300         n = (cvar_string(self.netname) == cvar_string(self.message));
301         if(self.spawnflags & 1)
302                 n = !n;
303
304         if(n)
305                 SUB_UseTargets();
306 }
307
308 void spawnfunc_trigger_relay_if()
309 {
310         self.use = trigger_relay_if_use;
311 };