diff options
author | Sebastian Leonhardt <sebastian.leonhardt@web.de> | 2016-01-08 01:05:36 +0100 |
---|---|---|
committer | Solomon Peachy <pizza@shaftnet.org> | 2024-06-30 17:24:16 -0400 |
commit | 102c3742487dba76ec72d5f56a2c3041344b2d68 (patch) | |
tree | 4931ad34d2cc0bac56d9984b9ead355d012ad63a /apps/plugins/xrick/e_them.c | |
parent | 6f1e67e5e318ba2fd0f5ec1892c7b6633ec6521c (diff) | |
download | rockbox-102c3742487dba76ec72d5f56a2c3041344b2d68.tar.gz rockbox-102c3742487dba76ec72d5f56a2c3041344b2d68.zip |
added xrick game
original xrick code by 'BigOrno' at:
http://www.bigorno.net/xrick/
Rockbox port, plus bugfixes at:
https://github.com/pierluigi-vicinanza/xrick
Further changes:
* Additonal fixes from g#3026
* Port to modern plugin API
* Add Pluginlib keymap fallback
* Support all >1bpp screens
* Fix build warnings in miniz
* Better error message when resources are missing
Change-Id: Id83928bc2539901b0221692f65cbca41389c58e7
Diffstat (limited to 'apps/plugins/xrick/e_them.c')
-rw-r--r-- | apps/plugins/xrick/e_them.c | 738 |
1 files changed, 738 insertions, 0 deletions
diff --git a/apps/plugins/xrick/e_them.c b/apps/plugins/xrick/e_them.c new file mode 100644 index 0000000000..465325b652 --- /dev/null +++ b/apps/plugins/xrick/e_them.c | |||
@@ -0,0 +1,738 @@ | |||
1 | /* | ||
2 | * xrick/e_them.c | ||
3 | * | ||
4 | * Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). | ||
5 | * Copyright (C) 2008-2014 Pierluigi Vicinanza. | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * The use and distribution terms for this software are contained in the file | ||
9 | * named README, which can be found in the root of this distribution. By | ||
10 | * using this software in any fashion, you are agreeing to be bound by the | ||
11 | * terms of this license. | ||
12 | * | ||
13 | * You must not remove this notice, or any other, from this software. | ||
14 | */ | ||
15 | |||
16 | #include "xrick/e_them.h" | ||
17 | |||
18 | #include "xrick/game.h" | ||
19 | #include "xrick/ents.h" | ||
20 | #include "xrick/e_rick.h" | ||
21 | #include "xrick/e_bomb.h" | ||
22 | #include "xrick/e_bullet.h" | ||
23 | #include "xrick/maps.h" | ||
24 | #include "xrick/util.h" | ||
25 | |||
26 | #define TYPE_1A (0x00) | ||
27 | #define TYPE_1B (0xff) | ||
28 | |||
29 | /* | ||
30 | * public vars | ||
31 | */ | ||
32 | U32 e_them_rndseed = 0; | ||
33 | |||
34 | /* | ||
35 | * local vars | ||
36 | */ | ||
37 | static U16 e_them_rndnbr = 0; | ||
38 | |||
39 | /* | ||
40 | * Check if entity boxtests with a lethal e_them i.e. something lethal | ||
41 | * in slot 0 and 4 to 8. | ||
42 | * | ||
43 | * ASM 122E | ||
44 | * | ||
45 | * e: entity slot number. | ||
46 | * ret: true/boxtests, false/not | ||
47 | */ | ||
48 | static bool | ||
49 | u_themtest(U8 e) | ||
50 | { | ||
51 | U8 i; | ||
52 | |||
53 | if ((ent_ents[0].n & ENT_LETHAL) && u_boxtest(e, 0)) | ||
54 | return true; | ||
55 | |||
56 | for (i = 4; i < 9; i++) | ||
57 | if ((ent_ents[i].n & ENT_LETHAL) && u_boxtest(e, i)) | ||
58 | return true; | ||
59 | |||
60 | return false; | ||
61 | } | ||
62 | |||
63 | |||
64 | /* | ||
65 | * Go zombie | ||
66 | * | ||
67 | * ASM 237B | ||
68 | */ | ||
69 | void | ||
70 | e_them_gozombie(U8 e) | ||
71 | { | ||
72 | #define offsx c1 | ||
73 | ent_ents[e].n = 0x47; /* zombie entity */ | ||
74 | ent_ents[e].front = true; | ||
75 | ent_ents[e].offsy = -0x0400; | ||
76 | #ifdef ENABLE_SOUND | ||
77 | syssnd_play(soundDie, 1); | ||
78 | #endif | ||
79 | game_score += 50; | ||
80 | if (ent_ents[e].flags & ENT_FLG_ONCE) { | ||
81 | /* make sure entity won't be activated again */ | ||
82 | map_marks[ent_ents[e].mark].ent |= MAP_MARK_NACT; | ||
83 | } | ||
84 | ent_ents[e].offsx = (ent_ents[e].x >= 0x80 ? -0x02 : 0x02); | ||
85 | #undef offsx | ||
86 | } | ||
87 | |||
88 | |||
89 | /* | ||
90 | * Action sub-function for e_them _t1a and _t1b | ||
91 | * | ||
92 | * Those two types move horizontally, and fall if they have to. | ||
93 | * Type 1a moves horizontally over a given distance and then | ||
94 | * u-turns and repeats; type 1b is more subtle as it does u-turns | ||
95 | * in order to move horizontally towards rick. | ||
96 | * | ||
97 | * ASM 2242 | ||
98 | */ | ||
99 | void | ||
100 | e_them_t1_action2(U8 e, U8 type) | ||
101 | { | ||
102 | #define offsx c1 | ||
103 | #define step_count c2 | ||
104 | U32 i; | ||
105 | S16 x, y; | ||
106 | U8 env0, env1; | ||
107 | |||
108 | /* by default, try vertical move. calculate new y */ | ||
109 | i = (ent_ents[e].y << 8) + ent_ents[e].offsy + ent_ents[e].ylow; | ||
110 | y = i >> 8; | ||
111 | |||
112 | /* deactivate if outside vertical boundaries */ | ||
113 | /* no need to test zero since e_them _t1a/b don't go up */ | ||
114 | /* FIXME what if they got scrolled out ? */ | ||
115 | if (y > 0x140) { | ||
116 | ent_ents[e].n = 0; | ||
117 | return; | ||
118 | } | ||
119 | |||
120 | /* test environment */ | ||
121 | u_envtest(ent_ents[e].x, y, false, &env0, &env1); | ||
122 | |||
123 | if (!(env1 & (MAP_EFLG_VERT|MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP))) { | ||
124 | /* vertical move possible: falling */ | ||
125 | if (env1 & MAP_EFLG_LETHAL) { | ||
126 | /* lethal entities kill e_them */ | ||
127 | e_them_gozombie(e); | ||
128 | return; | ||
129 | } | ||
130 | /* save, cleanup and return */ | ||
131 | ent_ents[e].y = y; | ||
132 | ent_ents[e].ylow = i; | ||
133 | ent_ents[e].offsy += 0x0080; | ||
134 | if (ent_ents[e].offsy > 0x0800) | ||
135 | ent_ents[e].offsy = 0x0800; | ||
136 | return; | ||
137 | } | ||
138 | |||
139 | /* vertical move not possible. calculate new sprite */ | ||
140 | ent_ents[e].sprite = ent_ents[e].sprbase | ||
141 | + ent_sprseq[(ent_ents[e].x & 0x1c) >> 3] | ||
142 | + (ent_ents[e].offsx < 0 ? 0x03 : 0x00); | ||
143 | |||
144 | /* reset offsy */ | ||
145 | ent_ents[e].offsy = 0x0080; | ||
146 | |||
147 | /* align to ground */ | ||
148 | ent_ents[e].y &= 0xfff8; | ||
149 | ent_ents[e].y |= 0x0003; | ||
150 | |||
151 | /* latency: if not zero then decrease and return */ | ||
152 | if (ent_ents[e].latency > 0) { | ||
153 | ent_ents[e].latency--; | ||
154 | return; | ||
155 | } | ||
156 | |||
157 | /* horizontal move. calculate new x */ | ||
158 | if (ent_ents[e].offsx == 0) /* not supposed to move -> don't */ | ||
159 | return; | ||
160 | |||
161 | x = ent_ents[e].x + ent_ents[e].offsx; | ||
162 | if (ent_ents[e].x < 0 || ent_ents[e].x > 0xe8) { | ||
163 | /* U-turn and return if reaching horizontal boundaries */ | ||
164 | ent_ents[e].step_count = 0; | ||
165 | ent_ents[e].offsx = -ent_ents[e].offsx; | ||
166 | return; | ||
167 | } | ||
168 | |||
169 | /* test environment */ | ||
170 | u_envtest(x, ent_ents[e].y, false, &env0, &env1); | ||
171 | |||
172 | if (env1 & (MAP_EFLG_VERT|MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP)) { | ||
173 | /* horizontal move not possible: u-turn and return */ | ||
174 | ent_ents[e].step_count = 0; | ||
175 | ent_ents[e].offsx = -ent_ents[e].offsx; | ||
176 | return; | ||
177 | } | ||
178 | |||
179 | /* horizontal move possible */ | ||
180 | if (env1 & MAP_EFLG_LETHAL) { | ||
181 | /* lethal entities kill e_them */ | ||
182 | e_them_gozombie(e); | ||
183 | return; | ||
184 | } | ||
185 | |||
186 | /* save */ | ||
187 | ent_ents[e].x = x; | ||
188 | |||
189 | /* depending on type, */ | ||
190 | if (type == TYPE_1B) { | ||
191 | /* set direction to move horizontally towards rick */ | ||
192 | if ((ent_ents[e].x & 0x1e) != 0x10) /* prevents too frequent u-turns */ | ||
193 | return; | ||
194 | ent_ents[e].offsx = (ent_ents[e].x < E_RICK_ENT.x) ? 0x02 : -0x02; | ||
195 | return; | ||
196 | } | ||
197 | else { | ||
198 | /* set direction according to step counter */ | ||
199 | ent_ents[e].step_count++; | ||
200 | /* FIXME why trig_x (b16) ?? */ | ||
201 | if ((ent_ents[e].trig_x >> 1) > ent_ents[e].step_count) | ||
202 | return; | ||
203 | } | ||
204 | |||
205 | /* type is 1A and step counter reached its limit: u-turn */ | ||
206 | ent_ents[e].step_count = 0; | ||
207 | ent_ents[e].offsx = -ent_ents[e].offsx; | ||
208 | #undef offsx | ||
209 | #undef step_count | ||
210 | } | ||
211 | |||
212 | |||
213 | /* | ||
214 | * ASM 21CF | ||
215 | */ | ||
216 | void | ||
217 | e_them_t1_action(U8 e, U8 type) | ||
218 | { | ||
219 | e_them_t1_action2(e, type); | ||
220 | |||
221 | /* lethal entities kill them */ | ||
222 | if (u_themtest(e)) { | ||
223 | e_them_gozombie(e); | ||
224 | return; | ||
225 | } | ||
226 | |||
227 | /* bullet kills them */ | ||
228 | if (E_BULLET_ENT.n && | ||
229 | u_fboxtest(e, E_BULLET_ENT.x + (e_bullet_offsx < 0 ? 0 : 0x18), | ||
230 | E_BULLET_ENT.y)) { | ||
231 | E_BULLET_ENT.n = 0; | ||
232 | e_them_gozombie(e); | ||
233 | return; | ||
234 | } | ||
235 | |||
236 | /* bomb kills them */ | ||
237 | if (e_bomb_lethal && e_bomb_hit(e)) { | ||
238 | e_them_gozombie(e); | ||
239 | return; | ||
240 | } | ||
241 | |||
242 | /* rick stops them */ | ||
243 | if (e_rick_state_test(E_RICK_STSTOP) && | ||
244 | u_fboxtest(e, e_rick_stop_x, e_rick_stop_y)) | ||
245 | ent_ents[e].latency = 0x14; | ||
246 | |||
247 | /* they kill rick */ | ||
248 | if (e_rick_boxtest(e)) | ||
249 | e_rick_gozombie(); | ||
250 | } | ||
251 | |||
252 | |||
253 | /* | ||
254 | * Action function for e_them _t1a type (stays within boundaries) | ||
255 | * | ||
256 | * ASM 2452 | ||
257 | */ | ||
258 | void | ||
259 | e_them_t1a_action(U8 e) | ||
260 | { | ||
261 | e_them_t1_action(e, TYPE_1A); | ||
262 | } | ||
263 | |||
264 | |||
265 | /* | ||
266 | * Action function for e_them _t1b type (runs for rick) | ||
267 | * | ||
268 | * ASM 21CA | ||
269 | */ | ||
270 | void | ||
271 | e_them_t1b_action(U8 e) | ||
272 | { | ||
273 | e_them_t1_action(e, TYPE_1B); | ||
274 | } | ||
275 | |||
276 | |||
277 | /* | ||
278 | * Action function for e_them _z (zombie) type | ||
279 | * | ||
280 | * ASM 23B8 | ||
281 | */ | ||
282 | void | ||
283 | e_them_z_action(U8 e) | ||
284 | { | ||
285 | #define offsx c1 | ||
286 | U32 i; | ||
287 | |||
288 | /* calc new sprite */ | ||
289 | ent_ents[e].sprite = ent_ents[e].sprbase | ||
290 | + ((ent_ents[e].x & 0x04) ? 0x07 : 0x06); | ||
291 | |||
292 | /* calc new y */ | ||
293 | i = (ent_ents[e].y << 8) + ent_ents[e].offsy + ent_ents[e].ylow; | ||
294 | |||
295 | /* deactivate if out of vertical boundaries */ | ||
296 | if (ent_ents[e].y < 0 || ent_ents[e].y > 0x0140) { | ||
297 | ent_ents[e].n = 0; | ||
298 | return; | ||
299 | } | ||
300 | |||
301 | /* save */ | ||
302 | ent_ents[e].offsy += 0x0080; | ||
303 | ent_ents[e].ylow = i; | ||
304 | ent_ents[e].y = i >> 8; | ||
305 | |||
306 | /* calc new x */ | ||
307 | ent_ents[e].x += ent_ents[e].offsx; | ||
308 | |||
309 | /* must stay within horizontal boundaries */ | ||
310 | if (ent_ents[e].x < 0) | ||
311 | ent_ents[e].x = 0; | ||
312 | if (ent_ents[e].x > 0xe8) | ||
313 | ent_ents[e].x = 0xe8; | ||
314 | #undef offsx | ||
315 | } | ||
316 | |||
317 | |||
318 | /* | ||
319 | * Action sub-function for e_them _t2. | ||
320 | * | ||
321 | * Must document what it does. | ||
322 | * | ||
323 | * ASM 2792 | ||
324 | */ | ||
325 | void | ||
326 | e_them_t2_action2(U8 e) | ||
327 | { | ||
328 | #define flgclmb c1 | ||
329 | #define offsx c2 | ||
330 | U32 i; | ||
331 | S16 x, y, yd; | ||
332 | U8 env0, env1; | ||
333 | |||
334 | /* | ||
335 | * vars required by the Black Magic (tm) performance at the | ||
336 | * end of this function. | ||
337 | */ | ||
338 | static U16 bx; | ||
339 | static U8 *bl = (U8 *)&bx; | ||
340 | static U8 *bh = (U8 *)&bx + 1; | ||
341 | static U16 cx; | ||
342 | static U8 *cl = (U8 *)&cx; | ||
343 | static U8 *ch = (U8 *)&cx + 1; | ||
344 | static U16 *sl = (U16 *)&e_them_rndseed; | ||
345 | static U16 *sh = (U16 *)&e_them_rndseed + 2; | ||
346 | |||
347 | /*sys_printf("e_them_t2 ------------------------------\n");*/ | ||
348 | |||
349 | /* latency: if not zero then decrease */ | ||
350 | if (ent_ents[e].latency > 0) ent_ents[e].latency--; | ||
351 | |||
352 | /* climbing? */ | ||
353 | if (!ent_ents[e].flgclmb) goto climbing_not; | ||
354 | |||
355 | /* CLIMBING */ | ||
356 | |||
357 | /*sys_printf("e_them_t2 climbing\n");*/ | ||
358 | |||
359 | /* latency: if not zero then return */ | ||
360 | if (ent_ents[e].latency > 0) return; | ||
361 | |||
362 | /* calc new sprite */ | ||
363 | ent_ents[e].sprite = ent_ents[e].sprbase + 0x08 + | ||
364 | (((ent_ents[e].x ^ ent_ents[e].y) & 0x04) ? 1 : 0); | ||
365 | |||
366 | /* reached rick's level? */ | ||
367 | if ((ent_ents[e].y & 0xfe) != (E_RICK_ENT.y & 0xfe)) goto ymove; | ||
368 | |||
369 | xmove: | ||
370 | /* calc new x and test environment */ | ||
371 | ent_ents[e].offsx = (ent_ents[e].x < E_RICK_ENT.x) ? 0x02 : -0x02; | ||
372 | x = ent_ents[e].x + ent_ents[e].offsx; | ||
373 | u_envtest(x, ent_ents[e].y, false, &env0, &env1); | ||
374 | if (env1 & (MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP)) | ||
375 | return; | ||
376 | if (env1 & MAP_EFLG_LETHAL) { | ||
377 | e_them_gozombie(e); | ||
378 | return; | ||
379 | } | ||
380 | ent_ents[e].x = x; | ||
381 | if (env1 & (MAP_EFLG_VERT|MAP_EFLG_CLIMB)) /* still climbing */ | ||
382 | return; | ||
383 | goto climbing_not; /* not climbing anymore */ | ||
384 | |||
385 | ymove: | ||
386 | /* calc new y and test environment */ | ||
387 | yd = ent_ents[e].y < E_RICK_ENT.y ? 0x02 : -0x02; | ||
388 | y = ent_ents[e].y + yd; | ||
389 | if (y < 0 || y > 0x0140) { | ||
390 | ent_ents[e].n = 0; | ||
391 | return; | ||
392 | } | ||
393 | u_envtest(ent_ents[e].x, y, false, &env0, &env1); | ||
394 | if (env1 & (MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP)) { | ||
395 | if (yd < 0) | ||
396 | goto xmove; /* can't go up */ | ||
397 | else | ||
398 | goto climbing_not; /* can't go down */ | ||
399 | } | ||
400 | /* can move */ | ||
401 | ent_ents[e].y = y; | ||
402 | if (env1 & (MAP_EFLG_VERT|MAP_EFLG_CLIMB)) /* still climbing */ | ||
403 | return; | ||
404 | |||
405 | /* NOT CLIMBING */ | ||
406 | |||
407 | climbing_not: | ||
408 | /*sys_printf("e_them_t2 climbing NOT\n");*/ | ||
409 | |||
410 | ent_ents[e].flgclmb = false; /* not climbing */ | ||
411 | |||
412 | /* calc new y (falling) and test environment */ | ||
413 | i = (ent_ents[e].y << 8) + ent_ents[e].offsy + ent_ents[e].ylow; | ||
414 | y = i >> 8; | ||
415 | u_envtest(ent_ents[e].x, y, false, &env0, &env1); | ||
416 | if (!(env1 & (MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP))) { | ||
417 | /*sys_printf("e_them_t2 y move OK\n");*/ | ||
418 | /* can go there */ | ||
419 | if (env1 & MAP_EFLG_LETHAL) { | ||
420 | e_them_gozombie(e); | ||
421 | return; | ||
422 | } | ||
423 | if (y > 0x0140) { /* deactivate if outside */ | ||
424 | ent_ents[e].n = 0; | ||
425 | return; | ||
426 | } | ||
427 | if (!(env1 & MAP_EFLG_VERT)) { | ||
428 | /* save */ | ||
429 | ent_ents[e].y = y; | ||
430 | ent_ents[e].ylow = i; | ||
431 | ent_ents[e].offsy += 0x0080; | ||
432 | if (ent_ents[e].offsy > 0x0800) | ||
433 | ent_ents[e].offsy = 0x0800; | ||
434 | return; | ||
435 | } | ||
436 | if (((ent_ents[e].x & 0x07) == 0x04) && (y < E_RICK_ENT.y)) { | ||
437 | /*sys_printf("e_them_t2 climbing00\n");*/ | ||
438 | ent_ents[e].flgclmb = true; /* climbing */ | ||
439 | return; | ||
440 | } | ||
441 | } | ||
442 | |||
443 | /*sys_printf("e_them_t2 ymove nok or ...\n");*/ | ||
444 | /* can't go there, or ... */ | ||
445 | ent_ents[e].y = (ent_ents[e].y & 0xf8) | 0x03; /* align to ground */ | ||
446 | ent_ents[e].offsy = 0x0100; | ||
447 | if (ent_ents[e].latency != 00) | ||
448 | return; | ||
449 | |||
450 | if ((env1 & MAP_EFLG_CLIMB) && | ||
451 | ((ent_ents[e].x & 0x0e) == 0x04) && | ||
452 | (ent_ents[e].y > E_RICK_ENT.y)) { | ||
453 | /*sys_printf("e_them_t2 climbing01\n");*/ | ||
454 | ent_ents[e].flgclmb = true; /* climbing */ | ||
455 | return; | ||
456 | } | ||
457 | |||
458 | /* calc new sprite */ | ||
459 | ent_ents[e].sprite = ent_ents[e].sprbase + | ||
460 | ent_sprseq[(ent_ents[e].offsx < 0 ? 4 : 0) + | ||
461 | ((ent_ents[e].x & 0x0e) >> 3)]; | ||
462 | /*sys_printf("e_them_t2 sprite %02x\n", ent_ents[e].sprite);*/ | ||
463 | |||
464 | |||
465 | /* */ | ||
466 | if (ent_ents[e].offsx == 0) | ||
467 | ent_ents[e].offsx = 2; | ||
468 | x = ent_ents[e].x + ent_ents[e].offsx; | ||
469 | /*sys_printf("e_them_t2 xmove x=%02x\n", x);*/ | ||
470 | if (x < 0xe8) { | ||
471 | u_envtest(x, ent_ents[e].y, false, &env0, &env1); | ||
472 | if (!(env1 & (MAP_EFLG_VERT|MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP))) { | ||
473 | ent_ents[e].x = x; | ||
474 | if ((x & 0x1e) != 0x08) | ||
475 | return; | ||
476 | |||
477 | /* | ||
478 | * Black Magic (tm) | ||
479 | * | ||
480 | * this is obviously some sort of randomizer to define a direction | ||
481 | * for the entity. it is an exact copy of what the assembler code | ||
482 | * does but I can't explain. | ||
483 | */ | ||
484 | bx = e_them_rndnbr + *sh + *sl + 0x0d; | ||
485 | cx = *sh; | ||
486 | *bl ^= *ch; | ||
487 | *bl ^= *cl; | ||
488 | *bl ^= *bh; | ||
489 | e_them_rndnbr = bx; | ||
490 | |||
491 | ent_ents[e].offsx = (*bl & 0x01) ? -0x02 : 0x02; | ||
492 | |||
493 | /* back to normal */ | ||
494 | |||
495 | return; | ||
496 | |||
497 | } | ||
498 | } | ||
499 | |||
500 | /* U-turn */ | ||
501 | /*sys_printf("e_them_t2 u-turn\n");*/ | ||
502 | if (ent_ents[e].offsx == 0) | ||
503 | ent_ents[e].offsx = 2; | ||
504 | else | ||
505 | ent_ents[e].offsx = -ent_ents[e].offsx; | ||
506 | #undef offsx | ||
507 | } | ||
508 | |||
509 | /* | ||
510 | * Action function for e_them _t2 type | ||
511 | * | ||
512 | * ASM 2718 | ||
513 | */ | ||
514 | void | ||
515 | e_them_t2_action(U8 e) | ||
516 | { | ||
517 | e_them_t2_action2(e); | ||
518 | |||
519 | /* they kill rick */ | ||
520 | if (e_rick_boxtest(e)) | ||
521 | e_rick_gozombie(); | ||
522 | |||
523 | /* lethal entities kill them */ | ||
524 | if (u_themtest(e)) { | ||
525 | e_them_gozombie(e); | ||
526 | return; | ||
527 | } | ||
528 | |||
529 | /* bullet kills them */ | ||
530 | if (E_BULLET_ENT.n && | ||
531 | u_fboxtest(e, E_BULLET_ENT.x + (e_bullet_offsx < 0 ? 00 : 0x18), | ||
532 | E_BULLET_ENT.y)) { | ||
533 | E_BULLET_ENT.n = 0; | ||
534 | e_them_gozombie(e); | ||
535 | return; | ||
536 | } | ||
537 | |||
538 | /* bomb kills them */ | ||
539 | if (e_bomb_lethal && e_bomb_hit(e)) { | ||
540 | e_them_gozombie(e); | ||
541 | return; | ||
542 | } | ||
543 | |||
544 | /* rick stops them */ | ||
545 | if (e_rick_state_test(E_RICK_STSTOP) && | ||
546 | u_fboxtest(e, e_rick_stop_x, e_rick_stop_y)) | ||
547 | ent_ents[e].latency = 0x14; | ||
548 | } | ||
549 | |||
550 | |||
551 | /* | ||
552 | * Action sub-function for e_them _t3 | ||
553 | * | ||
554 | * FIXME always starts asleep?? | ||
555 | * | ||
556 | * Waits until triggered by something, then execute move steps from | ||
557 | * ent_mvstep with sprite from ent_sprseq. When done, either restart | ||
558 | * or disappear. | ||
559 | * | ||
560 | * Not always lethal ... but if lethal, kills rick. | ||
561 | * | ||
562 | * ASM: 255A | ||
563 | */ | ||
564 | void | ||
565 | e_them_t3_action2(U8 e) | ||
566 | { | ||
567 | #define sproffs c1 | ||
568 | #define step_count c2 | ||
569 | U8 i; | ||
570 | S16 x, y; | ||
571 | int wav_index; | ||
572 | |||
573 | while (1) { | ||
574 | |||
575 | /* calc new sprite */ | ||
576 | i = ent_sprseq[ent_ents[e].sprbase + ent_ents[e].sproffs]; | ||
577 | if (i == 0xff) | ||
578 | i = ent_sprseq[ent_ents[e].sprbase]; | ||
579 | ent_ents[e].sprite = i; | ||
580 | |||
581 | if (ent_ents[e].sproffs != 0) { /* awake */ | ||
582 | |||
583 | /* rotate sprseq */ | ||
584 | if (ent_sprseq[ent_ents[e].sprbase + ent_ents[e].sproffs] != 0xff) | ||
585 | ent_ents[e].sproffs++; | ||
586 | if (ent_sprseq[ent_ents[e].sprbase + ent_ents[e].sproffs] == 0xff) | ||
587 | ent_ents[e].sproffs = 1; | ||
588 | |||
589 | if (ent_ents[e].step_count < ent_mvstep[ent_ents[e].step_no].count) { | ||
590 | /* | ||
591 | * still running this step: try to increment x and y while | ||
592 | * checking that they remain within boudaries. if so, return. | ||
593 | * else switch to next step. | ||
594 | */ | ||
595 | ent_ents[e].step_count++; | ||
596 | x = ent_ents[e].x + ent_mvstep[ent_ents[e].step_no].dx; | ||
597 | |||
598 | /* check'n save */ | ||
599 | if (x > 0 && x < 0xe8) { | ||
600 | ent_ents[e].x = x; | ||
601 | /*FIXME*/ | ||
602 | /* | ||
603 | y = ent_mvstep[ent_ents[e].step_no].dy; | ||
604 | if (y < 0) | ||
605 | y += 0xff00; | ||
606 | y += ent_ents[e].y; | ||
607 | */ | ||
608 | y = ent_ents[e].y + ent_mvstep[ent_ents[e].step_no].dy; | ||
609 | if (y > 0 && y < 0x0140) { | ||
610 | ent_ents[e].y = y; | ||
611 | return; | ||
612 | } | ||
613 | } | ||
614 | } | ||
615 | |||
616 | /* | ||
617 | * step is done, or x or y is outside boundaries. try to | ||
618 | * switch to next step | ||
619 | */ | ||
620 | ent_ents[e].step_no++; | ||
621 | if (ent_mvstep[ent_ents[e].step_no].count != 0xff) { | ||
622 | /* there is a next step: init and loop */ | ||
623 | ent_ents[e].step_count = 0; | ||
624 | } | ||
625 | else { | ||
626 | /* there is no next step: restart or deactivate */ | ||
627 | if (!e_rick_state_test(E_RICK_STZOMBIE) && | ||
628 | !(ent_ents[e].flags & ENT_FLG_ONCE)) { | ||
629 | /* loop this entity */ | ||
630 | ent_ents[e].sproffs = 0; | ||
631 | ent_ents[e].n &= ~ENT_LETHAL; | ||
632 | if (ent_ents[e].flags & ENT_FLG_LETHALR) | ||
633 | ent_ents[e].n |= ENT_LETHAL; | ||
634 | ent_ents[e].x = ent_ents[e].xsave; | ||
635 | ent_ents[e].y = ent_ents[e].ysave; | ||
636 | if (ent_ents[e].y < 0 || ent_ents[e].y > 0x140) { | ||
637 | ent_ents[e].n = 0; | ||
638 | return; | ||
639 | } | ||
640 | } | ||
641 | else { | ||
642 | /* deactivate this entity */ | ||
643 | ent_ents[e].n = 0; | ||
644 | return; | ||
645 | } | ||
646 | } | ||
647 | } | ||
648 | else { /* ent_ents[e].sprseq1 == 0 -- waiting */ | ||
649 | |||
650 | /* ugly GOTOs */ | ||
651 | |||
652 | if (ent_ents[e].flags & ENT_FLG_TRIGRICK) { /* reacts to rick */ | ||
653 | /* wake up if triggered by rick */ | ||
654 | if (u_trigbox(e, E_RICK_ENT.x + 0x0C, E_RICK_ENT.y + 0x0A)) | ||
655 | goto wakeup; | ||
656 | } | ||
657 | |||
658 | if (ent_ents[e].flags & ENT_FLG_TRIGSTOP) { /* reacts to rick "stop" */ | ||
659 | /* wake up if triggered by rick "stop" */ | ||
660 | if (e_rick_state_test(E_RICK_STSTOP) && | ||
661 | u_trigbox(e, e_rick_stop_x, e_rick_stop_y)) | ||
662 | goto wakeup; | ||
663 | } | ||
664 | |||
665 | if (ent_ents[e].flags & ENT_FLG_TRIGBULLET) { /* reacts to bullets */ | ||
666 | /* wake up if triggered by bullet */ | ||
667 | if (E_BULLET_ENT.n && u_trigbox(e, e_bullet_xc, e_bullet_yc)) { | ||
668 | E_BULLET_ENT.n = 0; | ||
669 | goto wakeup; | ||
670 | } | ||
671 | } | ||
672 | |||
673 | if (ent_ents[e].flags & ENT_FLG_TRIGBOMB) { /* reacts to bombs */ | ||
674 | /* wake up if triggered by bomb */ | ||
675 | if (e_bomb_lethal && u_trigbox(e, e_bomb_xc, e_bomb_yc)) | ||
676 | goto wakeup; | ||
677 | } | ||
678 | |||
679 | /* not triggered: keep waiting */ | ||
680 | return; | ||
681 | |||
682 | /* something triggered the entity: wake up */ | ||
683 | /* initialize step counter */ | ||
684 | wakeup: | ||
685 | if (e_rick_state_test(E_RICK_STZOMBIE)) | ||
686 | { | ||
687 | return; | ||
688 | } | ||
689 | #ifdef ENABLE_SOUND | ||
690 | /* | ||
691 | * FIXME the sound should come from a table, there are 10 of them | ||
692 | * but I dont have the table yet. must rip the data off the game... | ||
693 | * FIXME is it 8 of them, not 10? | ||
694 | * FIXME testing below... | ||
695 | */ | ||
696 | |||
697 | /* FIXME this is defensive, need to figure out whether there | ||
698 | is simply missing sound (and possibly rip it) | ||
699 | or wrong data in sumbmap 47 (when making the switch explode) | ||
700 | and submap 13 (when touching jewel) */ | ||
701 | wav_index = (ent_ents[e].trigsnd & 0x1F) - 0x14; | ||
702 | if((0 <= wav_index) && (wav_index < SOUNDS_NBR_ENTITIES - 1)) | ||
703 | { | ||
704 | syssnd_play(soundEntity[wav_index], 1); | ||
705 | } | ||
706 | /*syssnd_play(WAV_ENTITY[0], 1);*/ | ||
707 | #endif /* ENABLE_SOUND */ | ||
708 | ent_ents[e].n &= ~ENT_LETHAL; | ||
709 | if (ent_ents[e].flags & ENT_FLG_LETHALI) | ||
710 | ent_ents[e].n |= ENT_LETHAL; | ||
711 | ent_ents[e].sproffs = 1; | ||
712 | ent_ents[e].step_count = 0; | ||
713 | ent_ents[e].step_no = ent_ents[e].step_no_i; | ||
714 | return; | ||
715 | } | ||
716 | } | ||
717 | #undef step_count | ||
718 | } | ||
719 | |||
720 | |||
721 | /* | ||
722 | * Action function for e_them _t3 type | ||
723 | * | ||
724 | * ASM 2546 | ||
725 | */ | ||
726 | void | ||
727 | e_them_t3_action(U8 e) | ||
728 | { | ||
729 | e_them_t3_action2(e); | ||
730 | |||
731 | /* if lethal, can kill rick */ | ||
732 | if ((ent_ents[e].n & ENT_LETHAL) && | ||
733 | !e_rick_state_test(E_RICK_STZOMBIE) && e_rick_boxtest(e)) { /* CALL 1130 */ | ||
734 | e_rick_gozombie(); | ||
735 | } | ||
736 | } | ||
737 | |||
738 | /* eof */ | ||