diff options
Diffstat (limited to 'apps/plugins/xrick/ents.c')
-rw-r--r-- | apps/plugins/xrick/ents.c | 540 |
1 files changed, 540 insertions, 0 deletions
diff --git a/apps/plugins/xrick/ents.c b/apps/plugins/xrick/ents.c new file mode 100644 index 0000000000..5e35f2bdd1 --- /dev/null +++ b/apps/plugins/xrick/ents.c | |||
@@ -0,0 +1,540 @@ | |||
1 | /* | ||
2 | * xrick/ents.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/ents.h" | ||
17 | |||
18 | #include "xrick/config.h" | ||
19 | #include "xrick/control.h" | ||
20 | #include "xrick/game.h" | ||
21 | #include "xrick/debug.h" | ||
22 | #include "xrick/e_bullet.h" | ||
23 | #include "xrick/e_bomb.h" | ||
24 | #include "xrick/e_rick.h" | ||
25 | #include "xrick/e_them.h" | ||
26 | #include "xrick/e_bonus.h" | ||
27 | #include "xrick/e_box.h" | ||
28 | #include "xrick/e_sbonus.h" | ||
29 | #include "xrick/rects.h" | ||
30 | #include "xrick/maps.h" | ||
31 | #include "xrick/draw.h" | ||
32 | |||
33 | #include <stdlib.h> /* abs */ | ||
34 | |||
35 | /* | ||
36 | * global vars | ||
37 | */ | ||
38 | ent_t ent_ents[ENT_ENTSNUM + 1]; | ||
39 | |||
40 | size_t ent_nbr_entdata = 0; | ||
41 | entdata_t *ent_entdata = NULL; | ||
42 | |||
43 | rect_t *ent_rects = NULL; | ||
44 | |||
45 | size_t ent_nbr_sprseq = 0; | ||
46 | U8 *ent_sprseq = NULL; | ||
47 | |||
48 | size_t ent_nbr_mvstep = 0; | ||
49 | mvstep_t *ent_mvstep = NULL; | ||
50 | |||
51 | /* | ||
52 | * prototypes | ||
53 | */ | ||
54 | static void ent_addrect(S16, S16, U16, U16); | ||
55 | static bool ent_creat1(U8 *); | ||
56 | static bool ent_creat2(U8 *, U16); | ||
57 | |||
58 | |||
59 | /* | ||
60 | * Reset entities | ||
61 | * | ||
62 | * ASM 2520 | ||
63 | */ | ||
64 | void | ||
65 | ent_reset(void) | ||
66 | { | ||
67 | U8 i; | ||
68 | |||
69 | e_rick_state_clear(E_RICK_STSTOP); | ||
70 | e_bomb_lethal = false; | ||
71 | |||
72 | ent_ents[0].n = 0; | ||
73 | for (i = 2; ent_ents[i].n != 0xff; i++) | ||
74 | ent_ents[i].n = 0; | ||
75 | } | ||
76 | |||
77 | |||
78 | /* | ||
79 | * Create an entity on slots 4 to 8 by using the first slot available. | ||
80 | * Entities of type e_them on slots 4 to 8, when lethal, can kill | ||
81 | * other e_them (on slots 4 to C) as well as rick. | ||
82 | * | ||
83 | * ASM 209C | ||
84 | * | ||
85 | * e: anything, CHANGED to the allocated entity number. | ||
86 | * return: true/OK false/not | ||
87 | */ | ||
88 | static bool | ||
89 | ent_creat1(U8 *e) | ||
90 | { | ||
91 | /* look for a slot */ | ||
92 | for (*e = 0x04; *e < 0x09; (*e)++) | ||
93 | if (ent_ents[*e].n == 0) { /* if slot available, use it */ | ||
94 | ent_ents[*e].c1 = 0; | ||
95 | return true; | ||
96 | } | ||
97 | |||
98 | return false; | ||
99 | } | ||
100 | |||
101 | |||
102 | /* | ||
103 | * Create an entity on slots 9 to C by using the first slot available. | ||
104 | * Entities of type e_them on slots 9 to C can kill rick when lethal, | ||
105 | * but they can never kill other e_them. | ||
106 | * | ||
107 | * ASM 20BC | ||
108 | * | ||
109 | * e: anything, CHANGED to the allocated entity number. | ||
110 | * m: number of the mark triggering the creation of the entity. | ||
111 | * ret: true/OK false/not | ||
112 | */ | ||
113 | static bool | ||
114 | ent_creat2(U8 *e, U16 m) | ||
115 | { | ||
116 | /* make sure the entity created by this mark is not active already */ | ||
117 | for (*e = 0x09; *e < 0x0c; (*e)++) | ||
118 | if (ent_ents[*e].n != 0 && ent_ents[*e].mark == m) | ||
119 | return false; | ||
120 | |||
121 | /* look for a slot */ | ||
122 | for (*e = 0x09; *e < 0x0c; (*e)++) | ||
123 | if (ent_ents[*e].n == 0) { /* if slot available, use it */ | ||
124 | ent_ents[*e].c1 = 2; | ||
125 | return true; | ||
126 | } | ||
127 | |||
128 | return false; | ||
129 | } | ||
130 | |||
131 | |||
132 | /* | ||
133 | * Process marks that are within the visible portion of the map, | ||
134 | * and create the corresponding entities. | ||
135 | * | ||
136 | * absolute map coordinate means that they are not relative to | ||
137 | * map_frow, as any other coordinates are. | ||
138 | * | ||
139 | * ASM 1F40 | ||
140 | * | ||
141 | * frow: first visible row of the map -- absolute map coordinate | ||
142 | * lrow: last visible row of the map -- absolute map coordinate | ||
143 | */ | ||
144 | void | ||
145 | ent_actvis(U8 frow, U8 lrow) | ||
146 | { | ||
147 | U16 m; | ||
148 | U8 e; | ||
149 | U16 y; | ||
150 | |||
151 | /* | ||
152 | * go through the list and find the first mark that | ||
153 | * is visible, i.e. which has a row greater than the | ||
154 | * first row (marks being ordered by row number). | ||
155 | */ | ||
156 | for (m = map_submaps[game_submap].mark; | ||
157 | map_marks[m].row != 0xff && map_marks[m].row < frow; | ||
158 | m++); | ||
159 | |||
160 | if (map_marks[m].row == 0xff) /* none found */ | ||
161 | return; | ||
162 | |||
163 | /* | ||
164 | * go through the list and process all marks that are | ||
165 | * visible, i.e. which have a row lower than the last | ||
166 | * row (marks still being ordered by row number). | ||
167 | */ | ||
168 | for (; | ||
169 | map_marks[m].row != 0xff && map_marks[m].row < lrow; | ||
170 | m++) { | ||
171 | |||
172 | /* ignore marks that are not active */ | ||
173 | if (map_marks[m].ent & MAP_MARK_NACT) | ||
174 | continue; | ||
175 | |||
176 | /* | ||
177 | * allocate a slot to the new entity | ||
178 | * | ||
179 | * slot type | ||
180 | * 0 available for e_them (lethal to other e_them, and stops entities | ||
181 | * i.e. entities can't move over them. E.g. moving blocks. But they | ||
182 | * can move over entities and kill them!). | ||
183 | * 1 xrick | ||
184 | * 2 bullet | ||
185 | * 3 bomb | ||
186 | * 4-8 available for e_them, e_box, e_bonus or e_sbonus (lethal to | ||
187 | * other e_them, identified by their number being >= 0x10) | ||
188 | * 9-C available for e_them, e_box, e_bonus or e_sbonus (not lethal to | ||
189 | * other e_them, identified by their number being < 0x10) | ||
190 | * | ||
191 | * the type of an entity is determined by its .n as detailed below. | ||
192 | * | ||
193 | * 1 xrick | ||
194 | * 2 bullet | ||
195 | * 3 bomb | ||
196 | * 4, 7, a, d e_them, type 1a | ||
197 | * 5, 8, b, e e_them, type 1b | ||
198 | * 6, 9, c, f e_them, type 2 | ||
199 | * 10, 11 box | ||
200 | * 12, 13, 14, 15 bonus | ||
201 | * 16, 17 speed bonus | ||
202 | * >17 e_them, type 3 | ||
203 | * 47 zombie | ||
204 | */ | ||
205 | |||
206 | if (!(map_marks[m].flags & ENT_FLG_STOPRICK)) { | ||
207 | if (map_marks[m].ent >= 0x10) { | ||
208 | /* boxes, bonuses and type 3 e_them go to slot 4-8 */ | ||
209 | /* (c1 set to 0 -> all type 3 e_them are sleeping) */ | ||
210 | if (!ent_creat1(&e)) continue; | ||
211 | } | ||
212 | else { | ||
213 | /* type 1 and 2 e_them go to slot 9-c */ | ||
214 | /* (c1 set to 2) */ | ||
215 | if (!ent_creat2(&e, m)) continue; | ||
216 | } | ||
217 | } | ||
218 | else { | ||
219 | /* entities stopping rick (e.g. blocks) go to slot 0 */ | ||
220 | if (ent_ents[0].n) continue; | ||
221 | e = 0; | ||
222 | ent_ents[0].c1 = 0; | ||
223 | } | ||
224 | |||
225 | /* | ||
226 | * initialize the entity | ||
227 | */ | ||
228 | ent_ents[e].mark = m; | ||
229 | ent_ents[e].flags = map_marks[m].flags; | ||
230 | ent_ents[e].n = map_marks[m].ent; | ||
231 | |||
232 | /* | ||
233 | * if entity is to be already running (i.e. not asleep and waiting | ||
234 | * for some trigger to move), then use LETHALR i.e. restart flag, right | ||
235 | * from the beginning | ||
236 | */ | ||
237 | if (ent_ents[e].flags & ENT_FLG_LETHALR) | ||
238 | ent_ents[e].n |= ENT_LETHAL; | ||
239 | |||
240 | ent_ents[e].x = map_marks[m].xy & 0xf8; | ||
241 | |||
242 | y = (map_marks[m].xy & 0x07) + (map_marks[m].row & 0xf8) - map_frow; | ||
243 | y <<= 3; | ||
244 | if (!(ent_ents[e].flags & ENT_FLG_STOPRICK)) | ||
245 | y += 3; | ||
246 | ent_ents[e].y = y; | ||
247 | |||
248 | ent_ents[e].xsave = ent_ents[e].x; | ||
249 | ent_ents[e].ysave = ent_ents[e].y; | ||
250 | |||
251 | /*ent_ents[e].w0C = 0;*/ /* in ASM code but never used */ | ||
252 | |||
253 | ent_ents[e].w = ent_entdata[map_marks[m].ent].w; | ||
254 | ent_ents[e].h = ent_entdata[map_marks[m].ent].h; | ||
255 | ent_ents[e].sprbase = ent_entdata[map_marks[m].ent].spr; | ||
256 | ent_ents[e].step_no_i = ent_entdata[map_marks[m].ent].sni; | ||
257 | ent_ents[e].trigsnd = (U8)ent_entdata[map_marks[m].ent].snd; | ||
258 | |||
259 | /* | ||
260 | * FIXME what is this? when all trigger flags are up, then | ||
261 | * use .sni for sprbase. Why? What is the point? (This is | ||
262 | * for type 1 and 2 e_them, ...) | ||
263 | * | ||
264 | * This also means that as long as sprite has not been | ||
265 | * recalculated, a wrong value is used. This is normal, see | ||
266 | * what happens to the falling guy on the right on submap 3: | ||
267 | * it changes when hitting the ground. | ||
268 | * | ||
269 | * Note: sprite recalculation has been fixed, refer to the commit log. | ||
270 | */ | ||
271 | #define ENT_FLG_TRIGGERS \ | ||
272 | (ENT_FLG_TRIGBOMB|ENT_FLG_TRIGBULLET|ENT_FLG_TRIGSTOP|ENT_FLG_TRIGRICK) | ||
273 | if ((ent_ents[e].flags & ENT_FLG_TRIGGERS) == ENT_FLG_TRIGGERS | ||
274 | && e >= 0x09) | ||
275 | ent_ents[e].sprbase = (U8)(ent_entdata[map_marks[m].ent].sni & 0x00ff); | ||
276 | #undef ENT_FLG_TRIGGERS | ||
277 | |||
278 | ent_ents[e].sprite = (U8)ent_ents[e].sprbase; | ||
279 | ent_ents[e].trig_x = map_marks[m].lt & 0xf8; | ||
280 | ent_ents[e].latency = (map_marks[m].lt & 0x07) << 5; /* <<5 eq *32 */ | ||
281 | |||
282 | ent_ents[e].trig_y = 3 + 8 * ((map_marks[m].row & 0xf8) - map_frow + | ||
283 | (map_marks[m].lt & 0x07)); | ||
284 | |||
285 | ent_ents[e].c2 = 0; | ||
286 | ent_ents[e].offsy = 0; | ||
287 | ent_ents[e].ylow = 0; | ||
288 | |||
289 | ent_ents[e].front = false; | ||
290 | |||
291 | } | ||
292 | } | ||
293 | |||
294 | |||
295 | /* | ||
296 | * Add a tile-aligned rectangle containing the given rectangle (indicated | ||
297 | * by its MAP coordinates) to the list of rectangles. Clip the rectangle | ||
298 | * so it fits into the display zone. | ||
299 | */ | ||
300 | static void | ||
301 | ent_addrect(S16 x, S16 y, U16 width, U16 height) | ||
302 | { | ||
303 | S16 x0, y0; | ||
304 | U16 w0, h0; | ||
305 | rect_t *r; | ||
306 | |||
307 | /*sys_printf("rect %#04x,%#04x %#04x %#04x ", x, y, width, height);*/ | ||
308 | |||
309 | /* align to tiles */ | ||
310 | x0 = x & 0xfff8; | ||
311 | y0 = y & 0xfff8; | ||
312 | w0 = width; | ||
313 | h0 = height; | ||
314 | if (x - x0) w0 = (w0 + (x - x0)) | 0x0007; | ||
315 | if (y - y0) h0 = (h0 + (y - y0)) | 0x0007; | ||
316 | |||
317 | /* clip */ | ||
318 | if (draw_clipms(&x0, &y0, &w0, &h0)) { /* do not add if fully clipped */ | ||
319 | /*sys_printf("-> [clipped]\n");*/ | ||
320 | return; | ||
321 | } | ||
322 | |||
323 | /*sys_printf("-> %#04x,%#04x %#04x %#04x\n", x0, y0, w0, h0);*/ | ||
324 | |||
325 | #ifdef GFXST | ||
326 | y0 += 8; | ||
327 | #endif | ||
328 | |||
329 | /* get to screen */ | ||
330 | x0 -= DRAW_XYMAP_SCRLEFT; | ||
331 | y0 -= DRAW_XYMAP_SCRTOP; | ||
332 | |||
333 | /* add rectangle to the list */ | ||
334 | r = rects_new(x0, y0, w0, h0, ent_rects); | ||
335 | if (!r) | ||
336 | { | ||
337 | control_set(Control_EXIT); | ||
338 | return; | ||
339 | } | ||
340 | ent_rects = r; | ||
341 | } | ||
342 | |||
343 | |||
344 | /* | ||
345 | * Draw all entities onto the frame buffer. | ||
346 | * | ||
347 | * ASM 07a4 | ||
348 | * | ||
349 | * NOTE This may need to be part of draw.c. Also needs better comments, | ||
350 | * NOTE and probably better rectangles management. | ||
351 | */ | ||
352 | void | ||
353 | ent_draw(void) | ||
354 | { | ||
355 | U8 i; | ||
356 | #ifdef ENABLE_CHEATS | ||
357 | static bool ch3 = false; | ||
358 | #endif | ||
359 | S16 dx, dy; | ||
360 | |||
361 | draw_tilesBank = map_tilesBank; | ||
362 | |||
363 | /* reset rectangles list */ | ||
364 | rects_free(ent_rects); | ||
365 | ent_rects = NULL; | ||
366 | |||
367 | /*sys_printf("\n");*/ | ||
368 | |||
369 | /* | ||
370 | * background loop : erase all entities that were visible | ||
371 | */ | ||
372 | for (i = 0; ent_ents[i].n != 0xff; i++) { | ||
373 | #ifdef ENABLE_CHEATS | ||
374 | if (ent_ents[i].prev_n && (ch3 || ent_ents[i].prev_s)) | ||
375 | #else | ||
376 | if (ent_ents[i].prev_n && ent_ents[i].prev_s) | ||
377 | #endif | ||
378 | /* if entity was active, then erase it (redraw the map) */ | ||
379 | draw_spriteBackground(ent_ents[i].prev_x, ent_ents[i].prev_y); | ||
380 | } | ||
381 | |||
382 | /* | ||
383 | * foreground loop : draw all entities that are visible | ||
384 | */ | ||
385 | for (i = 0; ent_ents[i].n != 0xff; i++) { | ||
386 | /* | ||
387 | * If entity is active now, draw the sprite. If entity was | ||
388 | * not active before, add a rectangle for the sprite. | ||
389 | */ | ||
390 | #ifdef ENABLE_CHEATS | ||
391 | if (ent_ents[i].n && (game_cheat3 || ent_ents[i].sprite)) | ||
392 | #else | ||
393 | if (ent_ents[i].n && ent_ents[i].sprite) | ||
394 | #endif | ||
395 | /* If entitiy is active, draw the sprite. */ | ||
396 | draw_sprite2(ent_ents[i].sprite, | ||
397 | ent_ents[i].x, ent_ents[i].y, | ||
398 | ent_ents[i].front); | ||
399 | } | ||
400 | |||
401 | /* | ||
402 | * rectangles loop : figure out which parts of the screen have been | ||
403 | * impacted and need to be refreshed, then save state | ||
404 | */ | ||
405 | for (i = 0; ent_ents[i].n != 0xff; i++) { | ||
406 | #ifdef ENABLE_CHEATS | ||
407 | if (ent_ents[i].prev_n && (ch3 || ent_ents[i].prev_s)) { | ||
408 | #else | ||
409 | if (ent_ents[i].prev_n && ent_ents[i].prev_s) { | ||
410 | #endif | ||
411 | /* (1) if entity was active and has been drawn ... */ | ||
412 | #ifdef ENABLE_CHEATS | ||
413 | if (ent_ents[i].n && (game_cheat3 || ent_ents[i].sprite)) { | ||
414 | #else | ||
415 | if (ent_ents[i].n && ent_ents[i].sprite) { | ||
416 | #endif | ||
417 | /* (1.1) ... and is still active now and still needs to be drawn, */ | ||
418 | /* then check if rectangles intersect */ | ||
419 | dx = abs(ent_ents[i].x - ent_ents[i].prev_x); | ||
420 | dy = abs(ent_ents[i].y - ent_ents[i].prev_y); | ||
421 | if (dx < 0x20 && dy < 0x16) { | ||
422 | /* (1.1.1) if they do, then create one rectangle */ | ||
423 | ent_addrect((ent_ents[i].prev_x < ent_ents[i].x) | ||
424 | ? ent_ents[i].prev_x : ent_ents[i].x, | ||
425 | (ent_ents[i].prev_y < ent_ents[i].y) | ||
426 | ? ent_ents[i].prev_y : ent_ents[i].y, | ||
427 | dx + 0x20, dy + 0x15); | ||
428 | } | ||
429 | else { | ||
430 | /* (1.1.2) else, create two rectangles */ | ||
431 | ent_addrect(ent_ents[i].x, ent_ents[i].y, 0x20, 0x15); | ||
432 | ent_addrect(ent_ents[i].prev_x, ent_ents[i].prev_y, 0x20, 0x15); | ||
433 | } | ||
434 | } | ||
435 | else | ||
436 | /* (1.2) ... and is not active anymore or does not need to be drawn */ | ||
437 | /* then create one single rectangle */ | ||
438 | ent_addrect(ent_ents[i].prev_x, ent_ents[i].prev_y, 0x20, 0x15); | ||
439 | } | ||
440 | #ifdef ENABLE_CHEATS | ||
441 | else if (ent_ents[i].n && (game_cheat3 || ent_ents[i].sprite)) { | ||
442 | #else | ||
443 | else if (ent_ents[i].n && ent_ents[i].sprite) { | ||
444 | #endif | ||
445 | /* (2) if entity is active and needs to be drawn, */ | ||
446 | /* then create one rectangle */ | ||
447 | ent_addrect(ent_ents[i].x, ent_ents[i].y, 0x20, 0x15); | ||
448 | } | ||
449 | |||
450 | /* save state */ | ||
451 | ent_ents[i].prev_x = ent_ents[i].x; | ||
452 | ent_ents[i].prev_y = ent_ents[i].y; | ||
453 | ent_ents[i].prev_n = ent_ents[i].n; | ||
454 | ent_ents[i].prev_s = ent_ents[i].sprite; | ||
455 | } | ||
456 | |||
457 | #ifdef ENABLE_CHEATS | ||
458 | ch3 = game_cheat3; | ||
459 | #endif | ||
460 | } | ||
461 | |||
462 | |||
463 | /* | ||
464 | * Clear entities previous state | ||
465 | * | ||
466 | */ | ||
467 | void | ||
468 | ent_clprev(void) | ||
469 | { | ||
470 | U8 i; | ||
471 | |||
472 | for (i = 0; ent_ents[i].n != 0xff; i++) | ||
473 | ent_ents[i].prev_n = 0; | ||
474 | } | ||
475 | |||
476 | /* | ||
477 | * Table containing entity action function pointers. | ||
478 | */ | ||
479 | void (*ent_actf[])(U8) = { | ||
480 | NULL, /* 00 - zero means that the slot is free */ | ||
481 | e_rick_action, /* 01 - 12CA */ | ||
482 | e_bullet_action, /* 02 - 1883 */ | ||
483 | e_bomb_action, /* 03 - 18CA */ | ||
484 | e_them_t1a_action, /* 04 - 2452 */ | ||
485 | e_them_t1b_action, /* 05 - 21CA */ | ||
486 | e_them_t2_action, /* 06 - 2718 */ | ||
487 | e_them_t1a_action, /* 07 - 2452 */ | ||
488 | e_them_t1b_action, /* 08 - 21CA */ | ||
489 | e_them_t2_action, /* 09 - 2718 */ | ||
490 | e_them_t1a_action, /* 0A - 2452 */ | ||
491 | e_them_t1b_action, /* 0B - 21CA */ | ||
492 | e_them_t2_action, /* 0C - 2718 */ | ||
493 | e_them_t1a_action, /* 0D - 2452 */ | ||
494 | e_them_t1b_action, /* 0E - 21CA */ | ||
495 | e_them_t2_action, /* 0F - 2718 */ | ||
496 | e_box_action, /* 10 - 245A */ | ||
497 | e_box_action, /* 11 - 245A */ | ||
498 | e_bonus_action, /* 12 - 242C */ | ||
499 | e_bonus_action, /* 13 - 242C */ | ||
500 | e_bonus_action, /* 14 - 242C */ | ||
501 | e_bonus_action, /* 15 - 242C */ | ||
502 | e_sbonus_start, /* 16 - 2182 */ | ||
503 | e_sbonus_stop /* 17 - 2143 */ | ||
504 | }; | ||
505 | |||
506 | |||
507 | /* | ||
508 | * Run entities action function | ||
509 | * | ||
510 | */ | ||
511 | void | ||
512 | ent_action(void) | ||
513 | { | ||
514 | U8 i, k; | ||
515 | |||
516 | IFDEBUG_ENTS( | ||
517 | sys_printf("xrick/ents: --------- action ----------------\n"); | ||
518 | for (i = 0; ent_ents[i].n != 0xff; i++) | ||
519 | if (ent_ents[i].n) { | ||
520 | sys_printf("xrick/ents: slot %#04x, entity %#04x", i, ent_ents[i].n); | ||
521 | sys_printf(" (%#06x, %#06x), sprite %#04x.\n", | ||
522 | ent_ents[i].x, ent_ents[i].y, ent_ents[i].sprite); | ||
523 | } | ||
524 | ); | ||
525 | |||
526 | for (i = 0; ent_ents[i].n != 0xff; i++) { | ||
527 | if (ent_ents[i].n) { | ||
528 | k = ent_ents[i].n & 0x7f; | ||
529 | if (k == 0x47) | ||
530 | e_them_z_action(i); | ||
531 | else if (k >= 0x18) | ||
532 | e_them_t3_action(i); | ||
533 | else | ||
534 | ent_actf[k](i); | ||
535 | } | ||
536 | } | ||
537 | } | ||
538 | |||
539 | |||
540 | /* eof */ | ||