anim_classes_last = ANIM_CLASS_NONE;
}
+static void SetGlobalAnimEventsForCustomElements(int list_pos)
+{
+ int num_events = GetGlobalAnimEventValueCount(list_pos);
+ int i;
+
+ for (i = 0; i < num_events; i++)
+ {
+ int event = GetGlobalAnimEventValue(list_pos, i);
+
+ if (event & ANIM_EVENT_CE_CHANGE)
+ {
+ int nr = (event >> ANIM_EVENT_CE_BIT) & 0xff;
+
+ if (nr >= 0 && nr < NUM_CUSTOM_ELEMENTS)
+ element_info[EL_CUSTOM_START + nr].has_anim_event = TRUE;
+ }
+ }
+}
+
+void InitGlobalAnimEventsForCustomElements(void)
+{
+ int m, a, p;
+ int control;
+
+ // custom element events for global animations only relevant while playing
+ m = GAME_MODE_PLAYING;
+
+ for (a = 0; a < NUM_GLOBAL_ANIMS; a++)
+ {
+ int ctrl_id = GLOBAL_ANIM_ID_CONTROL_FIRST + a;
+
+ control = global_anim_info[ctrl_id].graphic[GLOBAL_ANIM_ID_PART_BASE][m];
+
+ // if no base animation parameters defined, use default values
+ if (control == IMG_UNDEFINED)
+ control = IMG_INTERNAL_GLOBAL_ANIM_DEFAULT;
+
+ SetGlobalAnimEventsForCustomElements(graphic_info[control].init_event);
+ SetGlobalAnimEventsForCustomElements(graphic_info[control].anim_event);
+
+ for (p = 0; p < NUM_GLOBAL_ANIM_PARTS_ALL; p++)
+ {
+ control = global_anim_info[ctrl_id].graphic[p][m];
+
+ if (control == IMG_UNDEFINED)
+ continue;
+
+ SetGlobalAnimEventsForCustomElements(graphic_info[control].init_event);
+ SetGlobalAnimEventsForCustomElements(graphic_info[control].anim_event);
+ }
+ }
+}
+
void InitGlobalAnimations(void)
{
InitGlobalAnimControls();
return (anim_event & ANIM_EVENT_SELF);
else if (mask & ANIM_EVENT_UNCLICK_ANY)
return (anim_event & ANIM_EVENT_UNCLICK_ANY);
+ else if (mask & ANIM_EVENT_CE_CHANGE)
+ return (anim_event == mask);
else
return (anim_event == mask ||
anim_event == mask_anim_only);
}
}
+static void InitGlobalAnim_Triggered_ByCustomElement(int nr)
+{
+ struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[GAME_MODE_PLAYING];
+
+ int event_value = ANIM_EVENT_CE_CHANGE;
+ int mask = event_value | (nr << ANIM_EVENT_CE_BIT);
+ int anim2_nr;
+
+ for (anim2_nr = 0; anim2_nr < ctrl->num_anims; anim2_nr++)
+ {
+ struct GlobalAnimMainControlInfo *anim2 = &ctrl->anim[anim2_nr];
+ int part2_nr;
+
+ for (part2_nr = 0; part2_nr < anim2->num_parts_all; part2_nr++)
+ {
+ struct GlobalAnimPartControlInfo *part2 = &anim2->part[part2_nr];
+
+ if (!(part2->state & ANIM_STATE_RUNNING))
+ continue;
+
+ if (isClickablePart(part2, mask))
+ {
+ part2->triggered = TRUE;
+
+#if 0
+ Debug("anim:InitGlobalAnim_Triggered_ByCustomElement",
+ "%d.%d TRIGGERED BY CE %d", anim2_nr, part2_nr, nr + 1);
+#endif
+ }
+ }
+ }
+}
+
static void HandleGlobalAnimDelay(struct GlobalAnimPartControlInfo *part,
int delay_type, char *info_text)
{
{
return anim_sync_frame;
}
+
+void HandleGlobalAnimEventByElementChange(int element)
+{
+ if (!IS_CUSTOM_ELEMENT(element))
+ return;
+
+ InitGlobalAnim_Triggered_ByCustomElement(element - EL_CUSTOM_START);
+}
int getAnimationFrame(int, int, int, int, int);
+void InitGlobalAnimEventsForCustomElements(void);
void InitGlobalAnimations(void);
void DrawGlobalAnimations(int, int);
void RestartGlobalAnimsByStatus(int);
boolean HandleGlobalAnimClicks(int, int, int, boolean);
+void HandleGlobalAnimEventByElementChange(int);
int getGlobalAnimSyncFrame(void);
return string_has_parameter(substring, s_contained);
}
+static int get_anim_parameter_value_ce(char *s)
+{
+ char *s_ptr = s;
+ char *pattern = "ce_change:custom_";
+ int pattern_len = strlen(pattern);
+ char *matching_char = strstr(s_ptr, pattern);
+ int result = ANIM_EVENT_NONE;
+
+ if (matching_char == NULL)
+ return ANIM_EVENT_NONE;
+
+ result = ANIM_EVENT_CE_CHANGE;
+
+ s_ptr = matching_char + pattern_len;
+
+ // check for custom element number ("custom_X" or "custom_XX" or "custom_XXX")
+ if (*s_ptr >= '0' && *s_ptr <= '9')
+ {
+ int gic_ce_nr = (*s_ptr++ - '0');
+
+ if (*s_ptr >= '0' && *s_ptr <= '9')
+ {
+ gic_ce_nr = 10 * gic_ce_nr + (*s_ptr++ - '0');
+
+ if (*s_ptr >= '0' && *s_ptr <= '9')
+ gic_ce_nr = 10 * gic_ce_nr + (*s_ptr++ - '0');
+ }
+
+ if (gic_ce_nr < 1 || gic_ce_nr > NUM_CUSTOM_ELEMENTS)
+ return ANIM_EVENT_NONE;
+
+ // store internal CE number (0 to 255, not "custom_1" to "custom_256")
+ gic_ce_nr--;
+
+ result |= gic_ce_nr << ANIM_EVENT_CE_BIT;
+ }
+ else
+ {
+ // invalid custom element number specified
+
+ return ANIM_EVENT_NONE;
+ }
+
+ // discard result if next character is neither delimiter nor whitespace
+ if (!(*s_ptr == ',' || *s_ptr == '\0' ||
+ *s_ptr == ' ' || *s_ptr == '\t'))
+ return ANIM_EVENT_NONE;
+
+ return result;
+}
+
static int get_anim_parameter_value(char *s)
{
int event_value[] =
int result = ANIM_EVENT_NONE;
int i;
+ result = get_anim_parameter_value_ce(s);
+
+ if (result != ANIM_EVENT_NONE)
+ return result;
+
for (i = 0; i < ARRAY_SIZE(event_value); i++)
{
matching_char = strstr(s_ptr, pattern_1[i]);
// if animation event found, add it to global animation event list
if (event_value != ANIM_EVENT_NONE)
+ {
list_pos = AddGlobalAnimEventValue(list_pos, event_value);
+ // continue with next part of the string, starting with next comma
+ s = strchr(s + 1, ',');
+ }
+
while (s != NULL)
{
// add optional "click:anim_X" or "click:anim_X.part_X" parameter
SET_PROPERTY(ch_delay->element, EP_CAN_CHANGE_OR_HAS_ACTION, TRUE);
}
+ // ---------- initialize if element can trigger global animations -----------
+
+ for (i = 0; i < MAX_NUM_ELEMENTS; i++)
+ {
+ struct ElementInfo *ei = &element_info[i];
+
+ ei->has_anim_event = FALSE;
+ }
+
+ InitGlobalAnimEventsForCustomElements();
+
// ---------- initialize internal run-time variables ------------------------
for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
ChangeCount[x][y]++; // count number of changes in the same frame
+ if (ei->has_anim_event)
+ HandleGlobalAnimEventByElementChange(element);
+
if (change->explode)
{
Bang(x, y);
#define ANIM_EVENT_END (1 << 5)
#define ANIM_EVENT_POST (1 << 6)
#define ANIM_EVENT_UNCLICK_ANY (1 << 7)
+#define ANIM_EVENT_CE_CHANGE (1 << 8)
-// event mask: bits 0-7
-// anim number: bits 8-15
-// part number: bits 16-23
-#define ANIM_EVENT_ANIM_BIT 8
-#define ANIM_EVENT_PART_BIT 16
+// event mask: bits 0-15
+// CE number: bits 16-23
+// anim number: bits 16-23
+// part number: bits 24-31
+#define ANIM_EVENT_CE_BIT 16
+#define ANIM_EVENT_ANIM_BIT 16
+#define ANIM_EVENT_PART_BIT 24
+#define ANIM_EVENT_CE_MASK (0xff << ANIM_EVENT_CE_BIT)
#define ANIM_EVENT_ANIM_MASK (0xff << ANIM_EVENT_ANIM_BIT)
#define ANIM_EVENT_PART_MASK (0xff << ANIM_EVENT_PART_BIT)
struct ElementGroupInfo *group; // pointer to element group info
+ boolean has_anim_event; // element can trigger global animation
+
// ---------- internal values used at runtime when playing ----------
boolean has_change_event[NUM_CHANGE_EVENTS];