X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=101855843b7c0f39165d2ace5b430bbddb7e395b;hb=ec2269c79c8535f2124dd8b0f0780e25d679be2b;hp=76a9952991770243f7d206eb143d2a11d11adea9;hpb=80e96bb2c18af80bdf42240afb36af0e507d4f3e;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 76a99529..10185584 100644 --- a/src/game.c +++ b/src/game.c @@ -58,9 +58,34 @@ #define USE_FIX_KILLED_BY_NON_WALKABLE (USE_NEW_STUFF * 1) #define USE_FIX_IMPACT_COLLISION (USE_NEW_STUFF * 1) +#define USE_FIX_CE_ACTION_WITH_PLAYER (USE_NEW_STUFF * 1) + +#define USE_PLAYER_REANIMATION (USE_NEW_STUFF * 1) #define USE_GFX_RESET_WHEN_NOT_MOVING (USE_NEW_STUFF * 1) +#define USE_DELAYED_GFX_REDRAW (USE_NEW_STUFF * 0) + +#if USE_DELAYED_GFX_REDRAW +#define TEST_DrawLevelField(x, y) \ + GfxRedraw[x][y] |= GFX_REDRAW_TILE +#define TEST_DrawLevelFieldCrumbledSand(x, y) \ + GfxRedraw[x][y] |= GFX_REDRAW_TILE_CRUMBLED +#define TEST_DrawLevelFieldCrumbledSandNeighbours(x, y) \ + GfxRedraw[x][y] |= GFX_REDRAW_TILE_CRUMBLED_NEIGHBOURS +#define TEST_DrawTwinkleOnField(x, y) \ + GfxRedraw[x][y] |= GFX_REDRAW_TILE_TWINKLED +#else +#define TEST_DrawLevelField(x, y) \ + DrawLevelField(x, y) +#define TEST_DrawLevelFieldCrumbledSand(x, y) \ + DrawLevelFieldCrumbledSand(x, y) +#define TEST_DrawLevelFieldCrumbledSandNeighbours(x, y) \ + DrawLevelFieldCrumbledSandNeighbours(x, y) +#define TEST_DrawTwinkleOnField(x, y) \ + DrawTwinkleOnField(x, y) +#endif + /* for DigField() */ #define DF_NO_PUSH 0 @@ -1103,6 +1128,7 @@ void TestIfBadThingRunsIntoPlayer(int, int, int); void TestIfFriendTouchesBadThing(int, int); void TestIfBadThingTouchesFriend(int, int); void TestIfBadThingTouchesOtherBadThing(int, int); +void TestIfGoodThingGetsHitByBadThing(int, int, int); void KillPlayer(struct PlayerInfo *); void BuryPlayer(struct PlayerInfo *); @@ -1698,6 +1724,7 @@ static void InitPlayerField(int x, int y, int element, boolean init_game) } else { + stored_player[0].initial_element = element; stored_player[0].use_murphy = TRUE; if (!level.use_artwork_element[0]) @@ -1756,6 +1783,17 @@ static void InitPlayerField(int x, int y, int element, boolean init_game) player->jx = player->last_jx = x; player->jy = player->last_jy = y; } + +#if USE_PLAYER_REANIMATION + if (!init_game) + { + int player_nr = GET_PLAYER_NR(element); + struct PlayerInfo *player = &stored_player[player_nr]; + + if (player->active) + player->killed = FALSE; /* if player was just killed, reanimate him */ + } +#endif } static void InitField(int x, int y, boolean init_game) @@ -2411,35 +2449,38 @@ void UpdateGameControlValues() if (gpc->type == TYPE_ELEMENT) { - int last_anim_random_frame = gfx.anim_random_frame; - int element = gpc->value; - int graphic = el2panelimg(element); - - if (gpc->value != gpc->last_value) + if (gpc->value != EL_UNDEFINED && gpc->value != EL_EMPTY) { - gpc->gfx_frame = 0; - gpc->gfx_random = INIT_GFX_RANDOM(); - } - else - { - gpc->gfx_frame++; + int last_anim_random_frame = gfx.anim_random_frame; + int element = gpc->value; + int graphic = el2panelimg(element); - if (ANIM_MODE(graphic) == ANIM_RANDOM && - IS_NEXT_FRAME(gpc->gfx_frame, graphic)) + if (gpc->value != gpc->last_value) + { + gpc->gfx_frame = 0; gpc->gfx_random = INIT_GFX_RANDOM(); - } + } + else + { + gpc->gfx_frame++; - if (ANIM_MODE(graphic) == ANIM_RANDOM) - gfx.anim_random_frame = gpc->gfx_random; + if (ANIM_MODE(graphic) == ANIM_RANDOM && + IS_NEXT_FRAME(gpc->gfx_frame, graphic)) + gpc->gfx_random = INIT_GFX_RANDOM(); + } + + if (ANIM_MODE(graphic) == ANIM_RANDOM) + gfx.anim_random_frame = gpc->gfx_random; - if (ANIM_MODE(graphic) == ANIM_CE_SCORE) - gpc->gfx_frame = element_info[element].collect_score; + if (ANIM_MODE(graphic) == ANIM_CE_SCORE) + gpc->gfx_frame = element_info[element].collect_score; - gpc->frame = getGraphicAnimationFrame(el2panelimg(gpc->value), - gpc->gfx_frame); + gpc->frame = getGraphicAnimationFrame(el2panelimg(gpc->value), + gpc->gfx_frame); - if (ANIM_MODE(graphic) == ANIM_RANDOM) - gfx.anim_random_frame = last_anim_random_frame; + if (ANIM_MODE(graphic) == ANIM_RANDOM) + gfx.anim_random_frame = last_anim_random_frame; + } } } } @@ -3691,10 +3732,11 @@ void InitGame() player->Frame = 0; player->StepFrame = 0; - player->use_murphy = FALSE; + player->initial_element = player->element_nr; player->artwork_element = (level.use_artwork_element[i] ? level.artwork_element[i] : player->element_nr); + player->use_murphy = FALSE; player->block_last_field = FALSE; /* initialized in InitPlayerField() */ player->block_delay_adjustment = 0; /* initialized in InitPlayerField() */ @@ -3880,6 +3922,7 @@ void InitGame() GfxElement[x][y] = EL_UNDEFINED; GfxAction[x][y] = ACTION_DEFAULT; GfxDir[x][y] = MV_NONE; + GfxRedraw[x][y] = GFX_REDRAW_NONE; } SCAN_PLAYFIELD(x, y) @@ -3989,6 +4032,7 @@ void InitGame() some_player->present = FALSE; some_player->active = FALSE; + player->initial_element = some_player->initial_element; player->artwork_element = some_player->artwork_element; player->block_last_field = some_player->block_last_field; @@ -5110,6 +5154,10 @@ static void RemoveField(int x, int y) GfxElement[x][y] = EL_UNDEFINED; GfxAction[x][y] = ACTION_DEFAULT; GfxDir[x][y] = MV_NONE; +#if 0 + /* !!! this would prevent the removed tile from being redrawn !!! */ + GfxRedraw[x][y] = GFX_REDRAW_NONE; +#endif } void RemoveMovingField(int x, int y) @@ -5135,7 +5183,7 @@ void RemoveMovingField(int x, int y) Store[oldx][oldy] = Store2[oldx][oldy] = 0; - DrawLevelField(oldx, oldy); + TEST_DrawLevelField(oldx, oldy); return; } @@ -5164,8 +5212,8 @@ void RemoveMovingField(int x, int y) if (next_element != EL_UNDEFINED) Feld[oldx][oldy] = next_element; - DrawLevelField(oldx, oldy); - DrawLevelField(newx, newy); + TEST_DrawLevelField(oldx, oldy); + TEST_DrawLevelField(newx, newy); } void DrawDynamite(int x, int y) @@ -5828,12 +5876,12 @@ void Explode(int ex, int ey, int phase, int mode) InitField_WithBug2(x, y, FALSE); - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); TestIfElementTouchesCustomElement(x, y); if (GFX_CRUMBLED(element)) - DrawLevelFieldCrumbledSandNeighbours(x, y); + TEST_DrawLevelFieldCrumbledSandNeighbours(x, y); if (IS_PLAYER(x, y) && !PLAYERINFO(x, y)->present) StorePlayer[x][y] = 0; @@ -5847,7 +5895,7 @@ void Explode(int ex, int ey, int phase, int mode) int frame = getGraphicAnimationFrame(graphic, GfxFrame[x][y]); if (phase == delay) - DrawLevelFieldCrumbledSand(x, y); + TEST_DrawLevelFieldCrumbledSand(x, y); if (IS_WALKABLE_OVER(Back[x][y]) && Back[x][y] != EL_EMPTY) { @@ -5924,8 +5972,12 @@ void Bang(int x, int y) { struct PlayerInfo *player = PLAYERINFO(x, y); +#if USE_FIX_CE_ACTION_WITH_PLAYER + element = Feld[x][y] = player->initial_element; +#else element = Feld[x][y] = (player->use_murphy ? EL_SP_MURPHY : player->element_nr); +#endif if (level.use_explosion_element[player->index_nr]) { @@ -6150,7 +6202,7 @@ static void ToggleBeltSwitch(int x, int y) if (e_belt_nr == belt_nr) { Feld[xx][yy] = belt_base_switch_element[belt_nr] + belt_dir_nr; - DrawLevelField(xx, yy); + TEST_DrawLevelField(xx, yy); } } else if (IS_BELT(element) && belt_dir != MV_NONE) @@ -6162,7 +6214,7 @@ static void ToggleBeltSwitch(int x, int y) int belt_part = Feld[xx][yy] - belt_base_element[belt_nr]; Feld[xx][yy] = belt_base_active_element[belt_nr] + belt_part; - DrawLevelField(xx, yy); + TEST_DrawLevelField(xx, yy); } } else if (IS_BELT_ACTIVE(element) && belt_dir == MV_NONE) @@ -6174,7 +6226,7 @@ static void ToggleBeltSwitch(int x, int y) int belt_part = Feld[xx][yy] - belt_base_active_element[belt_nr]; Feld[xx][yy] = belt_base_element[belt_nr] + belt_part; - DrawLevelField(xx, yy); + TEST_DrawLevelField(xx, yy); } } } @@ -6195,34 +6247,34 @@ static void ToggleSwitchgateSwitch(int x, int y) element == EL_SWITCHGATE_SWITCH_DOWN) { Feld[xx][yy] = EL_SWITCHGATE_SWITCH_UP + game.switchgate_pos; - DrawLevelField(xx, yy); + TEST_DrawLevelField(xx, yy); } else if (element == EL_DC_SWITCHGATE_SWITCH_UP || element == EL_DC_SWITCHGATE_SWITCH_DOWN) { Feld[xx][yy] = EL_DC_SWITCHGATE_SWITCH_UP + game.switchgate_pos; - DrawLevelField(xx, yy); + TEST_DrawLevelField(xx, yy); } #else if (element == EL_SWITCHGATE_SWITCH_UP) { Feld[xx][yy] = EL_SWITCHGATE_SWITCH_DOWN; - DrawLevelField(xx, yy); + TEST_DrawLevelField(xx, yy); } else if (element == EL_SWITCHGATE_SWITCH_DOWN) { Feld[xx][yy] = EL_SWITCHGATE_SWITCH_UP; - DrawLevelField(xx, yy); + TEST_DrawLevelField(xx, yy); } else if (element == EL_DC_SWITCHGATE_SWITCH_UP) { Feld[xx][yy] = EL_DC_SWITCHGATE_SWITCH_DOWN; - DrawLevelField(xx, yy); + TEST_DrawLevelField(xx, yy); } else if (element == EL_DC_SWITCHGATE_SWITCH_DOWN) { Feld[xx][yy] = EL_DC_SWITCHGATE_SWITCH_UP; - DrawLevelField(xx, yy); + TEST_DrawLevelField(xx, yy); } #endif else if (element == EL_SWITCHGATE_OPEN || @@ -6270,25 +6322,25 @@ static void RedrawAllLightSwitchesAndInvisibleElements() game.light_time_left > 0) { Feld[x][y] = EL_LIGHT_SWITCH_ACTIVE; - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } else if (element == EL_LIGHT_SWITCH_ACTIVE && game.light_time_left == 0) { Feld[x][y] = EL_LIGHT_SWITCH; - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } else if (element == EL_EMC_DRIPPER && game.light_time_left > 0) { Feld[x][y] = EL_EMC_DRIPPER_ACTIVE; - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } else if (element == EL_EMC_DRIPPER_ACTIVE && game.light_time_left == 0) { Feld[x][y] = EL_EMC_DRIPPER; - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } else if (element == EL_INVISIBLE_STEELWALL || element == EL_INVISIBLE_WALL || @@ -6297,11 +6349,11 @@ static void RedrawAllLightSwitchesAndInvisibleElements() if (game.light_time_left > 0) Feld[x][y] = getInvisibleActiveFromInvisibleElement(element); - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); /* uncrumble neighbour fields, if needed */ if (element == EL_INVISIBLE_SAND) - DrawLevelFieldCrumbledSandNeighbours(x, y); + TEST_DrawLevelFieldCrumbledSandNeighbours(x, y); } else if (element == EL_INVISIBLE_STEELWALL_ACTIVE || element == EL_INVISIBLE_WALL_ACTIVE || @@ -6310,11 +6362,11 @@ static void RedrawAllLightSwitchesAndInvisibleElements() if (game.light_time_left == 0) Feld[x][y] = getInvisibleFromInvisibleActiveElement(element); - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); /* re-crumble neighbour fields, if needed */ if (element == EL_INVISIBLE_SAND) - DrawLevelFieldCrumbledSandNeighbours(x, y); + TEST_DrawLevelFieldCrumbledSandNeighbours(x, y); } } } @@ -6331,13 +6383,13 @@ static void RedrawAllInvisibleElementsForLenses() game.lenses_time_left > 0) { Feld[x][y] = EL_EMC_DRIPPER_ACTIVE; - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } else if (element == EL_EMC_DRIPPER_ACTIVE && game.lenses_time_left == 0) { Feld[x][y] = EL_EMC_DRIPPER; - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } else if (element == EL_INVISIBLE_STEELWALL || element == EL_INVISIBLE_WALL || @@ -6346,11 +6398,11 @@ static void RedrawAllInvisibleElementsForLenses() if (game.lenses_time_left > 0) Feld[x][y] = getInvisibleActiveFromInvisibleElement(element); - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); /* uncrumble neighbour fields, if needed */ if (element == EL_INVISIBLE_SAND) - DrawLevelFieldCrumbledSandNeighbours(x, y); + TEST_DrawLevelFieldCrumbledSandNeighbours(x, y); } else if (element == EL_INVISIBLE_STEELWALL_ACTIVE || element == EL_INVISIBLE_WALL_ACTIVE || @@ -6359,11 +6411,11 @@ static void RedrawAllInvisibleElementsForLenses() if (game.lenses_time_left == 0) Feld[x][y] = getInvisibleFromInvisibleActiveElement(element); - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); /* re-crumble neighbour fields, if needed */ if (element == EL_INVISIBLE_SAND) - DrawLevelFieldCrumbledSandNeighbours(x, y); + TEST_DrawLevelFieldCrumbledSandNeighbours(x, y); } } } @@ -6380,13 +6432,13 @@ static void RedrawAllInvisibleElementsForMagnifier() game.magnify_time_left > 0) { Feld[x][y] = EL_EMC_FAKE_GRASS_ACTIVE; - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } else if (element == EL_EMC_FAKE_GRASS_ACTIVE && game.magnify_time_left == 0) { Feld[x][y] = EL_EMC_FAKE_GRASS; - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } else if (IS_GATE_GRAY(element) && game.magnify_time_left > 0) @@ -6397,8 +6449,10 @@ static void RedrawAllInvisibleElementsForMagnifier() element - EL_EM_GATE_1_GRAY + EL_EM_GATE_1_GRAY_ACTIVE : IS_EMC_GATE_GRAY(element) ? element - EL_EMC_GATE_5_GRAY + EL_EMC_GATE_5_GRAY_ACTIVE : + IS_DC_GATE_GRAY(element) ? + EL_DC_GATE_WHITE_GRAY_ACTIVE : element); - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } else if (IS_GATE_GRAY_ACTIVE(element) && game.magnify_time_left == 0) @@ -6409,8 +6463,10 @@ static void RedrawAllInvisibleElementsForMagnifier() element - EL_EM_GATE_1_GRAY_ACTIVE + EL_EM_GATE_1_GRAY : IS_EMC_GATE_GRAY_ACTIVE(element) ? element - EL_EMC_GATE_5_GRAY_ACTIVE + EL_EMC_GATE_5_GRAY : + IS_DC_GATE_GRAY_ACTIVE(element) ? + EL_DC_GATE_WHITE_GRAY : element); - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } } } @@ -6447,7 +6503,7 @@ static void ActivateTimegateSwitch(int x, int y) else if (element == EL_TIMEGATE_SWITCH_ACTIVE) { Feld[xx][yy] = EL_TIMEGATE_SWITCH; - DrawLevelField(xx, yy); + TEST_DrawLevelField(xx, yy); } */ @@ -6489,7 +6545,7 @@ void Impact(int x, int y) RemoveMovingField(x, y + 1); Feld[x][y + 1] = EL_QUICKSAND_EMPTY; Feld[x][y + 2] = EL_ROCK; - DrawLevelField(x, y + 2); + TEST_DrawLevelField(x, y + 2); object_hit = TRUE; } @@ -6499,7 +6555,7 @@ void Impact(int x, int y) RemoveMovingField(x, y + 1); Feld[x][y + 1] = EL_QUICKSAND_FAST_EMPTY; Feld[x][y + 2] = EL_ROCK; - DrawLevelField(x, y + 2); + TEST_DrawLevelField(x, y + 2); object_hit = TRUE; } @@ -6523,7 +6579,7 @@ void Impact(int x, int y) el_act_dir2img(element, GfxAction[x][y], MV_DOWN) != el2img(element)) { ResetGfxAnimation(x, y); - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } if (impact && CAN_EXPLODE_IMPACT(element)) @@ -6997,7 +7053,7 @@ inline static void TurnRoundExt(int x, int y) { Feld[move_x][move_y] = EL_EMC_SPRING_BUMPER_ACTIVE; ResetGfxAnimation(move_x, move_y); - DrawLevelField(move_x, move_y); + TEST_DrawLevelField(move_x, move_y); MovDir[x][y] = back_dir; } @@ -8102,7 +8158,7 @@ void StartMoving(int x, int y) element == EL_SP_SNIKSNAK || element == EL_SP_ELECTRON || element == EL_MOLE)) - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } } @@ -8136,7 +8192,7 @@ void StartMoving(int x, int y) if (IS_PLAYER(x, y)) DrawPlayerField(x, y); else - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); PlayLevelSoundActionIfLoop(x, y, ACTION_ATTACKING); @@ -8176,7 +8232,7 @@ void StartMoving(int x, int y) if (IN_SCR_FIELD(sx, sy)) { - DrawLevelFieldCrumbledSand(xx, yy); + TEST_DrawLevelFieldCrumbledSand(xx, yy); DrawGraphic(sx, sy, flame_graphic, frame); } } @@ -8184,7 +8240,7 @@ void StartMoving(int x, int y) { if (Feld[xx][yy] == EL_FLAMES) Feld[xx][yy] = EL_EMPTY; - DrawLevelField(xx, yy); + TEST_DrawLevelField(xx, yy); } } } @@ -8227,7 +8283,7 @@ void StartMoving(int x, int y) Feld[newx][newy] == EL_EM_STEEL_EXIT_OPEN) { RemoveField(x, y); - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); PlayLevelSound(newx, newy, SND_PENGUIN_PASSING); if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy))) @@ -8243,7 +8299,7 @@ void StartMoving(int x, int y) else if (IS_FOOD_PENGUIN(Feld[newx][newy])) { if (DigField(local_player, x, y, newx, newy, 0,0, DF_DIG) == MP_MOVING) - DrawLevelField(newx, newy); + TEST_DrawLevelField(newx, newy); else GfxDir[x][y] = MovDir[x][y] = MV_NONE; } @@ -8254,7 +8310,7 @@ void StartMoving(int x, int y) if (IS_PLAYER(x, y)) DrawPlayerField(x, y); else - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); return; } @@ -8268,7 +8324,7 @@ void StartMoving(int x, int y) else { Feld[newx][newy] = EL_EMPTY; - DrawLevelField(newx, newy); + TEST_DrawLevelField(newx, newy); } PlayLevelSound(x, y, SND_PIG_DIGGING); @@ -8278,7 +8334,7 @@ void StartMoving(int x, int y) if (IS_PLAYER(x, y)) DrawPlayerField(x, y); else - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); return; } @@ -8357,7 +8413,7 @@ void StartMoving(int x, int y) else { Feld[newx][newy] = EL_EMPTY; - DrawLevelField(newx, newy); + TEST_DrawLevelField(newx, newy); PlayLevelSoundAction(x, y, ACTION_DIGGING); } @@ -8368,7 +8424,7 @@ void StartMoving(int x, int y) if (IS_PLAYER(x, y)) DrawPlayerField(x, y); else - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); #endif return; @@ -8409,7 +8465,7 @@ void StartMoving(int x, int y) else { RemoveField(newx, newy); - DrawLevelField(newx, newy); + TEST_DrawLevelField(newx, newy); } /* if digged element was about to explode, prevent the explosion */ @@ -8450,7 +8506,7 @@ void StartMoving(int x, int y) if (IS_PLAYER(x, y)) DrawPlayerField(x, y); else - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); return; } @@ -8477,7 +8533,7 @@ void StartMoving(int x, int y) if (IS_PLAYER(x, y)) DrawPlayerField(x, y); else - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); PlayLevelSound(x, y, SND_DRAGON_ATTACKING); @@ -8515,7 +8571,7 @@ void StartMoving(int x, int y) else { Feld[newx][newy] = EL_EMPTY; - DrawLevelField(newx, newy); + TEST_DrawLevelField(newx, newy); } PlayLevelSound(x, y, SND_YAMYAM_DIGGING); @@ -8546,7 +8602,7 @@ void StartMoving(int x, int y) else { Feld[newx][newy] = EL_EMPTY; - DrawLevelField(newx, newy); + TEST_DrawLevelField(newx, newy); } PlayLevelSound(x, y, SND_DARK_YAMYAM_DIGGING); @@ -8569,7 +8625,7 @@ void StartMoving(int x, int y) ResetGfxAnimation(x, y); GfxAction[x][y] = ACTION_DIGGING; - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); MovDelay[newx][newy] = 0; /* start amoeba shrinking delay */ @@ -8578,7 +8634,7 @@ void StartMoving(int x, int y) else /* element == EL_PACMAN */ { Feld[newx][newy] = EL_EMPTY; - DrawLevelField(newx, newy); + TEST_DrawLevelField(newx, newy); PlayLevelSound(x, y, SND_PACMAN_DIGGING); } } @@ -8660,7 +8716,7 @@ void ContinueMoving(int x, int y) GfxAction[x][y], GfxDir[x][y], GfxFrame[x][y]); #endif - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); return; /* element is still moving */ } @@ -8679,7 +8735,7 @@ void ContinueMoving(int x, int y) { Feld[x][y] = EL_SAND; - DrawLevelFieldCrumbledSandNeighbours(x, y); + TEST_DrawLevelFieldCrumbledSandNeighbours(x, y); } else if (element == EL_QUICKSAND_FILLING) { @@ -8846,7 +8902,7 @@ void ContinueMoving(int x, int y) InitField(x, y, FALSE); if (GFX_CRUMBLED(Feld[x][y])) - DrawLevelFieldCrumbledSandNeighbours(x, y); + TEST_DrawLevelFieldCrumbledSandNeighbours(x, y); if (ELEM_IS_PLAYER(move_leave_element)) RelocatePlayer(x, y, move_leave_element); @@ -8862,8 +8918,8 @@ void ContinueMoving(int x, int y) element_info[element].move_pattern == MV_WHEN_DROPPED))) GfxDir[x][y] = MovDir[newx][newy] = 0; - DrawLevelField(x, y); - DrawLevelField(newx, newy); + TEST_DrawLevelField(x, y); + TEST_DrawLevelField(newx, newy); Stop[newx][newy] = TRUE; /* ignore this element until the next frame */ @@ -8908,6 +8964,11 @@ void ContinueMoving(int x, int y) else if (element == EL_PENGUIN) TestIfFriendTouchesBadThing(newx, newy); + if (DONT_GET_HIT_BY(element)) + { + TestIfGoodThingGetsHitByBadThing(newx, newy, direction); + } + /* give the player one last chance (one more frame) to move away */ if (CAN_FALL(element) && direction == MV_DOWN && (last_line || (!IS_FREE(x, newy + 1) && @@ -9125,7 +9186,7 @@ void AmoebeUmwandelnBD(int ax, int ay, int new_element) AmoebaNr[x][y] = 0; Feld[x][y] = new_element; InitField(x, y, FALSE); - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); done = TRUE; } } @@ -9167,7 +9228,7 @@ void AmoebeWaechst(int x, int y) { Feld[x][y] = Store[x][y]; Store[x][y] = 0; - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } } } @@ -9199,7 +9260,7 @@ void AmoebaDisappearing(int x, int y) if (!MovDelay[x][y]) { Feld[x][y] = EL_EMPTY; - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); /* don't let mole enter this field in this cycle; (give priority to objects falling to this field from above) */ @@ -9226,7 +9287,7 @@ void AmoebeAbleger(int ax, int ay) if (!level.amoeba_speed && element != EL_EMC_DRIPPER) { Feld[ax][ay] = EL_AMOEBA_DEAD; - DrawLevelField(ax, ay); + TEST_DrawLevelField(ax, ay); return; } @@ -9296,7 +9357,7 @@ void AmoebeAbleger(int ax, int ay) if (i == 4 && (!waiting_for_player || element == EL_BD_AMOEBA)) { Feld[ax][ay] = EL_AMOEBA_DEAD; - DrawLevelField(ax, ay); + TEST_DrawLevelField(ax, ay); AmoebaCnt[AmoebaNr[ax][ay]]--; if (AmoebaCnt[AmoebaNr[ax][ay]] <= 0) /* amoeba is completely dead */ @@ -9360,7 +9421,7 @@ void AmoebeAbleger(int ax, int ay) return; } - DrawLevelField(newax, neway); + TEST_DrawLevelField(newax, neway); } void Life(int ax, int ay) @@ -9418,7 +9479,7 @@ void Life(int ax, int ay) { Feld[xx][yy] = EL_EMPTY; if (!Stop[xx][yy]) - DrawLevelField(xx, yy); + TEST_DrawLevelField(xx, yy); Stop[xx][yy] = TRUE; changed = TRUE; } @@ -9431,7 +9492,7 @@ void Life(int ax, int ay) Feld[xx][yy] = element; MovDelay[xx][yy] = (element == EL_GAME_OF_LIFE ? 0 : life_time-1); if (!Stop[xx][yy]) - DrawLevelField(xx, yy); + TEST_DrawLevelField(xx, yy); Stop[xx][yy] = TRUE; changed = TRUE; } @@ -9695,28 +9756,28 @@ void MauerWaechst(int x, int y) if (MovDir[x][y] == MV_LEFT) { if (IN_LEV_FIELD(x - 1, y) && IS_WALL(Feld[x - 1][y])) - DrawLevelField(x - 1, y); + TEST_DrawLevelField(x - 1, y); } else if (MovDir[x][y] == MV_RIGHT) { if (IN_LEV_FIELD(x + 1, y) && IS_WALL(Feld[x + 1][y])) - DrawLevelField(x + 1, y); + TEST_DrawLevelField(x + 1, y); } else if (MovDir[x][y] == MV_UP) { if (IN_LEV_FIELD(x, y - 1) && IS_WALL(Feld[x][y - 1])) - DrawLevelField(x, y - 1); + TEST_DrawLevelField(x, y - 1); } else { if (IN_LEV_FIELD(x, y + 1) && IS_WALL(Feld[x][y + 1])) - DrawLevelField(x, y + 1); + TEST_DrawLevelField(x, y + 1); } Feld[x][y] = Store[x][y]; Store[x][y] = 0; GfxDir[x][y] = MovDir[x][y] = MV_NONE; - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } } } @@ -9807,7 +9868,7 @@ void MauerAbleger(int ax, int ay) } if (element == EL_EXPANDABLE_WALL && (links_frei || rechts_frei)) - DrawLevelField(ax, ay); + TEST_DrawLevelField(ax, ay); if (!IN_LEV_FIELD(ax, ay-1) || IS_WALL(Feld[ax][ay-1])) oben_massiv = TRUE; @@ -9971,7 +10032,7 @@ void CheckForDragon(int x, int y) if (IN_LEV_FIELD(xx, yy) && Feld[xx][yy] == EL_FLAMES) { Feld[xx][yy] = EL_EMPTY; - DrawLevelField(xx, yy); + TEST_DrawLevelField(xx, yy); } else break; @@ -10035,7 +10096,7 @@ static void ChangeActiveTrap(int x, int y) /* if new animation frame was drawn, correct crumbled sand border */ if (IS_NEW_FRAME(GfxFrame[x][y], graphic)) - DrawLevelFieldCrumbledSand(x, y); + TEST_DrawLevelFieldCrumbledSand(x, y); } static int getSpecialActionElement(int element, int number, int base_element) @@ -10590,10 +10651,10 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change) ResetRandomAnimationValue(x, y); #endif - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); if (GFX_CRUMBLED(new_element)) - DrawLevelFieldCrumbledSandNeighbours(x, y); + TEST_DrawLevelFieldCrumbledSandNeighbours(x, y); } #if 1 @@ -11961,7 +12022,7 @@ void GameActions_RND() if (MovDelay[x][y] <= 0) { RemoveField(x, y); - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); TestIfElementTouchesCustomElement(x, y); /* for empty space */ } @@ -11995,7 +12056,7 @@ void GameActions_RND() if (GfxAction[x][y] == ACTION_PUSHING && !IS_MOVING(x, y)) { ResetGfxAnimation(x, y); - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } #if DEBUG @@ -12130,7 +12191,7 @@ void GameActions_RND() DrawLevelGraphicAnimationIfNeeded(x, y, graphic); if (IS_GEM(element) || element == EL_SP_INFOTRON) - DrawTwinkleOnField(x, y); + TEST_DrawTwinkleOnField(x, y); } else if (IS_MOVING(x, y)) ContinueMoving(x, y); @@ -12265,7 +12326,7 @@ void GameActions_RND() DrawLevelGraphicAnimationIfNeeded(x, y, graphic); if (IS_GEM(element) || element == EL_SP_INFOTRON) - DrawTwinkleOnField(x, y); + TEST_DrawTwinkleOnField(x, y); } else if ((element == EL_ACID || element == EL_EXIT_OPEN || @@ -12450,19 +12511,19 @@ void GameActions_RND() element == EL_MAGIC_WALL_FULL) { Feld[x][y] = EL_MAGIC_WALL_DEAD; - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } else if (element == EL_BD_MAGIC_WALL_ACTIVE || element == EL_BD_MAGIC_WALL_FULL) { Feld[x][y] = EL_BD_MAGIC_WALL_DEAD; - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } else if (element == EL_DC_MAGIC_WALL_ACTIVE || element == EL_DC_MAGIC_WALL_FULL) { Feld[x][y] = EL_DC_MAGIC_WALL_DEAD; - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } } @@ -12516,6 +12577,36 @@ void GameActions_RND() } } +#if USE_DELAYED_GFX_REDRAW + SCAN_PLAYFIELD(x, y) + { +#if 1 + if (GfxRedraw[x][y] != GFX_REDRAW_NONE) +#else + if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)) && + GfxRedraw[x][y] != GFX_REDRAW_NONE) +#endif + { + /* !!! PROBLEM: THIS REDRAWS THE PLAYFIELD _AFTER_ THE SCAN, BUT TILES + !!! MAY HAVE CHANGED AFTER BEING DRAWN DURING PLAYFIELD SCAN !!! */ + + if (GfxRedraw[x][y] & GFX_REDRAW_TILE) + DrawLevelField(x, y); + + if (GfxRedraw[x][y] & GFX_REDRAW_TILE_CRUMBLED) + DrawLevelFieldCrumbledSand(x, y); + + if (GfxRedraw[x][y] & GFX_REDRAW_TILE_CRUMBLED_NEIGHBOURS) + DrawLevelFieldCrumbledSandNeighbours(x, y); + + if (GfxRedraw[x][y] & GFX_REDRAW_TILE_TWINKLED) + DrawTwinkleOnField(x, y); + } + + GfxRedraw[x][y] = GFX_REDRAW_NONE; + } +#endif + CheckLevelTime(); DrawAllPlayers(); @@ -12600,12 +12691,13 @@ static boolean AllPlayersInVisibleScreen() void ScrollLevel(int dx, int dy) { -#if 1 +#if 0 + /* (directly solved in BlitBitmap() now) */ static Bitmap *bitmap_db_field2 = NULL; int softscroll_offset = (setup.soft_scrolling ? TILEX : 0); int x, y; #else - int i, x, y; + int x, y; #endif #if 0 @@ -12615,7 +12707,8 @@ void ScrollLevel(int dx, int dy) return; #endif -#if 1 +#if 0 + /* (directly solved in BlitBitmap() now) */ if (bitmap_db_field2 == NULL) bitmap_db_field2 = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH); @@ -13073,7 +13166,7 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) else if (old_jx == jx && old_jy != jy) player->MovDir = (old_jy < jy ? MV_DOWN : MV_UP); - DrawLevelField(jx, jy); /* for "crumbled sand" */ + TEST_DrawLevelField(jx, jy); /* for "crumbled sand" */ player->last_move_dir = player->MovDir; player->is_moving = TRUE; @@ -13258,8 +13351,13 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) CE_PLAYER_ENTERS_X, player->index_bit, enter_side); +#if USE_FIX_CE_ACTION_WITH_PLAYER + CheckTriggeredElementChangeBySide(jx, jy, player->initial_element, + CE_MOVE_OF_X, move_direction); +#else CheckTriggeredElementChangeBySide(jx, jy, player->element_nr, CE_MOVE_OF_X, move_direction); +#endif } if (game.engine_version >= VERSION_IDENT(3,0,7,0)) @@ -13386,7 +13484,7 @@ void TestIfPlayerTouchesCustomElement(int x, int y) if (!IN_LEV_FIELD(xx, yy)) continue; - if (IS_PLAYER(x, y)) + if (IS_PLAYER(x, y)) /* player found at center element */ { struct PlayerInfo *player = PLAYERINFO(x, y); @@ -13404,8 +13502,21 @@ void TestIfPlayerTouchesCustomElement(int x, int y) CheckTriggeredElementChangeByPlayer(xx, yy, border_element, CE_PLAYER_TOUCHES_X, player->index_bit, border_side); + +#if USE_FIX_CE_ACTION_WITH_PLAYER + { + /* use player element that is initially defined in the level playfield, + not the player element that corresponds to the runtime player number + (example: a level that contains EL_PLAYER_3 as the only player would + incorrectly give EL_PLAYER_1 for "player->element_nr") */ + int player_element = PLAYERINFO(x, y)->initial_element; + + CheckElementChangeBySide(xx, yy, border_element, player_element, + CE_TOUCHING_X, border_side); + } +#endif } - else if (IS_PLAYER(xx, yy)) + else if (IS_PLAYER(xx, yy)) /* player found at border element */ { struct PlayerInfo *player = PLAYERINFO(xx, yy); @@ -13420,6 +13531,20 @@ void TestIfPlayerTouchesCustomElement(int x, int y) CheckTriggeredElementChangeByPlayer(x, y, center_element, CE_PLAYER_TOUCHES_X, player->index_bit, center_side); + +#if USE_FIX_CE_ACTION_WITH_PLAYER + { + /* use player element that is initially defined in the level playfield, + not the player element that corresponds to the runtime player number + (example: a level that contains EL_PLAYER_3 as the only player would + incorrectly give EL_PLAYER_1 for "player->element_nr") */ + int player_element = PLAYERINFO(xx, yy)->initial_element; + + CheckElementChangeBySide(x, y, center_element, player_element, + CE_TOUCHING_X, center_side); + } +#endif + break; } } @@ -13492,10 +13617,14 @@ void TestIfElementTouchesCustomElement(int x, int y) /* check for change of border element */ CheckElementChangeBySide(xx, yy, border_element, center_element, CE_TOUCHING_X, center_side); + + /* (center element cannot be player, so we dont have to check this here) */ } for (i = 0; i < NUM_DIRECTIONS; i++) { + int xx = x + xy[i][0]; + int yy = y + xy[i][1]; int border_side = trigger_sides[i][1]; int border_element = border_element_old[i]; @@ -13507,6 +13636,20 @@ void TestIfElementTouchesCustomElement(int x, int y) change_center_element = CheckElementChangeBySide(x, y, center_element, border_element, CE_TOUCHING_X, border_side); + +#if USE_FIX_CE_ACTION_WITH_PLAYER + if (IS_PLAYER(xx, yy)) + { + /* use player element that is initially defined in the level playfield, + not the player element that corresponds to the runtime player number + (example: a level that contains EL_PLAYER_3 as the only player would + incorrectly give EL_PLAYER_1 for "player->element_nr") */ + int player_element = PLAYERINFO(xx, yy)->initial_element; + + CheckElementChangeBySide(x, y, center_element, player_element, + CE_TOUCHING_X, border_side); + } +#endif } } @@ -13604,11 +13747,25 @@ void TestIfElementHitsCustomElement(int x, int y, int direction) CheckElementChangeBySide(x, y, hitting_element, touched_element, CE_HITTING_X, touched_side); - CheckElementChangeBySide(hitx, hity, touched_element, - hitting_element, CE_HIT_BY_X, hitting_side); + CheckElementChangeBySide(hitx, hity, touched_element, hitting_element, + CE_HIT_BY_X, hitting_side); CheckElementChangeBySide(hitx, hity, touched_element, hitting_element, CE_HIT_BY_SOMETHING, opposite_direction); + +#if USE_FIX_CE_ACTION_WITH_PLAYER + if (IS_PLAYER(hitx, hity)) + { + /* use player element that is initially defined in the level playfield, + not the player element that corresponds to the runtime player number + (example: a level that contains EL_PLAYER_3 as the only player would + incorrectly give EL_PLAYER_1 for "player->element_nr") */ + int player_element = PLAYERINFO(hitx, hity)->initial_element; + + CheckElementChangeBySide(x, y, hitting_element, player_element, + CE_HITTING_X, touched_side); + } +#endif } } @@ -13781,6 +13938,7 @@ void TestIfBadThingHitsGoodThing(int bad_x, int bad_y, int bad_move_dir) test_x = bad_x + test_xy[i][0]; test_y = bad_y + test_xy[i][1]; + if (!IN_LEV_FIELD(test_x, test_y)) continue; @@ -13811,12 +13969,14 @@ void TestIfBadThingHitsGoodThing(int bad_x, int bad_y, int bad_move_dir) kill_x = test_x; kill_y = test_y; + break; } else if (test_element == EL_PENGUIN) { kill_x = test_x; kill_y = test_y; + break; } } @@ -13839,6 +13999,63 @@ void TestIfBadThingHitsGoodThing(int bad_x, int bad_y, int bad_move_dir) } } +void TestIfGoodThingGetsHitByBadThing(int bad_x, int bad_y, int bad_move_dir) +{ + int bad_element = Feld[bad_x][bad_y]; + int dx = (bad_move_dir == MV_LEFT ? -1 : bad_move_dir == MV_RIGHT ? +1 : 0); + int dy = (bad_move_dir == MV_UP ? -1 : bad_move_dir == MV_DOWN ? +1 : 0); + int test_x = bad_x + dx, test_y = bad_y + dy; + int test_move_dir, test_element; + int kill_x = -1, kill_y = -1; + + if (!IN_LEV_FIELD(test_x, test_y)) + return; + + test_move_dir = + (IS_MOVING(test_x, test_y) ? MovDir[test_x][test_y] : MV_NONE); + + test_element = Feld[test_x][test_y]; + + if (test_move_dir != bad_move_dir) + { + /* good thing can be player or penguin that does not move away */ + if (IS_PLAYER(test_x, test_y)) + { + struct PlayerInfo *player = PLAYERINFO(test_x, test_y); + + /* (note: in comparison to DONT_RUN_TO and DONT_TOUCH, also handle the + player as being hit when he is moving towards the bad thing, because + the "get hit by" condition would be lost after the player stops) */ + if (player->MovPos != 0 && player->MovDir == bad_move_dir) + return; /* player moves away from bad thing */ + + kill_x = test_x; + kill_y = test_y; + } + else if (test_element == EL_PENGUIN) + { + kill_x = test_x; + kill_y = test_y; + } + } + + if (kill_x != -1 || kill_y != -1) + { + if (IS_PLAYER(kill_x, kill_y)) + { + struct PlayerInfo *player = PLAYERINFO(kill_x, kill_y); + + if (player->shield_deadly_time_left > 0 && + !IS_INDESTRUCTIBLE(bad_element)) + Bang(bad_x, bad_y); + else if (!PLAYER_ENEMY_PROTECTED(kill_x, kill_y)) + KillPlayer(player); + } + else + Bang(kill_x, kill_y); + } +} + void TestIfPlayerTouchesBadThing(int x, int y) { TestIfGoodThingHitsBadThing(x, y, MV_NONE); @@ -13935,7 +14152,13 @@ void KillPlayer(struct PlayerInfo *player) player->shield_deadly_time_left = 0; Bang(jx, jy); + +#if USE_PLAYER_REANIMATION + if (player->killed) /* player may have been reanimated */ + BuryPlayer(player); +#else BuryPlayer(player); +#endif } static void KillPlayerUnlessEnemyProtected(int x, int y) @@ -13976,7 +14199,7 @@ void RemovePlayer(struct PlayerInfo *player) StorePlayer[jx][jy] = 0; if (player->is_moving) - DrawLevelField(player->last_jx, player->last_jy); + TEST_DrawLevelField(player->last_jx, player->last_jy); for (i = 0; i < MAX_PLAYERS; i++) if (stored_player[i].active) @@ -14534,13 +14757,6 @@ static int DigField(struct PlayerInfo *player, CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, nextx, nexty))))) return MP_NO_ACTION; - if (IS_CUSTOM_ELEMENT(element) && - CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, nextx, nexty)) - { - if (!DigFieldByCE(nextx, nexty, element)) - return MP_NO_ACTION; - } - if (!checkDiagonalPushing(player, x, y, real_dx, real_dy)) return MP_NO_ACTION; @@ -14558,6 +14774,13 @@ static int DigField(struct PlayerInfo *player, return MP_NO_ACTION; } + if (IS_CUSTOM_ELEMENT(element) && + CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, nextx, nexty)) + { + if (!DigFieldByCE(nextx, nexty, element)) + return MP_NO_ACTION; + } + if (IS_SB_ELEMENT(element)) { if (element == EL_SOKOBAN_FIELD_FULL) @@ -14643,7 +14866,7 @@ static int DigField(struct PlayerInfo *player, game.robot_wheel_active = TRUE; - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } else if (element == EL_SP_TERMINAL) { @@ -14698,7 +14921,7 @@ static int DigField(struct PlayerInfo *player, local_player->lights_still_needed--; ResetGfxAnimation(x, y); - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } else if (element == EL_TIME_ORB_FULL) { @@ -14718,7 +14941,7 @@ static int DigField(struct PlayerInfo *player, } ResetGfxAnimation(x, y); - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } else if (element == EL_EMC_MAGIC_BALL_SWITCH || element == EL_EMC_MAGIC_BALL_SWITCH_ACTIVE) @@ -14830,7 +15053,7 @@ static boolean DigFieldByCE(int x, int y, int digging_element) else { RemoveField(x, y); - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); } /* if digged element was about to explode, prevent the explosion */ @@ -14932,9 +15155,9 @@ static boolean SnapField(struct PlayerInfo *player, int dx, int dy) } if (player->MovPos != 0) /* prevent graphic bugs in versions < 2.2.0 */ - DrawLevelField(player->last_jx, player->last_jy); + TEST_DrawLevelField(player->last_jx, player->last_jy); - DrawLevelField(x, y); + TEST_DrawLevelField(x, y); return TRUE; }