From 064d7909aadd84f633fefcccee3c6f6eb44d47ff Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Sun, 30 Jul 2023 01:50:39 +0200 Subject: [PATCH] added support for custom elements triggering global animations For the global animation options ".init_event" or "anim_event" in file "graphicsinfo.conf", the new value "ce_change:custom_xxx" can be used to trigger (initiate or continue) the corresponding global animation whenever custom element "custom_xxx" changes. --- src/anim.c | 96 ++++++++++++++++++++++++++++++++++++++++++++ src/anim.h | 2 + src/files.c | 61 ++++++++++++++++++++++++++++ src/game.c | 14 +++++++ src/libgame/system.h | 14 ++++--- src/main.h | 2 + 6 files changed, 184 insertions(+), 5 deletions(-) diff --git a/src/anim.c b/src/anim.c index 39f7e646..bbc38dc4 100644 --- a/src/anim.c +++ b/src/anim.c @@ -631,6 +631,59 @@ static void InitGlobalAnimControls(void) 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(); @@ -1145,6 +1198,8 @@ static boolean checkGlobalAnimEvent(int anim_event, int mask) 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); @@ -1303,6 +1358,39 @@ static void InitGlobalAnim_Triggered(struct GlobalAnimPartControlInfo *part, } } +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) { @@ -2051,3 +2139,11 @@ int getGlobalAnimSyncFrame(void) { return anim_sync_frame; } + +void HandleGlobalAnimEventByElementChange(int element) +{ + if (!IS_CUSTOM_ELEMENT(element)) + return; + + InitGlobalAnim_Triggered_ByCustomElement(element - EL_CUSTOM_START); +} diff --git a/src/anim.h b/src/anim.h index d16d9237..bf9561fd 100644 --- a/src/anim.h +++ b/src/anim.h @@ -15,12 +15,14 @@ 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); diff --git a/src/files.c b/src/files.c index 58d3e1b7..42208ce6 100644 --- a/src/files.c +++ b/src/files.c @@ -11546,6 +11546,57 @@ static boolean string_has_parameter(char *s, char *s_contained) 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[] = @@ -11571,6 +11622,11 @@ static int get_anim_parameter_value(char *s) 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]); @@ -11657,8 +11713,13 @@ static int get_anim_parameter_values(char *s) // 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 diff --git a/src/game.c b/src/game.c index c3b2ef7e..0d183034 100644 --- a/src/game.c +++ b/src/game.c @@ -3195,6 +3195,17 @@ static void InitGameEngine(void) 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++) @@ -10704,6 +10715,9 @@ static boolean ChangeElement(int x, int y, int element, int page) ChangeCount[x][y]++; // count number of changes in the same frame + if (ei->has_anim_event) + HandleGlobalAnimEventByElementChange(element); + if (change->explode) { Bang(x, y); diff --git a/src/libgame/system.h b/src/libgame/system.h index 44ac3e34..1c6cb88d 100644 --- a/src/libgame/system.h +++ b/src/libgame/system.h @@ -390,13 +390,17 @@ #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) diff --git a/src/main.h b/src/main.h index dc4ea9ac..a32e32a6 100644 --- a/src/main.h +++ b/src/main.h @@ -3591,6 +3591,8 @@ struct ElementInfo 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]; -- 2.34.1