(condition) || \
(DONT_COLLIDE_WITH(e) && \
IS_PLAYER(x, y) && \
- !PLAYER_PROTECTED(x, y))))
+ !PLAYER_ENEMY_PROTECTED(x, y))))
#else
#define ELEMENT_CAN_ENTER_FIELD_GENERIC(e, x, y, condition) \
(IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || \
static void InitBeltMovement(void);
static void CloseAllOpenTimegates(void);
static void CheckGravityMovement(struct PlayerInfo *);
-static void KillHeroUnlessProtected(int, int);
+static void KillHeroUnlessEnemyProtected(int, int);
+static void KillHeroUnlessExplosionProtected(int, int);
static void TestIfPlayerTouchesCustomElement(int, int);
static void TestIfElementTouchesCustomElement(int, int);
player->present = TRUE;
+ player->block_last_field = (element == EL_SP_MURPHY ?
+ level.sp_block_last_field :
+ level.block_last_field);
+
if (!options.network || player->connected)
{
player->active = TRUE;
group_element - EL_GROUP_START + 1);
/* replace element which caused too deep recursion by question mark */
- group->element_resolved[group->num_elements_resolved++] = EL_CHAR_QUESTION;
+ group->element_resolved[group->num_elements_resolved++] = EL_UNKNOWN;
return;
}
element_info[e].push_delay_random = push_delay_list[i].push_delay_random;
}
+ /* set push delay value for Supaplex elements for newer engine versions */
+ if (game.engine_version >= VERSION_IDENT(3,0,9,0))
+ {
+ for (i = 0; i < MAX_NUM_ELEMENTS; i++)
+ {
+ if (IS_SP_ELEMENT(i))
+ {
+ element_info[i].push_delay_fixed = 6;
+ element_info[i].push_delay_random = 0;
+ }
+ }
+ }
+
/* ---------- initialize move stepsize ----------------------------------- */
/* initialize move stepsize values to default */
player->use_murphy_graphic = FALSE;
+ player->block_last_field = FALSE;
+
player->actual_frame_counter = 0;
player->step_counter = 0;
int move_direction_initial = ei->move_direction_initial;
int move_pattern = ei->move_pattern;
- if (move_direction_initial == MV_PREVIOUS)
+ if (move_direction_initial == MV_START_PREVIOUS)
{
if (MovDir[x][y] != MV_NO_MOVING)
return;
- move_direction_initial = MV_AUTOMATIC;
+ move_direction_initial = MV_START_AUTOMATIC;
}
- if (move_direction_initial == MV_RANDOM)
+ if (move_direction_initial == MV_START_RANDOM)
MovDir[x][y] = 1 << RND(4);
else if (move_direction_initial & MV_ANY_DIRECTION)
MovDir[x][y] = move_direction_initial;
void RelocatePlayer(int x, int y, int element)
{
struct PlayerInfo *player = &stored_player[element - EL_PLAYER_1];
+ boolean ffwd_delay = (tape.playing && tape.fast_forward);
+ boolean no_delay = (tape.index_search);
+ int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
+ int wait_delay_value = (no_delay ? 0 : frame_delay_value);
if (player->GameOver) /* do not reanimate dead player */
return;
DrawPlayer(player);
BackToFront();
- Delay(GAME_FRAME_DELAY);
+ Delay(wait_delay_value);
}
DrawPlayer(player); /* needed here only to cleanup last field */
/* scroll in two steps of half tile size to make things smoother */
BlitBitmap(drawto_field, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
FlushDisplay();
- Delay(GAME_FRAME_DELAY);
+ Delay(wait_delay_value);
/* scroll second step to align at full tile size */
BackToFront();
- Delay(GAME_FRAME_DELAY);
+ Delay(wait_delay_value);
}
}
}
RemoveField(x, y);
#endif
- if (IS_PLAYER(ex, ey) && !PLAYER_PROTECTED(ex, ey))
+ if (IS_PLAYER(ex, ey) && !PLAYER_EXPLOSION_PROTECTED(ex, ey))
{
switch(StorePlayer[ex][ey])
{
int element = Store2[x][y];
if (IS_PLAYER(x, y))
- KillHeroUnlessProtected(x, y);
+ KillHeroUnlessExplosionProtected(x, y);
else if (CAN_EXPLODE_BY_FIRE(element))
{
Feld[x][y] = Store2[x][y];
#endif
#if 1
- if (IS_PLAYER(x, y) && !PLAYER_PROTECTED(x, y))
+ if (IS_PLAYER(x, y) && !PLAYER_EXPLOSION_PROTECTED(x, y))
#else
if (IS_PLAYER(x, y))
#endif
if (impact && element == EL_AMOEBA_DROP)
{
if (object_hit && IS_PLAYER(x, y + 1))
- KillHeroUnlessProtected(x, y + 1);
+ KillHeroUnlessEnemyProtected(x, y + 1);
else if (object_hit && smashed == EL_PENGUIN)
Bang(x, y + 1);
else
{
if (CAN_SMASH_PLAYER(element))
{
- KillHeroUnlessProtected(x, y + 1);
+ KillHeroUnlessEnemyProtected(x, y + 1);
return;
}
}
if (DONT_COLLIDE_WITH(element) &&
IN_LEV_FIELD(newx, newy) && IS_PLAYER(newx, newy) &&
- !PLAYER_PROTECTED(newx, newy))
+ !PLAYER_ENEMY_PROTECTED(newx, newy))
{
#if 1
TestIfBadThingRunsIntoHero(x, y, MovDir[x][y]);
#if 0
if (IN_LEV_FIELD(nextx, nexty))
{
- static int opposite_directions[] =
- {
- MV_RIGHT,
- MV_LEFT,
- MV_DOWN,
- MV_UP
- };
- int move_dir_bit = MV_DIR_BIT(direction);
- int opposite_direction = opposite_directions[move_dir_bit];
+ int opposite_direction = MV_DIR_OPPOSITE(direction);
int hitting_side = direction;
int touched_side = opposite_direction;
int touched_element = MovingOrBlocked2Element(nextx, nexty);
/* check if element under player changes from accessible to unaccessible
(needed for special case of dropping element which then changes) */
- if (IS_PLAYER(x, y) && !PLAYER_PROTECTED(x, y) &&
+ if (IS_PLAYER(x, y) && !PLAYER_EXPLOSION_PROTECTED(x, y) &&
IS_ACCESSIBLE(Feld[x][y]) && !IS_ACCESSIBLE(target_element))
{
Bang(x, y);
ResetGfxAnimation(x, y);
ResetRandomAnimationValue(x, y);
- if (element_info[Feld[x][y]].move_direction_initial == MV_PREVIOUS)
+ if (element_info[Feld[x][y]].move_direction_initial == MV_START_PREVIOUS)
MovDir[x][y] = previous_move_direction;
InitField(x, y, FALSE);
#if 0
DrawPlayer(player);
#endif
+
return;
}
else if (!FrameReached(&player->actual_frame_counter, 1))
player->MovPos += (player->MovPos > 0 ? -1 : 1) * move_stepsize;
player->GfxPos = move_stepsize * (player->MovPos / move_stepsize);
- if (Feld[last_jx][last_jy] == EL_PLAYER_IS_LEAVING)
+ if (!player->block_last_field &&
+ Feld[last_jx][last_jy] == EL_PLAYER_IS_LEAVING)
Feld[last_jx][last_jy] = EL_EMPTY;
/* before DrawPlayer() to draw correct player graphic for this case */
}
#endif
+ if (player->block_last_field &&
+ Feld[last_jx][last_jy] == EL_PLAYER_IS_LEAVING)
+ Feld[last_jx][last_jy] = EL_EMPTY;
+
player->last_jx = jx;
player->last_jy = jy;
if (IN_LEV_FIELD(hitx, hity))
{
- static int opposite_directions[] =
- {
- MV_RIGHT,
- MV_LEFT,
- MV_DOWN,
- MV_UP
- };
- int move_dir_bit = MV_DIR_BIT(direction);
- int opposite_direction = opposite_directions[move_dir_bit];
+ int opposite_direction = MV_DIR_OPPOSITE(direction);
int hitting_side = direction;
int touched_side = opposite_direction;
int touched_element = MovingOrBlocked2Element(hitx, hity);
if (player->shield_deadly_time_left > 0)
Bang(kill_x, kill_y);
- else if (!PLAYER_PROTECTED(good_x, good_y))
+ else if (!PLAYER_ENEMY_PROTECTED(good_x, good_y))
KillHero(player);
}
else
if (player->shield_deadly_time_left > 0)
Bang(bad_x, bad_y);
- else if (!PLAYER_PROTECTED(kill_x, kill_y))
+ else if (!PLAYER_ENEMY_PROTECTED(kill_x, kill_y))
KillHero(player);
}
else
BuryHero(player);
}
-static void KillHeroUnlessProtected(int x, int y)
+static void KillHeroUnlessEnemyProtected(int x, int y)
+{
+ if (!PLAYER_ENEMY_PROTECTED(x, y))
+ KillHero(PLAYERINFO(x, y));
+}
+
+static void KillHeroUnlessExplosionProtected(int x, int y)
{
- if (!PLAYER_PROTECTED(x, y))
+ if (!PLAYER_EXPLOSION_PROTECTED(x, y))
KillHero(PLAYERINFO(x, y));
}
PlayLevelSoundAction(jx, jy, ACTION_DROPPING);
+#if 1
+ /* needed if previous element just changed to "empty" in the last frame */
+ Changed[jx][jy] = 0; /* allow another change */
+#endif
+
CheckTriggeredElementChange(jx, jy, new_element, CE_OTHER_GETS_DROPPED);
CheckElementChange(jx, jy, new_element, CE_DROPPED_BY_PLAYER);
int move_stepsize = element_info[new_element].move_stepsize;
int direction, dx, dy, nextx, nexty;
- if (element_info[new_element].move_direction_initial == MV_AUTOMATIC)
+ if (element_info[new_element].move_direction_initial == MV_START_AUTOMATIC)
MovDir[jx][jy] = player->MovDir;
direction = MovDir[jx][jy];
}
else
{
- Changed[jx][jy] = 0; /* allow another change */
+ Changed[jx][jy] = 0; /* allow another change */
#if 1
TestIfElementHitsCustomElement(jx, jy, direction);