From 1e57e2856183b3ea50b298ec6ffb4307b584c056 Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Tue, 22 Nov 2005 02:32:59 +0100 Subject: [PATCH] rnd-20051122-1-src --- Makefile | 3 + src/conftime.h | 2 +- src/editor.c | 70 ++++++----- src/files.c | 60 ++++++--- src/game.c | 331 ++++++++++++++++++++++++++++++++++++++++++++++--- src/main.h | 95 ++++++++------ src/tape.c | 6 + 7 files changed, 466 insertions(+), 101 deletions(-) diff --git a/Makefile b/Makefile index bf09646d..832269b0 100644 --- a/Makefile +++ b/Makefile @@ -123,6 +123,9 @@ enginetestfast: all enginetestnew: all ./Scripts/make_enginetest.sh new +leveltest: all + ./Scripts/make_enginetest.sh leveltest + backup: ./Scripts/make_backup.sh src diff --git a/src/conftime.h b/src/conftime.h index 8b2851d2..3352ec2e 100644 --- a/src/conftime.h +++ b/src/conftime.h @@ -1 +1 @@ -#define COMPILE_DATE_STRING "[2005-11-20 02:42]" +#define COMPILE_DATE_STRING "[2005-11-22 02:31]" diff --git a/src/editor.c b/src/editor.c index 04409147..4385eb8b 100644 --- a/src/editor.c +++ b/src/editor.c @@ -474,9 +474,9 @@ #define GADGET_ID_CHANGE_PLAYER (GADGET_ID_SELECTBOX_FIRST + 19) #define GADGET_ID_CHANGE_PAGE (GADGET_ID_SELECTBOX_FIRST + 20) #define GADGET_ID_CHANGE_REPLACE_WHEN (GADGET_ID_SELECTBOX_FIRST + 21) -#define GADGET_ID_CHANGE_ACTION (GADGET_ID_SELECTBOX_FIRST + 22) -#define GADGET_ID_CHANGE_ACTION_MODE (GADGET_ID_SELECTBOX_FIRST + 23) -#define GADGET_ID_CHANGE_ACTION_ARG (GADGET_ID_SELECTBOX_FIRST + 24) +#define GADGET_ID_ACTION_TYPE (GADGET_ID_SELECTBOX_FIRST + 22) +#define GADGET_ID_ACTION_MODE (GADGET_ID_SELECTBOX_FIRST + 23) +#define GADGET_ID_ACTION_ARG (GADGET_ID_SELECTBOX_FIRST + 24) #define GADGET_ID_SELECT_CHANGE_PAGE (GADGET_ID_SELECTBOX_FIRST + 25) #define GADGET_ID_GROUP_CHOICE_MODE (GADGET_ID_SELECTBOX_FIRST + 26) @@ -680,9 +680,9 @@ #define ED_SELECTBOX_ID_CHANGE_PLAYER 19 #define ED_SELECTBOX_ID_CHANGE_PAGE 20 #define ED_SELECTBOX_ID_CHANGE_REPLACE_WHEN 21 -#define ED_SELECTBOX_ID_CHANGE_ACTION 22 -#define ED_SELECTBOX_ID_CHANGE_ACTION_MODE 23 -#define ED_SELECTBOX_ID_CHANGE_ACTION_ARG 24 +#define ED_SELECTBOX_ID_ACTION_TYPE 22 +#define ED_SELECTBOX_ID_ACTION_MODE 23 +#define ED_SELECTBOX_ID_ACTION_ARG 24 #define ED_SELECTBOX_ID_SELECT_CHANGE_PAGE 25 #define ED_SELECTBOX_ID_GROUP_CHOICE_MODE 26 @@ -864,7 +864,7 @@ /* values for elements with count for collecting */ #define MIN_COLLECT_COUNT 0 -#define MAX_COLLECT_COUNT 100 +#define MAX_COLLECT_COUNT 255 /* values for random placement */ #define RANDOM_USE_PERCENTAGE 0 @@ -1433,6 +1433,7 @@ static struct ValueTextInfo options_change_direct_action[] = { CE_IMPACT, "impact (on something)" }, { CE_SMASHED, "smashed (from above)" }, + { CE_COUNT_AT_ZERO, "CE count at zero" }, { -1, NULL } }; @@ -1455,6 +1456,7 @@ static struct ValueTextInfo options_change_other_action[] = { CE_SWITCH_OF_X, "switch of" }, { CE_CHANGE_OF_X, "change by page of" }, { CE_EXPLOSION_OF_X, "explosion of" }, + { CE_COUNT_AT_ZERO_OF_X, "CE count at zero of" }, { -1, NULL } }; @@ -1534,7 +1536,7 @@ static struct ValueTextInfo options_change_replace_when[] = { -1, NULL } }; -static struct ValueTextInfo options_change_action[] = +static struct ValueTextInfo options_action_type[] = { { CA_NO_ACTION, "no action" }, { CA_EXIT_PLAYER, "exit player" }, @@ -1545,9 +1547,10 @@ static struct ValueTextInfo options_change_action[] = { CA_DEL_KEY, "remove key" }, { CA_SET_PLAYER_SPEED, "set player speed" }, { CA_SET_GEMS, "set gems" }, - { CA_SET_SCORE, "set score" }, { CA_SET_TIME, "set time" }, - { CA_SET_COUNTER, "set counter" }, + { CA_SET_SCORE, "set score" }, + { CA_SET_CE_SCORE, "set CE score" }, + { CA_SET_CE_COUNT, "set CE count" }, { CA_SET_DYNABOMB_NUMBER, "set bomb number" }, { CA_SET_DYNABOMB_SIZE, "set bomb size" }, { CA_SET_DYNABOMB_POWER, "set bomb power" }, @@ -1558,7 +1561,7 @@ static struct ValueTextInfo options_change_action[] = { -1, NULL } }; -static struct ValueTextInfo options_change_action_mode[] = +static struct ValueTextInfo options_action_mode[] = { { CA_MODE_UNDEFINED, " " }, { CA_MODE_ADD, "+" }, @@ -1570,9 +1573,9 @@ static struct ValueTextInfo options_change_action_mode[] = { -1, NULL } }; -static struct ValueTextInfo options_change_action_arg[] = +static struct ValueTextInfo options_action_arg[] = { - { CA_ARG_PLAYER_HEADLINE, "[players]" }, + { CA_ARG_PLAYER_HEADLINE, "[player]" }, { CA_ARG_PLAYER_1, "1" }, { CA_ARG_PLAYER_2, "2" }, { CA_ARG_PLAYER_3, "3" }, @@ -1580,21 +1583,14 @@ static struct ValueTextInfo options_change_action_arg[] = { CA_ARG_PLAYER_ANY, "any" }, { CA_ARG_PLAYER_TRIGGER, "trigger" }, { CA_ARG_UNDEFINED, " " }, - { CA_ARG_NUMBER_HEADLINE, "[numbers]" }, + { CA_ARG_NUMBER_HEADLINE, "[number]" }, { CA_ARG_0, "0" }, { CA_ARG_1, "1" }, { CA_ARG_2, "2" }, { CA_ARG_3, "3" }, { CA_ARG_4, "4" }, { CA_ARG_5, "5" }, - { CA_ARG_6, "6" }, - { CA_ARG_7, "7" }, - { CA_ARG_8, "8" }, - { CA_ARG_9, "9" }, { CA_ARG_10, "10" }, - { CA_ARG_20, "20" }, - { CA_ARG_25, "25" }, - { CA_ARG_50, "50" }, { CA_ARG_100, "100" }, { CA_ARG_1000, "1000" }, { CA_ARG_UNDEFINED, " " }, @@ -1602,7 +1598,13 @@ static struct ValueTextInfo options_change_action_arg[] = { CA_ARG_NUMBER_MAX, "max" }, { CA_ARG_NUMBER_NORMAL, "normal" }, { CA_ARG_NUMBER_RESET, "reset" }, - { CA_ARG_NUMBER_COUNT, "counter" }, + { CA_ARG_NUMBER_CE_SCORE, "CE score" }, + { CA_ARG_NUMBER_CE_COUNT, "CE count" }, + { CA_ARG_NUMBER_CE_DELAY, "CE delay" }, + { CA_ARG_UNDEFINED, " " }, + { CA_ARG_ELEMENT_HEADLINE, "[element]" }, + { CA_ARG_ELEMENT_TARGET, "target" }, + { CA_ARG_ELEMENT_TRIGGER, "trigger" }, { -1, NULL } }; @@ -1824,26 +1826,26 @@ static struct }, { ED_ELEMENT_SETTINGS_XPOS(1), ED_ELEMENT_SETTINGS_YPOS(13), - GADGET_ID_CHANGE_ACTION, GADGET_ID_NONE, + GADGET_ID_ACTION_TYPE, GADGET_ID_NONE, -1, - options_change_action, - &custom_element_change.change_action, + options_action_type, + &custom_element_change.action_type, NULL, NULL, "action on specified condition" }, { -1, ED_ELEMENT_SETTINGS_YPOS(13), - GADGET_ID_CHANGE_ACTION_MODE, GADGET_ID_CHANGE_ACTION, + GADGET_ID_ACTION_MODE, GADGET_ID_ACTION_TYPE, -1, - options_change_action_mode, - &custom_element_change.change_action_mode, + options_action_mode, + &custom_element_change.action_mode, NULL, NULL, "action operator" }, { -1, ED_ELEMENT_SETTINGS_YPOS(13), - GADGET_ID_CHANGE_ACTION_ARG, GADGET_ID_CHANGE_ACTION_MODE, + GADGET_ID_ACTION_ARG, GADGET_ID_ACTION_MODE, -1, - options_change_action_arg, - &custom_element_change.change_action_arg, + options_action_arg, + &custom_element_change.action_arg, NULL, NULL, "action parameter" }, { @@ -2365,7 +2367,7 @@ static struct { ED_ELEMENT_SETTINGS_XPOS(0), ED_ELEMENT_SETTINGS_YPOS(13), GADGET_ID_CHANGE_USE_ACTION, GADGET_ID_NONE, - &custom_element_change.use_change_action, + &custom_element_change.use_action, NULL, NULL, "execute action on specified condition" }, }; @@ -6311,6 +6313,7 @@ static void CopyCustomElementPropertiesToEditor(int element) HAS_CHANGE_EVENT(element, CE_BLOCKED) ? CE_BLOCKED : HAS_CHANGE_EVENT(element, CE_IMPACT) ? CE_IMPACT : HAS_CHANGE_EVENT(element, CE_SMASHED) ? CE_SMASHED : + HAS_CHANGE_EVENT(element, CE_COUNT_AT_ZERO) ? CE_COUNT_AT_ZERO : custom_element_change.direct_action); /* set "change by other element action" selectbox help value */ @@ -6329,6 +6332,7 @@ static void CopyCustomElementPropertiesToEditor(int element) HAS_CHANGE_EVENT(element, CE_SWITCH_OF_X) ? CE_SWITCH_OF_X : HAS_CHANGE_EVENT(element, CE_CHANGE_OF_X) ? CE_CHANGE_OF_X : HAS_CHANGE_EVENT(element, CE_EXPLOSION_OF_X) ? CE_EXPLOSION_OF_X : + HAS_CHANGE_EVENT(element, CE_COUNT_AT_ZERO_OF_X) ? CE_COUNT_AT_ZERO_OF_X : custom_element_change.other_action); } @@ -6500,6 +6504,7 @@ static void CopyCustomElementPropertiesToGame(int element) custom_element_change_events[CE_BLOCKED] = FALSE; custom_element_change_events[CE_IMPACT] = FALSE; custom_element_change_events[CE_SMASHED] = FALSE; + custom_element_change_events[CE_COUNT_AT_ZERO] = FALSE; custom_element_change_events[custom_element_change.direct_action] = custom_element_change_events[CE_BY_DIRECT_ACTION]; @@ -6518,6 +6523,7 @@ static void CopyCustomElementPropertiesToGame(int element) custom_element_change_events[CE_SWITCH_OF_X] = FALSE; custom_element_change_events[CE_CHANGE_OF_X] = FALSE; custom_element_change_events[CE_EXPLOSION_OF_X] = FALSE; + custom_element_change_events[CE_COUNT_AT_ZERO_OF_X] = FALSE; custom_element_change_events[custom_element_change.other_action] = custom_element_change_events[CE_BY_OTHER_ACTION]; diff --git a/src/files.c b/src/files.c index d522761c..8d3cbc99 100644 --- a/src/files.c +++ b/src/files.c @@ -114,10 +114,10 @@ void setElementChangeInfoToDefaults(struct ElementChangeInfo *change) change->random_percentage = 100; change->replace_when = CP_WHEN_EMPTY; - change->use_change_action = FALSE; - change->change_action = CA_NO_ACTION; - change->change_action_mode = CA_MODE_UNDEFINED; - change->change_action_arg = CA_ARG_UNDEFINED; + change->use_action = FALSE; + change->action_type = CA_NO_ACTION; + change->action_mode = CA_MODE_UNDEFINED; + change->action_arg = CA_ARG_UNDEFINED; for (x = 0; x < 3; x++) for (y = 0; y < 3; y++) @@ -1306,8 +1306,18 @@ static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level) change->trigger_page = (change->trigger_page == CH_PAGE_ANY_FILE ? CH_PAGE_ANY : (1 << change->trigger_page)); +#if 1 + change->use_action = getFile8Bit(file); + change->action_type = getFile8Bit(file); + change->action_mode = getFile8Bit(file); + change->action_arg = getFile16BitBE(file); + + /* some free bytes for future change property values and padding */ + ReadUnusedBytesFromFile(file, 1); +#else /* some free bytes for future change property values and padding */ ReadUnusedBytesFromFile(file, 6); +#endif #else @@ -2711,7 +2721,8 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename) int i, j, x, y; /* map custom element change events that have changed in newer versions - (these following values were accidentally changed in version 3.0.1) */ + (these following values were accidentally changed in version 3.0.1) + (this seems to be needed only for 'ab_levelset3' and 'ab_levelset4') */ if (level->game_version <= VERSION_IDENT(3,0,0,0)) { for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) @@ -2719,7 +2730,7 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename) int element = EL_CUSTOM_START + i; /* order of checking and copying events to be mapped is important */ - for (j = CE_BY_OTHER_ACTION; j >= CE_BY_PLAYER_OBSOLETE; j--) + for (j = CE_BY_OTHER_ACTION; j >= CE_COUNT_AT_ZERO; j--) { if (HAS_CHANGE_EVENT(element, j - 2)) { @@ -2740,20 +2751,30 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename) } } +#if 0 + /* !!! TESTS SHOWED THAT THIS CODE SEGMENT IS NOT NEEDED FOR ANY LEVEL !!! */ + /* some custom element change events get mapped since version 3.0.3 */ - for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) +#if 1 + if (level->game_version >= VERSION_IDENT(3,0,3,0) && + level->game_version <= VERSION_IDENT(3,2,0,3)) +#endif { - int element = EL_CUSTOM_START + i; - - if (HAS_CHANGE_EVENT(element, CE_BY_PLAYER_OBSOLETE) || - HAS_CHANGE_EVENT(element, CE_BY_COLLISION_OBSOLETE)) + for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) { - SET_CHANGE_EVENT(element, CE_BY_PLAYER_OBSOLETE, FALSE); - SET_CHANGE_EVENT(element, CE_BY_COLLISION_OBSOLETE, FALSE); + int element = EL_CUSTOM_START + i; + + if (HAS_CHANGE_EVENT(element, CE_BY_PLAYER_OBSOLETE) || + HAS_CHANGE_EVENT(element, CE_BY_COLLISION_OBSOLETE)) + { + SET_CHANGE_EVENT(element, CE_BY_PLAYER_OBSOLETE, FALSE); + SET_CHANGE_EVENT(element, CE_BY_COLLISION_OBSOLETE, FALSE); - SET_CHANGE_EVENT(element, CE_BY_DIRECT_ACTION, TRUE); + SET_CHANGE_EVENT(element, CE_BY_DIRECT_ACTION, TRUE); + } } } +#endif /* initialize "can_change" field for old levels with only one change page */ if (level->game_version <= VERSION_IDENT(3,0,2,0)) @@ -3388,8 +3409,19 @@ static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element) putFile8Bit(file, (change->trigger_page == CH_PAGE_ANY ? CH_PAGE_ANY_FILE : log_2(change->trigger_page))); +#if 1 + + putFile8Bit(file, change->use_action); + putFile8Bit(file, change->action_type); + putFile8Bit(file, change->action_mode); + putFile16BitBE(file, change->action_arg); + + /* some free bytes for future change property values and padding */ + WriteUnusedBytesToFile(file, 1); +#else /* some free bytes for future change property values and padding */ WriteUnusedBytesToFile(file, 6); +#endif #else diff --git a/src/game.c b/src/game.c index e3007408..78a112f2 100644 --- a/src/game.c +++ b/src/game.c @@ -143,6 +143,8 @@ RND(element_info[e].move_delay_random)) #define GET_MAX_MOVE_DELAY(e) ( (element_info[e].move_delay_fixed) + \ (element_info[e].move_delay_random)) +#define GET_CHANGE_DELAY(c) ( ((c)->delay_fixed * (c)->delay_frames) + \ + RND((c)->delay_random * (c)->delay_frames)) #define GET_TARGET_ELEMENT(e, ch) \ ((e) == EL_TRIGGER_ELEMENT ? (ch)->actual_trigger_element : \ @@ -1130,9 +1132,15 @@ inline void DrawGameValue_Keys(int key[MAX_NUM_KEYS]) /* currently only 4 of 8 possible keys are displayed */ for (i = 0; i < STD_NUM_KEYS; i++) + { if (key[i]) DrawMiniGraphicExt(drawto, DX_KEYS + i * MINI_TILEX, DY_KEYS, el2edimg(EL_KEY_1 + i)); + else + BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, + DOOR_GFX_PAGEX5 + XX_KEYS + i * MINI_TILEX, YY_KEYS, + MINI_TILEX, MINI_TILEY, DX_KEYS + i * MINI_TILEX, DY_KEYS); + } } inline void DrawGameValue_Score(int value) @@ -7859,21 +7867,301 @@ static void ChangeActiveTrap(int x, int y) DrawLevelFieldCrumbledSand(x, y); } -static void HandleChangeAction(int change_action) +static int getSpecialActionElement(int element, int number, int base_element) { - if (change_action == CA_EXIT_PLAYER) - { - printf("::: CA_EXIT_GAME\n"); + return (element != EL_EMPTY ? element : + number != -1 ? base_element + number - 1 : + EL_EMPTY); +} - /* !!! local_player <-> 4 players !!! (EXTEND THIS) !!! */ - local_player->LevelSolved = local_player->GameOver = TRUE; - } - else if (change_action == CA_KILL_PLAYER) - { - printf("::: CA_KILL_PLAYER\n"); +static int getModifiedActionNumber(int value_old, int value_min, int value_max, + int operator, int operand) +{ + int value_new = (operator == CA_MODE_ADD ? value_old + operand : + operator == CA_MODE_SUBTRACT ? value_old - operand : + operator == CA_MODE_MULTIPLY ? value_old * operand : + operator == CA_MODE_DIVIDE ? value_old / MAX(1, operand) : + operator == CA_MODE_SET ? operand : + value_old); + + return (value_new < value_min ? value_min : + value_new > value_max ? value_max : + value_new); +} + +static void ExecuteCustomElementAction(int x, int y, int element, int page) +{ + struct ElementInfo *ei = &element_info[element]; + struct ElementChangeInfo *change = &ei->change_page[page]; + int action_type = change->action_type; + int action_mode = change->action_mode; + int action_arg = change->action_arg; + int i; + + /* ---------- determine action paramater values ---------- */ + + int action_arg_element = + (action_arg == CA_ARG_PLAYER_TRIGGER ? change->actual_trigger_player : + action_arg == CA_ARG_ELEMENT_TRIGGER ? change->actual_trigger_element : + action_arg == CA_ARG_ELEMENT_TARGET ? change->target_element : + EL_EMPTY); + + int action_arg_number = + (action_arg <= CA_ARG_MAX ? action_arg : + action_arg == CA_ARG_NUMBER_MIN ? CA_ARG_MIN : + action_arg == CA_ARG_NUMBER_MAX ? CA_ARG_MAX : + action_arg == CA_ARG_NUMBER_CE_SCORE ? ei->collect_score : + action_arg == CA_ARG_NUMBER_CE_COUNT ? ei->collect_count : + action_arg == CA_ARG_NUMBER_CE_DELAY ? GET_CHANGE_DELAY(change) : + -1); + + /* (for explicit player choice, set invalid value to "no player") */ + int action_arg_player_bits = + (action_arg == CA_ARG_PLAYER_ANY ? action_arg - CA_ARG_PLAYER : + action_arg >= CA_ARG_PLAYER_1 && + action_arg <= CA_ARG_PLAYER_4 ? action_arg - CA_ARG_PLAYER : + action_arg >= CA_ARG_1 && + action_arg <= CA_ARG_PLAYER_4 ? (1 << (action_arg - 1)) : + action_arg_element >= EL_PLAYER_1 && + action_arg_element <= EL_PLAYER_4 ? + (1 << (action_arg_element - EL_PLAYER_1)) : + 0); + + /* (for implicit player choice, set invalid value to "all players") */ + int trigger_player_bits = + (change->actual_trigger_player >= EL_PLAYER_1 && + change->actual_trigger_player <= EL_PLAYER_4 ? + (1 << (change->actual_trigger_player - EL_PLAYER_1)) : + PLAYER_BITS_ANY); + + /* ---------- execute action ---------- */ + + switch(action_type) + { + case CA_NO_ACTION: + { + return; + } + + case CA_EXIT_PLAYER: + { + for (i = 0; i < MAX_PLAYERS; i++) + if (action_arg_player_bits & (1 << i)) + stored_player[i].LevelSolved = stored_player[i].GameOver = TRUE; + + break; + } + + case CA_KILL_PLAYER: + { + for (i = 0; i < MAX_PLAYERS; i++) + if (action_arg_player_bits & (1 << i)) + KillHero(&stored_player[i]); + + break; + } + + case CA_RESTART_LEVEL: + { + printf("::: CA_RESTART_LEVEL -- not yet implemented\n"); + + break; + } + + case CA_SHOW_ENVELOPE: + { + int element = getSpecialActionElement(action_arg_element, + action_arg_number, EL_ENVELOPE_1); + + if (IS_ENVELOPE(element)) + local_player->show_envelope = element; + + break; + } + + case CA_ADD_KEY: + { + int element = getSpecialActionElement(action_arg_element, + action_arg_number, EL_KEY_1); + + if (IS_KEY(element)) + { + for (i = 0; i < MAX_PLAYERS; i++) + { + if (trigger_player_bits & (1 << i)) + { + stored_player[i].key[KEY_NR(element)] = TRUE; + + DrawGameValue_Keys(stored_player[i].key); + + redraw_mask |= REDRAW_DOOR_1; + } + } + } + + break; + } + + case CA_DEL_KEY: + { + int element = getSpecialActionElement(action_arg_element, + action_arg_number, EL_KEY_1); + + if (IS_KEY(element)) + { + for (i = 0; i < MAX_PLAYERS; i++) + { + if (trigger_player_bits & (1 << i)) + { + stored_player[i].key[KEY_NR(element)] = FALSE; + + DrawGameValue_Keys(stored_player[i].key); + + redraw_mask |= REDRAW_DOOR_1; + } + } + } + + break; + } + + case CA_SET_PLAYER_SPEED: + { + for (i = 0; i < MAX_PLAYERS; i++) + { + if (trigger_player_bits & (1 << i)) + { + if (action_arg == CA_ARG_NUMBER_RESET) + stored_player[i].move_delay_value = game.initial_move_delay_value; + else if (action_arg == CA_ARG_NUMBER_NORMAL) + stored_player[i].move_delay_value = MOVE_DELAY_NORMAL_SPEED; + else if (action_arg == CA_ARG_NUMBER_MIN) + stored_player[i].move_delay_value = 16; + else if (action_arg == CA_ARG_NUMBER_MAX) + stored_player[i].move_delay_value = MOVE_DELAY_HIGH_SPEED; + else + { +#if 0 + if (action_mode == CA_MODE_ADD) + { + action_mode = CA_MODE_DIVIDE; + action_arg_number = (1 << action_arg_number); + } + else if (action_mode == CA_MODE_SUBTRACT) + { + action_mode = CA_MODE_MULTIPLY; + action_arg_number = (1 << action_arg_number); + } - /* !!! local_player <-> 4 players !!! (EXTEND THIS) !!! */ - KillHero(local_player); + int mode = (action_mode == CA_MODE_MULTIPLY ? CA_MODE_DIVIDE : + action_mode == CA_MODE_DIVIDE ? CA_MODE_MULTIPLY : + action_mode); + + stored_player[i].move_delay_value = + getModifiedActionNumber(stored_player[i].move_delay_value, + 1, 16, + action_mode, action_arg_number); +#endif + } + } + } + + break; + } + + case CA_SET_GEMS: + { + local_player->gems_still_needed = + getModifiedActionNumber(local_player->gems_still_needed, 0, 999, + action_mode, action_arg_number); + + DrawGameValue_Emeralds(local_player->gems_still_needed); + + break; + } + + case CA_SET_TIME: + { + if (level.time > 0) /* only modify limited time value */ + { + TimeLeft = getModifiedActionNumber(TimeLeft, 0, 9999, + action_mode, action_arg_number); + + DrawGameValue_Time(TimeLeft); + } + + break; + } + + case CA_SET_SCORE: + { + local_player->score = + getModifiedActionNumber(local_player->score, 0, 99999, + action_mode, action_arg_number); + + DrawGameValue_Score(local_player->score); + + break; + } + + case CA_SET_CE_SCORE: + { + printf("::: CA_SET_CE_SCORE -- not yet implemented\n"); + + break; + } + + case CA_SET_CE_COUNT: + { + printf("::: CA_SET_CE_COUNT -- not yet implemented\n"); + + break; + } + + case CA_SET_DYNABOMB_NUMBER: + { + printf("::: CA_SET_DYNABOMB_NUMBER -- not yet implemented\n"); + + break; + } + + case CA_SET_DYNABOMB_SIZE: + { + printf("::: CA_SET_DYNABOMB_SIZE -- not yet implemented\n"); + + break; + } + + case CA_SET_DYNABOMB_POWER: + { + printf("::: CA_SET_DYNABOMB_POWER -- not yet implemented\n"); + + break; + } + + case CA_TOGGLE_PLAYER_GRAVITY: + { + game.gravity = !game.gravity; + + break; + } + + case CA_ENABLE_PLAYER_GRAVITY: + { + game.gravity = TRUE; + + break; + } + + case CA_DISABLE_PLAYER_GRAVITY: + { + game.gravity = FALSE; + + break; + } + + default: + break; } } @@ -7966,8 +8254,10 @@ static void ChangeElementNowExt(struct ElementChangeInfo *change, TestIfElementTouchesCustomElement(x, y); #endif - if (change->use_change_action) - HandleChangeAction(change->change_action); +#if 0 + if (change->use_action) + ExecuteCustomElementAction(...); +#endif } static boolean ChangeElementNow(int x, int y, int element, int page) @@ -7982,7 +8272,7 @@ static boolean ChangeElementNow(int x, int y, int element, int page) if (ChangeEvent[x][y] == CE_DELAY) { - /* reset actual trigger element and player */ + /* reset actual trigger element, trigger player and action element */ change->actual_trigger_element = EL_EMPTY; change->actual_trigger_player = EL_PLAYER_1; } @@ -8210,8 +8500,12 @@ static void ChangeElement(int x, int y, int page) if (ChangeDelay[x][y] == 0) /* initialize element change */ { +#if 1 + ChangeDelay[x][y] = GET_CHANGE_DELAY(change) + 1; +#else ChangeDelay[x][y] = ( change->delay_fixed * change->delay_frames + RND(change->delay_random * change->delay_frames)) + 1; +#endif ResetGfxAnimation(x, y); ResetRandomAnimationValue(x, y); @@ -8254,6 +8548,11 @@ static void ChangeElement(int x, int y, int page) return; } +#if 1 + if (change->use_action) + ExecuteCustomElementAction(x, y, element, page); +#endif + if (ChangeElementNow(x, y, element, page)) { if (change->post_change_function) @@ -11817,7 +12116,9 @@ int DigField(struct PlayerInfo *player, } if (element == EL_SPEED_PILL) + { player->move_delay_value = MOVE_DELAY_HIGH_SPEED; + } else if (element == EL_EXTRA_TIME && level.time > 0) { TimeLeft += 10; diff --git a/src/main.h b/src/main.h index 10fed0f8..a5b300d7 100644 --- a/src/main.h +++ b/src/main.h @@ -187,8 +187,15 @@ #define CE_PLAYER_PUSHES_X 13 #define CE_PLAYER_COLLECTS_X 14 #define CE_PLAYER_DROPS_X 15 + +#if 1 +#define CE_COUNT_AT_ZERO 16 +#define CE_COUNT_AT_ZERO_OF_X 17 +#else #define CE_BY_PLAYER_OBSOLETE 16 /* obsolete; now CE_BY_DIRECT_ACTION */ #define CE_BY_COLLISION_OBSOLETE 17 /* obsolete; now CE_BY_DIRECT_ACTION */ +#endif + #define CE_BY_OTHER_ACTION 18 /* activates other element events */ #define CE_BY_DIRECT_ACTION 19 /* activates direct element events */ #define CE_PLAYER_DIGS_X 20 @@ -243,6 +250,18 @@ (CH_ANY_EVENT_VAR(e) &= ~CH_EVENT_BIT(c))) : 0) #endif +/* values for player bitmasks */ +#define PLAYER_BITS_NONE 0 +#define PLAYER_BITS_1 (1 << 0) +#define PLAYER_BITS_2 (1 << 1) +#define PLAYER_BITS_3 (1 << 2) +#define PLAYER_BITS_4 (1 << 3) +#define PLAYER_BITS_ANY (PLAYER_BITS_1 | \ + PLAYER_BITS_2 | \ + PLAYER_BITS_3 | \ + PLAYER_BITS_4) +#define PLAYER_BITS_TRIGGER (1 << 4) + /* values for change side for custom elements */ #define CH_SIDE_NONE MV_NO_MOVING #define CH_SIDE_LEFT MV_LEFT @@ -254,16 +273,12 @@ #define CH_SIDE_ANY MV_ANY_DIRECTION /* values for change player for custom elements */ -#define CH_PLAYER_NONE 0 -#define CH_PLAYER_1 (1 << 0) -#define CH_PLAYER_2 (1 << 1) -#define CH_PLAYER_3 (1 << 2) -#define CH_PLAYER_4 (1 << 3) -#define CH_PLAYER_ANY (CH_PLAYER_1 | \ - CH_PLAYER_2 | \ - CH_PLAYER_3 | \ - CH_PLAYER_4) -#define CH_PLAYER_TRIGGER (1 << 4) +#define CH_PLAYER_NONE PLAYER_BITS_NONE +#define CH_PLAYER_1 PLAYER_BITS_1 +#define CH_PLAYER_2 PLAYER_BITS_2 +#define CH_PLAYER_3 PLAYER_BITS_3 +#define CH_PLAYER_4 PLAYER_BITS_4 +#define CH_PLAYER_ANY PLAYER_BITS_ANY /* values for change page for custom elements */ #define CH_PAGE_ANY_FILE (0xff) @@ -287,15 +302,16 @@ #define CA_DEL_KEY 6 #define CA_SET_PLAYER_SPEED 7 #define CA_SET_GEMS 8 -#define CA_SET_SCORE 9 -#define CA_SET_TIME 10 -#define CA_SET_COUNTER 11 -#define CA_SET_DYNABOMB_NUMBER 12 -#define CA_SET_DYNABOMB_SIZE 13 -#define CA_SET_DYNABOMB_POWER 14 -#define CA_TOGGLE_PLAYER_GRAVITY 15 -#define CA_ENABLE_PLAYER_GRAVITY 16 -#define CA_DISABLE_PLAYER_GRAVITY 17 +#define CA_SET_TIME 9 +#define CA_SET_SCORE 10 +#define CA_SET_CE_SCORE 11 +#define CA_SET_CE_COUNT 12 +#define CA_SET_DYNABOMB_NUMBER 13 +#define CA_SET_DYNABOMB_SIZE 14 +#define CA_SET_DYNABOMB_POWER 15 +#define CA_TOGGLE_PLAYER_GRAVITY 16 +#define CA_ENABLE_PLAYER_GRAVITY 17 +#define CA_DISABLE_PLAYER_GRAVITY 18 /* values for change action mode for custom elements */ #define CA_MODE_UNDEFINED 0 @@ -306,37 +322,38 @@ #define CA_MODE_SET 5 /* values for change action parameters for custom elements */ +#define CA_ARG_MIN 0 #define CA_ARG_0 0 #define CA_ARG_1 1 #define CA_ARG_2 2 #define CA_ARG_3 3 #define CA_ARG_4 4 #define CA_ARG_5 5 -#define CA_ARG_6 6 -#define CA_ARG_7 7 -#define CA_ARG_8 8 -#define CA_ARG_9 9 #define CA_ARG_10 10 -#define CA_ARG_20 20 -#define CA_ARG_25 25 -#define CA_ARG_50 50 #define CA_ARG_100 100 #define CA_ARG_1000 1000 -#define CA_ARG_PLAYER 20000 +#define CA_ARG_MAX 9999 +#define CA_ARG_PLAYER 10000 #define CA_ARG_PLAYER_HEADLINE (CA_ARG_PLAYER + 0) -#define CA_ARG_PLAYER_1 (CA_ARG_PLAYER + CH_PLAYER_1) -#define CA_ARG_PLAYER_2 (CA_ARG_PLAYER + CH_PLAYER_2) -#define CA_ARG_PLAYER_3 (CA_ARG_PLAYER + CH_PLAYER_3) -#define CA_ARG_PLAYER_4 (CA_ARG_PLAYER + CH_PLAYER_4) -#define CA_ARG_PLAYER_ANY (CA_ARG_PLAYER + CH_PLAYER_ANY) -#define CA_ARG_PLAYER_TRIGGER (CA_ARG_PLAYER + CH_PLAYER_TRIGGER) -#define CA_ARG_NUMBER 30000 +#define CA_ARG_PLAYER_1 (CA_ARG_PLAYER + PLAYER_BITS_1) +#define CA_ARG_PLAYER_2 (CA_ARG_PLAYER + PLAYER_BITS_2) +#define CA_ARG_PLAYER_3 (CA_ARG_PLAYER + PLAYER_BITS_3) +#define CA_ARG_PLAYER_4 (CA_ARG_PLAYER + PLAYER_BITS_4) +#define CA_ARG_PLAYER_ANY (CA_ARG_PLAYER + PLAYER_BITS_ANY) +#define CA_ARG_PLAYER_TRIGGER (CA_ARG_PLAYER + PLAYER_BITS_TRIGGER) +#define CA_ARG_NUMBER 20000 #define CA_ARG_NUMBER_HEADLINE (CA_ARG_NUMBER + 0) #define CA_ARG_NUMBER_MIN (CA_ARG_NUMBER + 1) #define CA_ARG_NUMBER_MAX (CA_ARG_NUMBER + 2) #define CA_ARG_NUMBER_NORMAL (CA_ARG_NUMBER + 3) #define CA_ARG_NUMBER_RESET (CA_ARG_NUMBER + 4) -#define CA_ARG_NUMBER_COUNT (CA_ARG_NUMBER + 5) +#define CA_ARG_NUMBER_CE_SCORE (CA_ARG_NUMBER + 5) +#define CA_ARG_NUMBER_CE_COUNT (CA_ARG_NUMBER + 6) +#define CA_ARG_NUMBER_CE_DELAY (CA_ARG_NUMBER + 7) +#define CA_ARG_ELEMENT 30000 +#define CA_ARG_ELEMENT_HEADLINE (CA_ARG_ELEMENT + 0) +#define CA_ARG_ELEMENT_TARGET (CA_ARG_ELEMENT + 1) +#define CA_ARG_ELEMENT_TRIGGER (CA_ARG_ELEMENT + 2) #define CA_ARG_UNDEFINED 30999 /* values for custom move patterns (bits 0 - 3: basic move directions) */ @@ -1894,10 +1911,10 @@ struct ElementChangeInfo boolean explode; /* explode instead of change */ - boolean use_change_action; /* execute change action after change */ - int change_action; /* type of change action after change */ - int change_action_mode; /* mode of change action after change */ - int change_action_arg; /* parameter of change action after change */ + boolean use_action; /* execute action on specified condition */ + int action_type; /* type of action */ + int action_mode; /* mode of action */ + int action_arg; /* parameter of action */ /* ---------- internal values used at runtime when playing ---------- */ diff --git a/src/tape.c b/src/tape.c index 172af415..05c6f7c2 100644 --- a/src/tape.c +++ b/src/tape.c @@ -1297,6 +1297,12 @@ void AutoPlayTape() continue; } +#if 0 + /* ACTIVATE THIS FOR LOADING/TESTING OF LEVELS ONLY */ + printf("(only testing level)\n"); + continue; +#endif + LoadSolutionTape(level_nr); #if 1 if (tape.no_valid_file) -- 2.34.1