InitPlayfieldScanModeVars();
}
+static int get_move_delay_from_stepsize(int move_stepsize)
+{
+ move_stepsize =
+ MIN(MAX(MOVE_STEPSIZE_MIN, move_stepsize), MOVE_STEPSIZE_MAX);
+
+ /* make sure that stepsize value is always a power of 2 */
+ move_stepsize = (1 << log_2(move_stepsize));
+
+ return TILEX / move_stepsize;
+}
+
+static void SetPlayerMoveSpeed(struct PlayerInfo *player, int move_stepsize,
+ boolean init_game)
+{
+ int move_delay = get_move_delay_from_stepsize(move_stepsize);
+ boolean cannot_move = (move_stepsize == STEPSIZE_NOT_MOVING ? TRUE : FALSE);
+
+ /* do no immediately change move delay -- the player might just be moving */
+ player->move_delay_value_next = move_delay;
+
+ /* information if player can move must be set separately */
+ player->cannot_move = cannot_move;
+
+ if (init_game)
+ {
+ player->move_delay = game.initial_move_delay;
+ player->move_delay_value = game.initial_move_delay_value;
+
+ player->move_delay_value_next = -1;
+
+ player->move_delay_reset_counter = 0;
+ }
+}
+
void GetPlayerConfig()
{
if (!audio.sound_available)
/* ---------- initialize player's initial move delay --------------------- */
+#if 1
+ /* dynamically adjust player properties according to level information */
+ game.initial_move_delay_value =
+ get_move_delay_from_stepsize(level.initial_player_stepsize);
+#else
/* dynamically adjust player properties according to level information */
game.initial_move_delay_value =
(level.double_speed ? MOVE_DELAY_HIGH_SPEED : MOVE_DELAY_NORMAL_SPEED);
+#endif
/* dynamically adjust player properties according to game engine version */
game.initial_move_delay = (game.engine_version <= VERSION_IDENT(2,0,1,0) ?
player->is_bored = FALSE;
player->is_sleeping = FALSE;
- player->cannot_move = FALSE;
-
player->frame_counter_bored = -1;
player->frame_counter_sleeping = -1;
player->show_envelope = 0;
+#if 1
+ SetPlayerMoveSpeed(player, level.initial_player_stepsize, TRUE);
+#else
player->move_delay = game.initial_move_delay;
player->move_delay_value = game.initial_move_delay_value;
player->move_delay_reset_counter = 0;
+ player->cannot_move = FALSE;
+#endif
+
player->push_delay = -1; /* initialized when pushing starts */
player->push_delay_value = game.initial_push_delay_value;
static void InitMagicBallDelay(int x, int y)
{
- ChangeDelay[x][y] = level.ball_time * FRAMES_PER_SECOND;
-
- if (ChangeDelay[x][y] == 0)
- ChangeDelay[x][y] = 1;
+#if 1
+ ChangeDelay[x][y] = (level.ball_time + 1) * 8 + 1;
+#else
+ ChangeDelay[x][y] = level.ball_time * FRAMES_PER_SECOND + 1;
+#endif
}
static void ActivateMagicBall(int bx, int by)
MV_NONE);
int action_arg_number_min =
- (action_type == CA_SET_PLAYER_SPEED ? MOVE_STEPSIZE_MIN :
+ (action_type == CA_SET_PLAYER_SPEED ? STEPSIZE_NOT_MOVING :
CA_ARG_MIN);
int action_arg_number_max =
- (action_type == CA_SET_PLAYER_SPEED ? MOVE_STEPSIZE_MAX :
+ (action_type == CA_SET_PLAYER_SPEED ? STEPSIZE_EVEN_FASTER :
action_type == CA_SET_LEVEL_GEMS ? 999 :
action_type == CA_SET_LEVEL_TIME ? 9999 :
action_type == CA_SET_LEVEL_SCORE ? 99999 :
CA_ARG_MAX);
int action_arg_number_reset =
- (action_type == CA_SET_PLAYER_SPEED ? TILEX/game.initial_move_delay_value :
+ (action_type == CA_SET_PLAYER_SPEED ? level.initial_player_stepsize :
action_type == CA_SET_LEVEL_GEMS ? level.gems_needed :
action_type == CA_SET_LEVEL_TIME ? level.time :
action_type == CA_SET_LEVEL_SCORE ? 0 :
{
int move_stepsize = TILEX / stored_player[i].move_delay_value;
- if (action_arg == CA_ARG_SPEED_SLOWER ||
- action_arg == CA_ARG_SPEED_FASTER)
+ if (action_arg == CA_ARG_SPEED_FASTER &&
+ stored_player[i].cannot_move)
+ {
+ action_arg_number = STEPSIZE_VERY_SLOW;
+ }
+ else if (action_arg == CA_ARG_SPEED_SLOWER ||
+ action_arg == CA_ARG_SPEED_FASTER)
{
action_arg_number = 2;
action_mode = (action_arg == CA_ARG_SPEED_SLOWER ? CA_MODE_DIVIDE :
action_arg_number_min,
action_arg_number_max);
+#if 1
+ SetPlayerMoveSpeed(&stored_player[i], move_stepsize, FALSE);
+#else
/* make sure that value is power of 2 */
move_stepsize = (1 << log_2(move_stepsize));
stored_player[i].cannot_move =
(action_arg == CA_ARG_SPEED_NOT_MOVING ? TRUE : FALSE);
+#endif
}
}
}
}
-static void CreateField(int x, int y, int target_element)
+static void CreateFieldExt(int x, int y, int element, boolean is_change)
{
int previous_move_direction = MovDir[x][y];
#if USE_NEW_CUSTOM_VALUE
int last_ce_value = CustomValue[x][y];
#endif
- boolean add_player = (ELEM_IS_PLAYER(target_element) &&
+ boolean add_player = (ELEM_IS_PLAYER(element) &&
IS_WALKABLE(Feld[x][y]));
/* 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_EXPLOSION_PROTECTED(x, y) &&
- IS_ACCESSIBLE(Feld[x][y]) && !IS_ACCESSIBLE(target_element))
+ IS_ACCESSIBLE(Feld[x][y]) && !IS_ACCESSIBLE(element))
{
Bang(x, y);
else
RemoveField(x, y);
- Feld[x][y] = target_element;
+ Feld[x][y] = element;
ResetGfxAnimation(x, y);
ResetRandomAnimationValue(x, y);
}
/* "ChangeCount" not set yet to allow "entered by player" change one time */
- if (ELEM_IS_PLAYER(target_element))
- RelocatePlayer(x, y, target_element);
+ if (ELEM_IS_PLAYER(element))
+ RelocatePlayer(x, y, element);
-#if 0
- ChangeCount[x][y]++; /* count number of changes in the same frame */
-#endif
+ if (is_change)
+ ChangeCount[x][y]++; /* count number of changes in the same frame */
TestIfBadThingTouchesPlayer(x, y);
TestIfPlayerTouchesCustomElement(x, y);
TestIfElementTouchesCustomElement(x, y);
}
-static void CreateElementFromChange(int x, int y, int element)
+static void CreateField(int x, int y, int element)
{
- CreateField(x, y, element);
+ CreateFieldExt(x, y, element, FALSE);
+}
- ChangeCount[x][y]++; /* count number of changes in the same frame */
+static void CreateElementFromChange(int x, int y, int element)
+{
+ CreateFieldExt(x, y, element, TRUE);
}
static boolean ChangeElement(int x, int y, int element, int page)
int new_jx = jx + dx, new_jy = jy + dy;
int element;
int can_move;
+ boolean player_can_move = !player->cannot_move;
if (!player->active || (!dx && !dy))
return MF_NO_ACTION;
if (!IN_LEV_FIELD(new_jx, new_jy))
return MF_NO_ACTION;
- if (player->cannot_move)
+ if (!player_can_move)
{
#if 1
if (player->MovPos == 0)
SnapField(player, 0, 0);
#endif
+#if 0
return MF_NO_ACTION;
+#endif
}
if (!options.network && !AllPlayersInSight(player, new_jx, new_jy))
element = MovingOrBlocked2ElementIfNotLeaving(new_jx, new_jy);
- if (DONT_RUN_INTO(element))
+ if (player_can_move && DONT_RUN_INTO(element))
{
if (element == EL_ACID && dx == 0 && dy == 1)
{
{
boolean is_player = (IS_PLAYER(oldx, oldy) || mode != DF_DIG);
boolean player_was_pushing = player->is_pushing;
+ boolean player_can_enter = (!player->cannot_move || mode == DF_SNAP);
int jx = oldx, jy = oldy;
int dx = x - jx, dy = y - jy;
int nextx = x + dx, nexty = y + dy;
!canMoveToValidFieldWithGravity(jx, jy, move_direction))
return MF_NO_ACTION; /* player cannot walk here due to gravity */
- if (IS_WALKABLE(element) && ACCESS_FROM(element, opposite_direction))
+ if (player_can_enter &&
+ IS_WALKABLE(element) && ACCESS_FROM(element, opposite_direction))
{
int sound_element = SND_ELEMENT(element);
int sound_action = ACTION_WALKING;
else
PlayLevelSoundElementAction(x, y, player->artwork_element, sound_action);
}
- else if (IS_PASSABLE(element) && canPassField(x, y, move_direction))
+ else if (player_can_enter &&
+ IS_PASSABLE(element) && canPassField(x, y, move_direction))
{
if (!ACCESS_FROM(element, opposite_direction))
return MF_NO_ACTION; /* field not accessible from this direction */
PlayLevelSoundAction(x, y, ACTION_PASSING);
}
- else if (IS_DIGGABLE(element))
+ else if (player_can_enter && IS_DIGGABLE(element))
{
RemoveField(x, y);
player->index_bit, dig_side);
}
}
- else if (IS_COLLECTIBLE(element))
+ else if (player_can_enter && IS_COLLECTIBLE(element))
{
RemoveField(x, y);
player->index_bit, dig_side);
}
}
- else if (IS_PUSHABLE(element))
+ else if (player_can_enter && IS_PUSHABLE(element))
{
if (mode == DF_SNAP && element != EL_BD_ROCK)
return MF_NO_ACTION;