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