X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=666149c277e1194c35a72586529cc89dfe84ec67;hb=7a7f090296fc140cb8d51bcc02759eb0d09ed8c8;hp=82aa0240f6011653f4032bc378cc66c92b4cce40;hpb=4ce4ca0889817ddafeaebb710f8f19bfdbf7d2ea;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 82aa0240..666149c2 100644 --- a/src/game.c +++ b/src/game.c @@ -154,38 +154,144 @@ struct ChangingElementInfo static struct ChangingElementInfo changing_element_list[] = { - { EL_NUT_BREAKING, EL_EMERALD, 6, NULL, NULL, NULL }, - { EL_PEARL_BREAKING, EL_EMPTY, 8, NULL, NULL, NULL }, - { EL_EXIT_OPENING, EL_EXIT_OPEN, 29, NULL, NULL, NULL }, - - { EL_SWITCHGATE_OPENING, EL_SWITCHGATE_OPEN, 29, NULL, NULL, NULL }, - { EL_SWITCHGATE_CLOSING, EL_SWITCHGATE_CLOSED, 29, NULL, NULL, NULL }, - - { EL_TIMEGATE_OPENING, EL_TIMEGATE_OPEN, 29, NULL, NULL, NULL }, - { EL_TIMEGATE_CLOSING, EL_TIMEGATE_CLOSED, 29, NULL, NULL, NULL }, - - { EL_ACID_SPLASH_LEFT, EL_EMPTY, 8, NULL, NULL, NULL }, - { EL_ACID_SPLASH_RIGHT, EL_EMPTY, 8, NULL, NULL, NULL }, - - { EL_SP_BUGGY_BASE, EL_SP_BUGGY_BASE_ACTIVATING, 0, - InitBuggyBase, NULL, NULL }, - { EL_SP_BUGGY_BASE_ACTIVATING,EL_SP_BUGGY_BASE_ACTIVE, 0, - InitBuggyBase, NULL, NULL }, - { EL_SP_BUGGY_BASE_ACTIVE, EL_SP_BUGGY_BASE, 0, - InitBuggyBase, WarnBuggyBase, NULL }, - - { EL_TRAP, EL_TRAP_ACTIVE, 0, - InitTrap, NULL, ActivateTrap }, - { EL_TRAP_ACTIVE, EL_TRAP, 31, - NULL, ChangeActiveTrap, NULL }, - - { EL_ROBOT_WHEEL_ACTIVE, EL_ROBOT_WHEEL, 0, - InitRobotWheel, RunRobotWheel, StopRobotWheel }, + { + EL_NUT_BREAKING, + EL_EMERALD, + 6, + NULL, + NULL, + NULL + }, + { + EL_PEARL_BREAKING, + EL_EMPTY, + 8, + NULL, + NULL, + NULL + }, + { + EL_EXIT_OPENING, + EL_EXIT_OPEN, + 29, + NULL, + NULL, + NULL + }, + { + EL_SWITCHGATE_OPENING, + EL_SWITCHGATE_OPEN, + 29, + NULL, + NULL, + NULL + }, + { + EL_SWITCHGATE_CLOSING, + EL_SWITCHGATE_CLOSED, + 29, + NULL, + NULL, + NULL + }, + { + EL_TIMEGATE_OPENING, + EL_TIMEGATE_OPEN, + 29, + NULL, + NULL, + NULL + }, + { + EL_TIMEGATE_CLOSING, + EL_TIMEGATE_CLOSED, + 29, + NULL, + NULL, + NULL + }, - { EL_TIMEGATE_SWITCH_ACTIVE, EL_TIMEGATE_SWITCH, 0, - InitTimegateWheel, RunTimegateWheel, NULL }, + { + EL_ACID_SPLASH_LEFT, + EL_EMPTY, + 8, + NULL, + NULL, + NULL + }, + { + EL_ACID_SPLASH_RIGHT, + EL_EMPTY, + 8, + NULL, + NULL, + NULL + }, + { + EL_SP_BUGGY_BASE, + EL_SP_BUGGY_BASE_ACTIVATING, + 0, + InitBuggyBase, + NULL, + NULL + }, + { + EL_SP_BUGGY_BASE_ACTIVATING, + EL_SP_BUGGY_BASE_ACTIVE, + 0, + InitBuggyBase, + NULL, + NULL + }, + { + EL_SP_BUGGY_BASE_ACTIVE, + EL_SP_BUGGY_BASE, + 0, + InitBuggyBase, + WarnBuggyBase, + NULL + }, + { + EL_TRAP, + EL_TRAP_ACTIVE, + 0, + InitTrap, + NULL, + ActivateTrap + }, + { + EL_TRAP_ACTIVE, + EL_TRAP, + 31, + NULL, + ChangeActiveTrap, + NULL + }, + { + EL_ROBOT_WHEEL_ACTIVE, + EL_ROBOT_WHEEL, + 0, + InitRobotWheel, + RunRobotWheel, + StopRobotWheel + }, + { + EL_TIMEGATE_SWITCH_ACTIVE, + EL_TIMEGATE_SWITCH, + 0, + InitTimegateWheel, + RunTimegateWheel, + NULL + }, - { EL_UNDEFINED, EL_UNDEFINED, -1, NULL } + { + EL_UNDEFINED, + EL_UNDEFINED, + -1, + NULL, + NULL, + NULL + } }; static struct ChangingElementInfo changing_element[MAX_NUM_ELEMENTS]; @@ -561,6 +667,7 @@ static void InitGameEngine() changing_element[i].post_change_function = NULL; } + /* add changing elements from pre-defined list */ i = 0; while (changing_element_list[i].base_element != EL_UNDEFINED) { @@ -576,6 +683,30 @@ static void InitGameEngine() i++; } + + /* add changing elements from custom element configuration */ + for (i=0; i < NUM_CUSTOM_ELEMENTS; i++) + { + struct CustomElementChangeInfo *change = &level.custom_element[i].change; + int element = EL_CUSTOM_START + i; + + /* only add custom elements that change after fixed/random frame delay */ + if (!IS_CHANGEABLE(element) || + (!HAS_CHANGE_EVENT(element, CE_DELAY_FIXED) && + !HAS_CHANGE_EVENT(element, CE_DELAY_RANDOM))) + continue; + + changing_element[element].base_element = element; + changing_element[element].next_element = change->successor; + changing_element[element].change_delay = 0; + + if (HAS_CHANGE_EVENT(element, CE_DELAY_FIXED)) + changing_element[element].change_delay += + change->delay_fixed * FRAMES_PER_SECOND; + + if (HAS_CHANGE_EVENT(element, CE_DELAY_RANDOM)); + /* random frame delay added at runtime for each element individually */ + } } @@ -1719,7 +1850,7 @@ void Explode(int ex, int ey, int phase, int mode) if (phase == delay) DrawLevelFieldCrumbledSand(x, y); - if (IS_WALKABLE_OVER(Back[x][y])) + if (IS_WALKABLE_OVER(Back[x][y]) && Back[x][y] != EL_EMPTY) { DrawLevelElement(x, y, Back[x][y]); DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame); @@ -4422,10 +4553,22 @@ static void ChangeElement(int x, int y) { int element = Feld[x][y]; + if (IS_MOVING(x, y)) /* never change a running system :-) */ + return; + if (MovDelay[x][y] == 0) /* initialize element change */ { MovDelay[x][y] = changing_element[element].change_delay + 1; + if (IS_CUSTOM_ELEMENT(element) && + HAS_CHANGE_EVENT(element, CE_DELAY_RANDOM)) + { + int i = element - EL_CUSTOM_START; + int max_random_delay = level.custom_element[i].change.delay_random; + + MovDelay[x][y] += RND(max_random_delay * FRAMES_PER_SECOND); + } + ResetGfxAnimation(x, y); ResetRandomAnimationValue(x, y); @@ -4450,6 +4593,11 @@ static void ChangeElement(int x, int y) ResetGfxAnimation(x, y); ResetRandomAnimationValue(x, y); +#if 1 + InitField(x, y, FALSE); + if (CAN_MOVE(element)) + InitMovDir(x, y); +#endif DrawLevelField(x, y); if (changing_element[element].post_change_function) @@ -4653,6 +4801,15 @@ void GameActions() element = Feld[x][y]; graphic = el2img(element); +#if 0 + if (element == -1) + { + printf("::: %d,%d: %d [%d]\n", x, y, element, FrameCounter); + + element = graphic = 0; + } +#endif + if (graphic_info[graphic].anim_global_sync) GfxFrame[x][y] = FrameCounter; @@ -4729,13 +4886,21 @@ void GameActions() MauerAbleger(x, y); else if (element == EL_FLAMES) CheckForDragon(x, y); +#if 0 else if (IS_AUTO_CHANGING(element)) ChangeElement(x, y); +#endif else if (element == EL_EXPLOSION) ; /* drawing of correct explosion animation is handled separately */ - else if (IS_ANIMATED(graphic)) + else if (IS_ANIMATED(graphic) && !IS_AUTO_CHANGING(element)) DrawLevelGraphicAnimationIfNeeded(x, y, graphic); +#if 1 + /* this may take place after moving, therefore element may have changed */ + if (IS_AUTO_CHANGING(Feld[x][y])) + ChangeElement(x, y); +#endif + if (IS_BELT_ACTIVE(element)) PlaySoundLevelAction(x, y, ACTION_ACTIVE); @@ -5152,24 +5317,6 @@ boolean MoveFigure(struct PlayerInfo *player, int dx, int dy) if (!player->active || (!dx && !dy)) return FALSE; -#if 0 - { - static boolean done = FALSE; - static old_count = -1; - - if (FrameCounter < old_count) - done = FALSE; - - if (FrameCounter < 100) - { - printf("::: wanna move [%d] [%d]\n", - FrameCounter, player->push_delay_value); - done = TRUE; - old_count = FrameCounter; - } - } -#endif - #if 0 if (!FrameReached(&player->move_delay, player->move_delay_value) && !tape.playing) @@ -5756,24 +5903,6 @@ int DigField(struct PlayerInfo *player, dy == +1 ? MV_DOWN : MV_NO_MOVING); int element; -#if 0 - { - static boolean done = FALSE; - - if (FrameCounter < 10) - done = FALSE; - - if (!done && - real_dx == -1 && - FrameCounter > 10) - { - printf("::: wanna move left [%d] [%d]\n", - FrameCounter, player->push_delay_value); - done = TRUE; - } - } -#endif - if (player->MovPos == 0) { player->is_digging = FALSE; @@ -5787,6 +5916,7 @@ int DigField(struct PlayerInfo *player, { player->Switching = FALSE; player->push_delay = 0; + return MF_NO_ACTION; } @@ -5831,6 +5961,12 @@ int DigField(struct PlayerInfo *player, element = Feld[x][y]; +#if 1 + if (mode == DF_SNAP && !IS_SNAPPABLE(element) && + game.engine_version >= VERSION_IDENT(2,2,0)) + return MF_NO_ACTION; +#endif + switch (element) { case EL_EMPTY: @@ -6446,6 +6582,7 @@ int DigField(struct PlayerInfo *player, break; default: + if (IS_WALKABLE(element)) { break; @@ -6528,6 +6665,9 @@ boolean SnapField(struct PlayerInfo *player, int dx, int dy) int jx = player->jx, jy = player->jy; int x = jx + dx, y = jy + dy; + if (player->MovPos && game.engine_version >= VERSION_IDENT(2,2,0)) + return FALSE; + if (!player->active || !IN_LEV_FIELD(x, y)) return FALSE; @@ -6558,7 +6698,7 @@ boolean SnapField(struct PlayerInfo *player, int dx, int dy) dy < 0 ? MV_UP : dy > 0 ? MV_DOWN : MV_NO_MOVING); - if (!DigField(player, x, y, 0, 0, DF_SNAP)) + if (DigField(player, x, y, 0, 0, DF_SNAP) == MF_NO_ACTION) return FALSE; player->snapped = TRUE;