changed global animations (esp. toons) to be controlled by game mode
[rocksndiamonds.git] / src / cartoons.c
1 // ============================================================================
2 // Rocks'n'Diamonds - McDuffin Strikes Back!
3 // ----------------------------------------------------------------------------
4 // (c) 1995-2014 by Artsoft Entertainment
5 //                  Holger Schemel
6 //                  info@artsoft.org
7 //                  http://www.artsoft.org/
8 // ----------------------------------------------------------------------------
9 // cartoons.c
10 // ============================================================================
11
12 #include "cartoons.h"
13 #include "main.h"
14 #include "tools.h"
15
16
17 /* values for global toon animation definition */
18 #define NUM_GLOBAL_TOON_ANIMS           1
19 #define NUM_GLOBAL_TOON_PARTS           MAX_NUM_TOONS
20
21 /* values for global animation definition (including toons) */
22 #define NUM_GLOBAL_ANIMS_AND_TOONS      (NUM_GLOBAL_ANIMS +             \
23                                          NUM_GLOBAL_TOON_ANIMS)
24 #define NUM_GLOBAL_ANIM_PARTS_AND_TOONS MAX(NUM_GLOBAL_ANIM_PARTS_ALL,  \
25                                             NUM_GLOBAL_TOON_PARTS)
26
27 #define ANIM_CLASS_BIT_MENU             0
28 #define ANIM_CLASS_BIT_TOONS            1
29
30 #define NUM_ANIM_CLASSES                2
31
32 #define ANIM_CLASS_NONE                 0
33 #define ANIM_CLASS_MENU                 (1 << ANIM_CLASS_BIT_MENU)
34 #define ANIM_CLASS_TOONS                (1 << ANIM_CLASS_BIT_TOONS)
35
36
37 struct GlobalAnimPartControlInfo
38 {
39   int nr;
40   int anim_nr;
41   int mode_nr;
42
43   int graphic;
44   struct GraphicInfo graphic_info;
45   struct GraphicInfo control_info;
46
47   int viewport_x;
48   int viewport_y;
49   int viewport_width;
50   int viewport_height;
51
52   int x, y;
53   int step_xoffset, step_yoffset;
54
55   unsigned int initial_anim_sync_frame;
56   unsigned int step_delay, step_delay_value;
57
58   int init_delay_counter;
59   int anim_delay_counter;
60   int post_delay_counter;
61
62   int drawing_stage;
63
64   int state;
65   int last_game_status;
66 };
67
68 struct GlobalAnimMainControlInfo
69 {
70   struct GlobalAnimPartControlInfo base;
71   struct GlobalAnimPartControlInfo part[NUM_GLOBAL_ANIM_PARTS_AND_TOONS];
72
73   int nr;
74   int mode_nr;
75
76   struct GraphicInfo control_info;
77
78   int num_parts;
79   int part_counter;
80   int active_part_nr;
81
82   boolean has_base;
83
84   int init_delay_counter;
85
86   int state;
87 };
88
89 struct GlobalAnimControlInfo
90 {
91   struct GlobalAnimMainControlInfo anim[NUM_GLOBAL_ANIMS_AND_TOONS];
92
93   int nr;
94   int num_anims;
95 };
96
97 struct GameModeAnimClass
98 {
99   int game_mode;
100   int class;
101 } game_mode_anim_classes_list[] =
102 {
103   { GAME_MODE_MAIN,             ANIM_CLASS_TOONS | ANIM_CLASS_MENU      },
104   { GAME_MODE_LEVELS,           ANIM_CLASS_TOONS | ANIM_CLASS_MENU      },
105   { GAME_MODE_LEVELNR,          ANIM_CLASS_TOONS | ANIM_CLASS_MENU      },
106   { GAME_MODE_INFO,             ANIM_CLASS_TOONS | ANIM_CLASS_MENU      },
107   { GAME_MODE_SETUP,            ANIM_CLASS_TOONS | ANIM_CLASS_MENU      },
108   { GAME_MODE_SCORES,           ANIM_CLASS_TOONS                        },
109
110   { -1,                         -1                                      }
111 };
112
113 struct AnimClassGameMode
114 {
115   int class_bit;
116   int game_mode;
117 } anim_class_game_modes_list[] =
118 {
119   { ANIM_CLASS_BIT_MENU,        GAME_MODE_PSEUDO_MENU   },
120   { ANIM_CLASS_BIT_TOONS,       GAME_MODE_PSEUDO_TOONS  },
121
122   { -1,                         -1                      }
123 };
124
125 /* forward declaration for internal use */
126 static void HandleGlobalAnim(int, int);
127 static void DoAnimationExt(void);
128
129 static struct GlobalAnimControlInfo global_anim_ctrl[NUM_GAME_MODES];
130 static struct ToonInfo toons[MAX_NUM_TOONS];
131
132 static unsigned int anim_sync_frame = 0;
133 static unsigned int anim_sync_frame_delay = 0;
134 static unsigned int anim_sync_frame_delay_value = GAME_FRAME_DELAY;
135
136 static int game_mode_anim_classes[NUM_GAME_MODES];
137 static int anim_class_game_modes[NUM_ANIM_CLASSES];
138
139 static int game_status_last = GAME_MODE_DEFAULT;
140 static int anim_classes_last = ANIM_CLASS_NONE;
141
142
143 static int getGlobalAnimationPart(struct GlobalAnimMainControlInfo *anim)
144 {
145   struct GraphicInfo *c = &anim->control_info;
146   int last_anim_random_frame = gfx.anim_random_frame;
147   int part_nr;
148
149   gfx.anim_random_frame = -1;   // (use simple, ad-hoc random numbers)
150
151   part_nr = getAnimationFrame(anim->num_parts, 1,
152                               c->anim_mode, c->anim_start_frame,
153                               anim->part_counter);
154
155   gfx.anim_random_frame = last_anim_random_frame;
156
157   return part_nr;
158 }
159
160 static void PrepareBackbuffer()
161 {
162   if (game_status != GAME_MODE_PLAYING)
163     return;
164
165   BlitScreenToBitmap(backbuffer);
166 }
167
168 boolean ToonNeedsRedraw()
169 {
170   return TRUE;
171 }
172
173 void InitToons()
174 {
175   int num_toons = MAX_NUM_TOONS;
176   int i;
177
178   if (global.num_toons >= 0 && global.num_toons < MAX_NUM_TOONS)
179     num_toons = global.num_toons;
180
181   for (i = 0; i < num_toons; i++)
182   {
183     int graphic = IMG_TOON_1 + i;
184     struct FileInfo *image = getImageListEntryFromImageID(graphic);
185
186     toons[i].bitmap = graphic_info[graphic].bitmap;
187
188     toons[i].src_x = graphic_info[graphic].src_x;
189     toons[i].src_y = graphic_info[graphic].src_y;
190
191     toons[i].width  = graphic_info[graphic].width;
192     toons[i].height = graphic_info[graphic].height;
193
194     toons[i].anim_frames      = graphic_info[graphic].anim_frames;
195     toons[i].anim_delay       = graphic_info[graphic].anim_delay;
196     toons[i].anim_mode        = graphic_info[graphic].anim_mode;
197     toons[i].anim_start_frame = graphic_info[graphic].anim_start_frame;
198
199     toons[i].step_offset = graphic_info[graphic].step_offset;
200     toons[i].step_delay  = graphic_info[graphic].step_delay;
201
202     toons[i].direction = image->parameter[GFX_ARG_DIRECTION];
203     toons[i].position = image->parameter[GFX_ARG_POSITION];
204   }
205
206   InitToonScreen(bitmap_db_toons,
207                  BackToFront, PrepareBackbuffer, ToonNeedsRedraw,
208                  toons, num_toons,
209                  REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
210                  GAME_FRAME_DELAY);
211 }
212
213 static void InitToonControls()
214 {
215   int mode_nr_toons = GAME_MODE_PSEUDO_TOONS;
216   struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr_toons];
217   struct GlobalAnimMainControlInfo *anim = &ctrl->anim[ctrl->num_anims];
218   int mode_nr, anim_nr, part_nr;
219   int control = IMG_INTERNAL_GLOBAL_TOON_DEFAULT;
220   int num_toons = MAX_NUM_TOONS;
221   int i;
222
223   if (global.num_toons >= 0 && global.num_toons < MAX_NUM_TOONS)
224     num_toons = global.num_toons;
225
226   mode_nr = mode_nr_toons;
227   anim_nr = ctrl->num_anims;
228
229   anim->nr = anim_nr;
230   anim->mode_nr = mode_nr;
231   anim->control_info = graphic_info[control];
232
233   anim->num_parts = 0;
234   anim->part_counter = 0;
235   anim->active_part_nr = 0;
236
237   anim->has_base = FALSE;
238
239   anim->init_delay_counter = 0;
240
241   anim->state = ANIM_STATE_INACTIVE;
242
243   part_nr = 0;
244
245   for (i = 0; i < num_toons; i++)
246   {
247     struct GlobalAnimPartControlInfo *part = &anim->part[part_nr];
248     int graphic = IMG_TOON_1 + i;
249     int control = graphic;
250
251     part->nr = part_nr;
252     part->anim_nr = anim_nr;
253     part->mode_nr = mode_nr;
254     part->graphic = graphic;
255     part->graphic_info = graphic_info[graphic];
256     part->control_info = graphic_info[control];
257
258     part->graphic_info.anim_delay *= part->graphic_info.step_delay;
259
260     part->control_info.init_delay_fixed = 0;
261     part->control_info.init_delay_random = 150;
262
263     part->control_info.x = ARG_UNDEFINED_VALUE;
264     part->control_info.y = ARG_UNDEFINED_VALUE;
265
266     part->initial_anim_sync_frame = 0;
267
268     part->step_delay = 0;
269     part->step_delay_value = graphic_info[control].step_delay;
270
271     part->state = ANIM_STATE_INACTIVE;
272     part->last_game_status = -1;
273
274     anim->num_parts++;
275     part_nr++;
276   }
277
278   ctrl->num_anims++;
279 }
280
281 void InitGlobalAnimControls()
282 {
283   int i, m, a, p;
284   int mode_nr, anim_nr, part_nr;
285   int graphic, control;
286
287   anim_sync_frame = 0;
288
289   ResetDelayCounter(&anim_sync_frame_delay);
290
291   for (m = 0; m < NUM_GAME_MODES; m++)
292   {
293     mode_nr = m;
294
295     struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr];
296
297     ctrl->nr = mode_nr;
298     ctrl->num_anims = 0;
299
300     anim_nr = 0;
301
302     for (a = 0; a < NUM_GLOBAL_ANIMS; a++)
303     {
304       struct GlobalAnimMainControlInfo *anim = &ctrl->anim[anim_nr];
305       int ctrl_id = GLOBAL_ANIM_ID_CONTROL_FIRST + a;
306
307       control = global_anim_info[ctrl_id].graphic[GLOBAL_ANIM_ID_PART_BASE][m];
308
309       // if no base animation parameters defined, use default values
310       if (control == IMG_UNDEFINED)
311         control = IMG_INTERNAL_GLOBAL_ANIM_DEFAULT;
312
313       anim->nr = anim_nr;
314       anim->mode_nr = mode_nr;
315       anim->control_info = graphic_info[control];
316
317       anim->num_parts = 0;
318       anim->part_counter = 0;
319       anim->active_part_nr = 0;
320
321       anim->has_base = FALSE;
322
323       anim->init_delay_counter = 0;
324
325       anim->state = ANIM_STATE_INACTIVE;
326
327       part_nr = 0;
328
329       for (p = 0; p < NUM_GLOBAL_ANIM_PARTS_ALL; p++)
330       {
331         struct GlobalAnimPartControlInfo *part = &anim->part[part_nr];
332
333         graphic = global_anim_info[a].graphic[p][m];
334         control = global_anim_info[ctrl_id].graphic[p][m];
335
336         if (graphic == IMG_UNDEFINED || graphic_info[graphic].bitmap == NULL ||
337             control == IMG_UNDEFINED)
338           continue;
339
340 #if 0
341         printf("::: mode == %d, anim = %d, part = %d [%d, %d, %d] [%d]\n",
342                m, a, p, mode_nr, anim_nr, part_nr, control);
343 #endif
344
345         part->nr = part_nr;
346         part->anim_nr = anim_nr;
347         part->mode_nr = mode_nr;
348         part->graphic = graphic;
349         part->graphic_info = graphic_info[graphic];
350         part->control_info = graphic_info[control];
351
352         part->initial_anim_sync_frame = 0;
353
354         part->step_delay = 0;
355         part->step_delay_value = graphic_info[control].step_delay;
356
357         part->state = ANIM_STATE_INACTIVE;
358         part->last_game_status = -1;
359
360         if (p < GLOBAL_ANIM_ID_PART_BASE)
361         {
362           anim->num_parts++;
363           part_nr++;
364         }
365         else
366         {
367           anim->base = *part;
368           anim->has_base = TRUE;
369         }
370       }
371
372       if (anim->num_parts > 0 || anim->has_base)
373       {
374         ctrl->num_anims++;
375         anim_nr++;
376       }
377     }
378   }
379
380   InitToonControls();
381
382   for (i = 0; i < NUM_GAME_MODES; i++)
383     game_mode_anim_classes[i] = ANIM_CLASS_NONE;
384   for (i = 0; game_mode_anim_classes_list[i].game_mode != -1; i++)
385     game_mode_anim_classes[game_mode_anim_classes_list[i].game_mode] =
386       game_mode_anim_classes_list[i].class;
387
388   for (i = 0; i < NUM_ANIM_CLASSES; i++)
389     anim_class_game_modes[i] = GAME_MODE_DEFAULT;
390   for (i = 0; anim_class_game_modes_list[i].game_mode != -1; i++)
391     anim_class_game_modes[anim_class_game_modes_list[i].class_bit] =
392       anim_class_game_modes_list[i].game_mode;
393
394   game_status_last = GAME_MODE_LOADING;
395   anim_classes_last = ANIM_CLASS_NONE;
396 }
397
398 void InitGlobalAnimations()
399 {
400   InitGlobalAnimControls();
401 }
402
403 void DrawGlobalAnimExt(int drawing_stage)
404 {
405   int anim_classes = game_mode_anim_classes[game_status];
406   int mode_nr;
407   int i;
408
409   // start or stop global animations by change of game mode
410   // (special handling of animations for "current screen" and "all screens")
411   if (game_status != game_status_last)
412   {
413     // stop animations for last screen
414     HandleGlobalAnim(ANIM_STOP, game_status_last);
415
416     // start animations for current screen
417     HandleGlobalAnim(ANIM_START, game_status);
418
419     // start animations for all screens after loading new artwork set
420     if (game_status_last == GAME_MODE_LOADING)
421       HandleGlobalAnim(ANIM_START, GAME_MODE_DEFAULT);
422
423     game_status_last = game_status;
424   }
425
426   // start or stop global animations by change of animation class
427   // (generic handling of animations for "class of screens")
428   if (anim_classes != anim_classes_last)
429   {
430     for (i = 0; i < NUM_ANIM_CLASSES; i++)
431     {
432       int anim_class_check = (1 << i);
433       int anim_class_game_mode = anim_class_game_modes[i];
434       int anim_class_last = anim_classes_last & anim_class_check;
435       int anim_class      = anim_classes      & anim_class_check;
436
437       if (anim_class_last && !anim_class)
438         HandleGlobalAnim(ANIM_STOP, anim_class_game_mode);
439       else if (!anim_class_last && anim_class)
440         HandleGlobalAnim(ANIM_START, anim_class_game_mode);
441     }
442
443     anim_classes_last = anim_classes;
444   }
445
446   if (!setup.toons || game_status == GAME_MODE_LOADING)
447     return;
448
449   if (drawing_stage == DRAW_GLOBAL_ANIM_STAGE_1)
450     DoAnimationExt();
451
452   for (mode_nr = 0; mode_nr < NUM_GAME_MODES; mode_nr++)
453   {
454     struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr];
455     int anim_nr;
456
457 #if 0
458     if (mode_nr != GFX_SPECIAL_ARG_DEFAULT &&
459         mode_nr != game_status)
460       continue;
461 #endif
462
463     for (anim_nr = 0; anim_nr < ctrl->num_anims; anim_nr++)
464     {
465       struct GlobalAnimMainControlInfo *anim = &ctrl->anim[anim_nr];
466       struct GraphicInfo *c = &anim->control_info;
467       int part_first, part_last;
468       int part_nr;
469
470       if (!(anim->state & ANIM_STATE_RUNNING))
471         continue;
472
473       part_first = part_last = anim->active_part_nr;
474
475       if (c->anim_mode & ANIM_ALL || anim->num_parts == 0)
476       {
477         int num_parts = anim->num_parts + (anim->has_base ? 1 : 0);
478
479         part_first = 0;
480         part_last = num_parts - 1;
481       }
482
483       for (part_nr = part_first; part_nr <= part_last; part_nr++)
484       {
485         struct GlobalAnimPartControlInfo *part = &anim->part[part_nr];
486         struct GraphicInfo *g = &part->graphic_info;
487         Bitmap *src_bitmap;
488         int src_x, src_y;
489         int width  = g->width;
490         int height = g->height;
491         int dst_x = part->x;
492         int dst_y = part->y;
493         int cut_x = 0;
494         int cut_y = 0;
495         int sync_frame;
496         int frame;
497
498         if (!(part->state & ANIM_STATE_RUNNING))
499           continue;
500
501         if (part->drawing_stage != drawing_stage)
502           continue;
503
504         if (part->x < 0)
505         {
506           dst_x = 0;
507           width += part->x;
508           cut_x = -part->x;
509         }
510         else if (part->x > part->viewport_width - g->width)
511           width -= (part->x - (part->viewport_width - g->width));
512
513         if (part->y < 0)
514         {
515           dst_y = 0;
516           height += part->y;
517           cut_y = -part->y;
518         }
519         else if (part->y > part->viewport_height - g->height)
520           height -= (part->y - (part->viewport_height - g->height));
521
522         dst_x += part->viewport_x;
523         dst_y += part->viewport_y;
524
525         sync_frame = anim_sync_frame - part->initial_anim_sync_frame;
526         frame = getAnimationFrame(g->anim_frames, g->anim_delay,
527                                   g->anim_mode, g->anim_start_frame,
528                                   sync_frame);
529
530         getFixedGraphicSource(part->graphic, frame, &src_bitmap,
531                               &src_x, &src_y);
532
533         src_x += cut_x;
534         src_y += cut_y;
535
536         BlitToScreenMasked(src_bitmap, src_x, src_y, width, height,
537                            dst_x, dst_y);
538       }
539     }
540   }
541 }
542
543 void DrawGlobalAnim(int drawing_stage)
544 {
545   DrawGlobalAnimExt(drawing_stage);
546 }
547
548 boolean SetGlobalAnimPart_Viewport(struct GlobalAnimPartControlInfo *part)
549 {
550   int viewport_x;
551   int viewport_y;
552   int viewport_width;
553   int viewport_height;
554   boolean changed = FALSE;
555
556   if (part->last_game_status == game_status)
557     return FALSE;
558
559   part->last_game_status = game_status;
560
561   part->drawing_stage = DRAW_GLOBAL_ANIM_STAGE_1;
562
563   if (part->control_info.class == get_hash_from_key("window") ||
564       part->control_info.class == get_hash_from_key("border"))
565   {
566     viewport_x = 0;
567     viewport_y = 0;
568     viewport_width  = WIN_XSIZE;
569     viewport_height = WIN_YSIZE;
570
571     part->drawing_stage = DRAW_GLOBAL_ANIM_STAGE_2;
572   }
573   else if (part->control_info.class == get_hash_from_key("door_1"))
574   {
575     viewport_x = DX;
576     viewport_y = DY;
577     viewport_width  = DXSIZE;
578     viewport_height = DYSIZE;
579   }
580   else if (part->control_info.class == get_hash_from_key("door_2"))
581   {
582     viewport_x = VX;
583     viewport_y = VY;
584     viewport_width  = VXSIZE;
585     viewport_height = VYSIZE;
586   }
587   else          // default: "playfield"
588   {
589     viewport_x = REAL_SX;
590     viewport_y = REAL_SY;
591     viewport_width  = FULL_SXSIZE;
592     viewport_height = FULL_SYSIZE;
593   }
594
595   if (viewport_x != part->viewport_x ||
596       viewport_y != part->viewport_y ||
597       viewport_width  != part->viewport_width ||
598       viewport_height != part->viewport_height)
599   {
600     part->viewport_x = viewport_x;
601     part->viewport_y = viewport_y;
602     part->viewport_width  = viewport_width;
603     part->viewport_height = viewport_height;
604
605     changed = TRUE;
606   }
607
608   return changed;
609 }
610
611 int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state)
612 {
613   struct GraphicInfo *g = &part->graphic_info;
614   struct GraphicInfo *c = &part->control_info;
615   boolean viewport_changed = SetGlobalAnimPart_Viewport(part);
616
617   if (viewport_changed)
618     state |= ANIM_STATE_RESTART;
619
620   if (state & ANIM_STATE_RESTART)
621   {
622     ResetDelayCounterExt(&part->step_delay, anim_sync_frame);
623
624     part->init_delay_counter =
625       (c->init_delay_fixed + GetSimpleRandom(c->init_delay_random));
626
627     part->anim_delay_counter =
628       (c->anim_delay_fixed + GetSimpleRandom(c->anim_delay_random));
629
630     part->initial_anim_sync_frame =
631       (g->anim_global_sync ? 0 : anim_sync_frame + part->init_delay_counter);
632
633     if (c->direction & MV_HORIZONTAL)
634     {
635       int pos_bottom = part->viewport_height - g->height;
636
637       if (c->position == POS_TOP)
638         part->y = 0;
639       else if (c->position == POS_UPPER)
640         part->y = GetSimpleRandom(pos_bottom / 2);
641       else if (c->position == POS_MIDDLE)
642         part->y = pos_bottom / 2;
643       else if (c->position == POS_LOWER)
644         part->y = pos_bottom / 2 + GetSimpleRandom(pos_bottom / 2);
645       else if (c->position == POS_BOTTOM)
646         part->y = pos_bottom;
647       else
648         part->y = GetSimpleRandom(pos_bottom);
649
650       if (c->direction == MV_RIGHT)
651       {
652         part->step_xoffset = c->step_offset;
653         part->x = -g->width + part->step_xoffset;
654       }
655       else
656       {
657         part->step_xoffset = -c->step_offset;
658         part->x = part->viewport_width + part->step_xoffset;
659       }
660
661       part->step_yoffset = 0;
662     }
663     else if (c->direction & MV_VERTICAL)
664     {
665       int pos_right = part->viewport_width - g->width;
666
667       if (c->position == POS_LEFT)
668         part->x = 0;
669       else if (c->position == POS_RIGHT)
670         part->x = pos_right;
671       else
672         part->x = GetSimpleRandom(pos_right);
673
674       if (c->direction == MV_DOWN)
675       {
676         part->step_yoffset = c->step_offset;
677         part->y = -g->height + part->step_yoffset;
678       }
679       else
680       {
681         part->step_yoffset = -c->step_offset;
682         part->y = part->viewport_height + part->step_yoffset;
683       }
684
685       part->step_xoffset = 0;
686     }
687     else
688     {
689       part->x = 0;
690       part->y = 0;
691
692       part->step_xoffset = 0;
693       part->step_yoffset = 0;
694     }
695
696     if (c->x != ARG_UNDEFINED_VALUE)
697       part->x = c->x;
698     if (c->y != ARG_UNDEFINED_VALUE)
699       part->y = c->y;
700
701     if (c->step_xoffset != ARG_UNDEFINED_VALUE)
702       part->step_xoffset = c->step_xoffset;
703     if (c->step_yoffset != ARG_UNDEFINED_VALUE)
704       part->step_yoffset = c->step_yoffset;
705   }
706
707   if (part->init_delay_counter > 0)
708   {
709     part->init_delay_counter--;
710
711     return ANIM_STATE_WAITING;
712   }
713
714   if ((part->x <= -g->width              && part->step_xoffset <= 0) ||
715       (part->x >=  part->viewport_width  && part->step_xoffset >= 0) ||
716       (part->y <= -g->height             && part->step_yoffset <= 0) ||
717       (part->y >=  part->viewport_height && part->step_yoffset >= 0))
718     return ANIM_STATE_RESTART;
719
720   if (part->anim_delay_counter > 0)
721   {
722     part->anim_delay_counter--;
723
724     if (part->anim_delay_counter == 0)
725     {
726       part->post_delay_counter =
727         (c->post_delay_fixed + GetSimpleRandom(c->post_delay_random));
728
729       if (part->post_delay_counter > 0)
730         return ANIM_STATE_RUNNING;
731
732       return ANIM_STATE_RESTART | ANIM_STATE_RUNNING;
733     }
734   }
735
736   if (part->post_delay_counter > 0)
737   {
738     part->post_delay_counter--;
739
740     if (part->post_delay_counter == 0)
741       return ANIM_STATE_RESTART;
742
743     return ANIM_STATE_WAITING;
744   }
745
746   if (!DelayReachedExt(&part->step_delay, part->step_delay_value,
747                        anim_sync_frame))
748     return ANIM_STATE_RUNNING;
749
750 #if 0
751   {
752     static unsigned int last_counter = -1;
753     unsigned int counter = Counter();
754
755     printf("::: NEXT ANIM PART [%d, %d]\n",
756            anim_sync_frame, counter - last_counter);
757
758     last_counter = counter;
759   }
760 #endif
761
762   part->x += part->step_xoffset;
763   part->y += part->step_yoffset;
764
765   return ANIM_STATE_RUNNING;
766 }
767
768 void HandleGlobalAnim_Main(struct GlobalAnimMainControlInfo *anim, int action)
769 {
770   struct GlobalAnimPartControlInfo *part;
771   struct GraphicInfo *c = &anim->control_info;
772   boolean skip = FALSE;
773
774 #if 0
775   printf("::: HandleGlobalAnim_Main: %d, %d => %d\n",
776          anim->mode_nr, anim->nr, anim->num_parts);
777   printf("::: %d, %d, %d\n", global.num_toons, setup.toons, num_toons);
778 #endif
779
780 #if 0
781   printf("::: %s(%d): %d, %d, %d [%d]\n",
782          (action == ANIM_START ? "ANIM_START" :
783           action == ANIM_CONTINUE ? "ANIM_CONTINUE" :
784           action == ANIM_STOP ? "ANIM_STOP" : "(should not happen)"),
785          anim->nr,
786          anim->state & ANIM_STATE_RESTART,
787          anim->state & ANIM_STATE_WAITING,
788          anim->state & ANIM_STATE_RUNNING,
789          anim->num_parts);
790 #endif
791
792   switch (action)
793   {
794     case ANIM_START:
795       anim->state = ANIM_STATE_RESTART;
796       anim->part_counter = 0;
797       anim->active_part_nr = 0;
798       skip = TRUE;
799
800       break;
801
802     case ANIM_CONTINUE:
803       if (anim->state == ANIM_STATE_INACTIVE)
804         skip = TRUE;
805
806       break;
807
808     case ANIM_STOP:
809       anim->state = ANIM_STATE_INACTIVE;
810       skip = TRUE;
811
812       break;
813
814     default:
815       break;
816   }
817
818   if (c->anim_mode & ANIM_ALL || anim->num_parts == 0)
819   {
820     int num_parts = anim->num_parts + (anim->has_base ? 1 : 0);
821     int i;
822
823 #if 0
824     printf("::: HandleGlobalAnim_Main: %d, %d => %d\n",
825            anim->mode_nr, anim->nr, num_parts);
826 #endif
827
828     for (i = 0; i < num_parts; i++)
829     {
830       part = &anim->part[i];
831
832       switch (action)
833       {
834         case ANIM_START:
835           anim->state = ANIM_STATE_RUNNING;
836           part->state = ANIM_STATE_RESTART;
837           skip = TRUE;
838
839           break;
840
841         case ANIM_CONTINUE:
842           if (part->state == ANIM_STATE_INACTIVE)
843             skip = TRUE;
844
845           break;
846
847         case ANIM_STOP:
848           part->state = ANIM_STATE_INACTIVE;
849           skip = TRUE;
850
851           break;
852
853         default:
854           break;
855       }
856
857       if (skip)
858         continue;
859
860       part->state = HandleGlobalAnim_Part(part, part->state);
861     }
862
863     return;
864   }
865
866   if (skip)
867     return;
868
869   if (anim->state & ANIM_STATE_RESTART)         // directly after restart
870     anim->active_part_nr = getGlobalAnimationPart(anim);
871
872   part = &anim->part[anim->active_part_nr];
873
874   part->state = ANIM_STATE_RUNNING;
875
876   anim->state = HandleGlobalAnim_Part(part, anim->state);
877
878   if (anim->state & ANIM_STATE_RESTART)
879     anim->part_counter++;
880 }
881
882 void HandleGlobalAnim_Mode(struct GlobalAnimControlInfo *ctrl, int action)
883 {
884   int i;
885
886 #if 0
887   printf("::: HandleGlobalAnim_Mode: %d => %d\n",
888          ctrl->nr, ctrl->num_anims);
889 #endif
890
891   for (i = 0; i < ctrl->num_anims; i++)
892     HandleGlobalAnim_Main(&ctrl->anim[i], action);
893 }
894
895 static void HandleGlobalAnim(int action, int game_mode)
896 {
897 #if 0
898   printf("::: HandleGlobalAnim [mode == %d]\n", game_status);
899 #endif
900
901   HandleGlobalAnim_Mode(&global_anim_ctrl[game_mode], action);
902 }
903
904 void InitAnimation()
905 {
906 }
907
908 void StopAnimation()
909 {
910 }
911
912 static void DoAnimationExt()
913 {
914   int i;
915
916 #if 0
917   printf("::: DoAnimation [%d, %d]\n", anim_sync_frame, Counter());
918 #endif
919
920 #if 1
921   WaitUntilDelayReached(&anim_sync_frame_delay, anim_sync_frame_delay_value);
922   anim_sync_frame++;
923 #else
924   if (DelayReached(&anim_sync_frame_delay, anim_sync_frame_delay_value))
925     anim_sync_frame++;
926 #endif
927
928   for (i = 0; i < NUM_GAME_MODES; i++)
929     HandleGlobalAnim(ANIM_CONTINUE, i);
930
931 #if 1
932   // force screen redraw in next frame to continue drawing global animations
933   redraw_mask = REDRAW_ALL;
934 #endif
935 }
936
937 void DoAnimation()
938 {
939   // HandleAnimation(ANIM_CONTINUE);
940
941 #if 1
942   // force screen redraw in next frame to continue drawing global animations
943   redraw_mask = REDRAW_ALL;
944 #endif
945 }