#define USE_NEW_ALL_SLIPPERY (USE_NEW_STUFF * 1)
#define USE_NEW_PLAYER_SPEED (USE_NEW_STUFF * 1)
#define USE_NEW_DELAYED_ACTION (USE_NEW_STUFF * 1)
+#define USE_NEW_SNAP_DELAY (USE_NEW_STUFF * 1)
/* for DigField() */
#define DF_NO_PUSH 0
((e) == EL_TRIGGER_ELEMENT ? (ch)->actual_trigger_element : \
(e) == EL_TRIGGER_PLAYER ? (ch)->actual_trigger_player : (e))
-#define GET_VALID_PLAYER_ELEMENT(e) \
- ((e) >= EL_PLAYER_1 && (e) <= EL_PLAYER_4 ? (e) : EL_PLAYER_1)
-
#define CAN_GROW_INTO(e) \
((e) == EL_SAND || (IS_DIGGABLE(e) && level.grow_into_diggable))
/* forward declaration for internal use */
+static void SetPlayerWaiting(struct PlayerInfo *, boolean);
static void AdvanceFrameAndPlayerCounters(int);
static boolean MovePlayerOneStep(struct PlayerInfo *, int, int, int, int);
}
else
{
- stored_player[0].use_murphy_graphic = TRUE;
+ stored_player[0].use_murphy = TRUE;
}
Feld[x][y] = EL_PLAYER_1;
break;
default:
+#if 1
+ if (IS_CUSTOM_ELEMENT(element))
+ {
+ if (CAN_MOVE(element))
+ InitMovDir(x, y);
+
+#if USE_NEW_CUSTOM_VALUE
+ if (!element_info[element].use_last_ce_value || init_game)
+ CustomValue[x][y] = GET_NEW_CUSTOM_VALUE(Feld[x][y]);
+#endif
+ }
+#else
if (IS_CUSTOM_ELEMENT(element) && CAN_MOVE(element))
InitMovDir(x, y);
+#endif
else if (IS_GROUP_ELEMENT(element))
{
struct ElementGroupInfo *group = element_info[element].group;
break;
}
+#if 0
+
#if USE_NEW_CUSTOM_VALUE
#if 1
CustomValue[x][y] = element_info[Feld[x][y]].custom_value_initial;
#endif
+#endif
+
#endif
}
access_direction_list[i].direction;
}
+int get_num_special_action(int element, int action_first, int action_last)
+{
+ int num_special_action = 0;
+ int i, j;
+
+ for (i = action_first; i <= action_last; i++)
+ {
+ boolean found = FALSE;
+
+ for (j = 0; j < NUM_DIRECTIONS; j++)
+ if (el_act_dir2img(element, i, j) !=
+ el_act_dir2img(element, ACTION_DEFAULT, j))
+ found = TRUE;
+
+ if (found)
+ num_special_action++;
+ else
+ break;
+ }
+
+ return num_special_action;
+}
/*
=============================================================================
boolean emulate_bd = TRUE; /* unless non-BOULDERDASH elements found */
boolean emulate_sb = TRUE; /* unless non-SOKOBAN elements found */
boolean emulate_sp = TRUE; /* unless non-SUPAPLEX elements found */
- int i, j, k, x, y;
+ int i, j, x, y;
InitGameEngine();
player->Frame = 0;
player->StepFrame = 0;
- player->use_murphy_graphic = FALSE;
+ player->use_murphy = FALSE;
+ player->artwork_element = player->element_nr;
player->block_last_field = FALSE; /* initialized in InitPlayerField() */
player->block_delay_adjustment = 0; /* initialized in InitPlayerField() */
player->is_bored = FALSE;
player->is_sleeping = FALSE;
+ player->cannot_move = FALSE;
+
player->frame_counter_bored = -1;
player->frame_counter_sleeping = -1;
player->special_action_bored = ACTION_DEFAULT;
player->special_action_sleeping = ACTION_DEFAULT;
- player->num_special_action_bored = 0;
- player->num_special_action_sleeping = 0;
-
- /* determine number of special actions for bored and sleeping animation */
- for (j = ACTION_BORING_1; j <= ACTION_BORING_LAST; j++)
- {
- boolean found = FALSE;
-
- for (k = 0; k < NUM_DIRECTIONS; k++)
- if (el_act_dir2img(player->element_nr, j, k) !=
- el_act_dir2img(player->element_nr, ACTION_DEFAULT, k))
- found = TRUE;
-
- if (found)
- player->num_special_action_bored++;
- else
- break;
- }
- for (j = ACTION_SLEEPING_1; j <= ACTION_SLEEPING_LAST; j++)
- {
- boolean found = FALSE;
-
- for (k = 0; k < NUM_DIRECTIONS; k++)
- if (el_act_dir2img(player->element_nr, j, k) !=
- el_act_dir2img(player->element_nr, ACTION_DEFAULT, k))
- found = TRUE;
-
- if (found)
- player->num_special_action_sleeping++;
- else
- break;
- }
+ /* set number of special actions for bored and sleeping animation */
+ player->num_special_action_bored =
+ get_num_special_action(player->artwork_element,
+ ACTION_BORING_1, ACTION_BORING_LAST);
+ player->num_special_action_sleeping =
+ get_num_special_action(player->artwork_element,
+ ACTION_SLEEPING_1, ACTION_SLEEPING_LAST);
player->switch_x = -1;
player->switch_y = -1;
game.gravity = level.initial_gravity;
game.explosions_delayed = TRUE;
+ game.lenses_time_left = 0;
+ game.magnify_time_left = 0;
+
game.envelope_active = FALSE;
for (i = 0; i < NUM_BELTS; i++)
player->element_nr = some_player->element_nr;
#endif
+ player->artwork_element = some_player->artwork_element;
+
player->block_last_field = some_player->block_last_field;
player->block_delay_adjustment = some_player->block_delay_adjustment;
int start_x = 0, start_y = 0;
int found_rating = 0;
int found_element = EL_UNDEFINED;
+ int player_nr = local_player->index_nr;
for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
{
int xx, yy;
boolean is_player;
+ if (level.use_start_element[player_nr] &&
+ level.start_element[player_nr] == element &&
+ found_rating < 4)
+ {
+ start_x = x;
+ start_y = y;
+
+ found_rating = 4;
+ found_element = element;
+ }
+
if (!IS_CUSTOM_ELEMENT(element))
continue;
{
for (i = 0; i < element_info[element].num_change_pages; i++)
{
+ /* check for player created from custom element as single target */
content = element_info[element].change_page[i].target_element;
is_player = ELEM_IS_PLAYER(content);
for (yy = 0; yy < 3; yy++) for (xx = 0; xx < 3; xx++)
{
+ /* check for player created from custom element as explosion content */
content = element_info[element].content.e[xx][yy];
is_player = ELEM_IS_PLAYER(content);
for (i = 0; i < element_info[element].num_change_pages; i++)
{
+ /* check for player created from custom element as extended target */
content =
element_info[element].change_page[i].target_content.e[xx][yy];
{
if (!tape.playing && !setup.sound_loops)
PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, SOUND_MIDDLE);
- if (TimeLeft > 0 && !(TimeLeft % 10))
- RaiseScore(level.score[SC_TIME_BONUS]);
- if (TimeLeft > 100 && !(TimeLeft % 10))
+
+ if (TimeLeft > 100 && TimeLeft % 10 == 0)
+ {
TimeLeft -= 10;
+ RaiseScore(level.score[SC_TIME_BONUS] * 10);
+ }
else
+ {
TimeLeft--;
+ RaiseScore(level.score[SC_TIME_BONUS]);
+ }
DrawGameValue_Time(TimeLeft);
{
if (!tape.playing && !setup.sound_loops)
PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, SOUND_MIDDLE);
- if (TimePlayed < 999 && !(TimePlayed % 10))
- RaiseScore(level.score[SC_TIME_BONUS]);
- if (TimePlayed < 900 && !(TimePlayed % 10))
+
+ if (TimePlayed < 900 && TimePlayed % 10 == 0)
+ {
TimePlayed += 10;
+ RaiseScore(level.score[SC_TIME_BONUS] * 10);
+ }
else
+ {
TimePlayed++;
+ RaiseScore(level.score[SC_TIME_BONUS]);
+ }
DrawGameValue_Time(TimePlayed);
void RelocatePlayer(int jx, int jy, int el_player_raw)
{
- int el_player = GET_VALID_PLAYER_ELEMENT(el_player_raw);
- struct PlayerInfo *player = &stored_player[el_player - EL_PLAYER_1];
+ int el_player = GET_PLAYER_ELEMENT(el_player_raw);
+ int player_nr = GET_PLAYER_NR(el_player);
+ struct PlayerInfo *player = &stored_player[player_nr];
boolean ffwd_delay = (tape.playing && tape.fast_forward);
boolean no_delay = (tape.warp_forward);
int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
break;
}
- if (PLAYERINFO(ex, ey)->use_murphy_graphic)
+ if (PLAYERINFO(ex, ey)->use_murphy)
Store[x][y] = EL_EMPTY;
}
else if (center_element == EL_MOLE)
{
struct PlayerInfo *player = PLAYERINFO(x, y);
- element = Feld[x][y] = (player->use_murphy_graphic ? EL_SP_MURPHY :
+ element = Feld[x][y] = (player->use_murphy ? EL_SP_MURPHY :
player->element_nr);
}
{
int x, y;
- for (y = 0; y < lev_fieldy; y++)
+ for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
{
- for (x = 0; x < lev_fieldx; x++)
+ int element = Feld[x][y];
+
+ if (element == EL_LIGHT_SWITCH &&
+ game.light_time_left > 0)
{
- int element = Feld[x][y];
+ Feld[x][y] = EL_LIGHT_SWITCH_ACTIVE;
+ DrawLevelField(x, y);
+ }
+ else if (element == EL_LIGHT_SWITCH_ACTIVE &&
+ game.light_time_left == 0)
+ {
+ Feld[x][y] = EL_LIGHT_SWITCH;
+ DrawLevelField(x, y);
+ }
+ else if (element == EL_EMC_DRIPPER &&
+ game.light_time_left > 0)
+ {
+ Feld[x][y] = EL_EMC_DRIPPER_ACTIVE;
+ DrawLevelField(x, y);
+ }
+ else if (element == EL_EMC_DRIPPER_ACTIVE &&
+ game.light_time_left == 0)
+ {
+ Feld[x][y] = EL_EMC_DRIPPER;
+ DrawLevelField(x, y);
+ }
+ else if (element == EL_INVISIBLE_STEELWALL ||
+ element == EL_INVISIBLE_WALL ||
+ element == EL_INVISIBLE_SAND)
+ {
+ if (game.light_time_left > 0)
+ Feld[x][y] = getInvisibleActiveFromInvisibleElement(element);
- if (element == EL_LIGHT_SWITCH &&
- game.light_time_left > 0)
- {
- Feld[x][y] = EL_LIGHT_SWITCH_ACTIVE;
- DrawLevelField(x, y);
- }
- else if (element == EL_LIGHT_SWITCH_ACTIVE &&
- game.light_time_left == 0)
- {
- Feld[x][y] = EL_LIGHT_SWITCH;
- DrawLevelField(x, y);
- }
- else if (element == EL_INVISIBLE_STEELWALL ||
- element == EL_INVISIBLE_WALL ||
- element == EL_INVISIBLE_SAND)
- {
- if (game.light_time_left > 0)
- Feld[x][y] = getInvisibleActiveFromInvisibleElement(element);
+ DrawLevelField(x, y);
- DrawLevelField(x, y);
+ /* uncrumble neighbour fields, if needed */
+ if (element == EL_INVISIBLE_SAND)
+ DrawLevelFieldCrumbledSandNeighbours(x, y);
+ }
+ else if (element == EL_INVISIBLE_STEELWALL_ACTIVE ||
+ element == EL_INVISIBLE_WALL_ACTIVE ||
+ element == EL_INVISIBLE_SAND_ACTIVE)
+ {
+ if (game.light_time_left == 0)
+ Feld[x][y] = getInvisibleFromInvisibleActiveElement(element);
- /* uncrumble neighbour fields, if needed */
- if (element == EL_INVISIBLE_SAND)
- DrawLevelFieldCrumbledSandNeighbours(x, y);
- }
- else if (element == EL_INVISIBLE_STEELWALL_ACTIVE ||
- element == EL_INVISIBLE_WALL_ACTIVE ||
- element == EL_INVISIBLE_SAND_ACTIVE)
- {
- if (game.light_time_left == 0)
- Feld[x][y] = getInvisibleFromInvisibleActiveElement(element);
+ DrawLevelField(x, y);
- DrawLevelField(x, y);
+ /* re-crumble neighbour fields, if needed */
+ if (element == EL_INVISIBLE_SAND)
+ DrawLevelFieldCrumbledSandNeighbours(x, y);
+ }
+ }
+}
- /* re-crumble neighbour fields, if needed */
- if (element == EL_INVISIBLE_SAND)
- DrawLevelFieldCrumbledSandNeighbours(x, y);
- }
+static void RedrawAllInvisibleElementsForLenses()
+{
+ int x, y;
+
+ for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
+ {
+ int element = Feld[x][y];
+
+ if (element == EL_EMC_DRIPPER &&
+ game.lenses_time_left > 0)
+ {
+ Feld[x][y] = EL_EMC_DRIPPER_ACTIVE;
+ DrawLevelField(x, y);
+ }
+ else if (element == EL_EMC_DRIPPER_ACTIVE &&
+ game.lenses_time_left == 0)
+ {
+ Feld[x][y] = EL_EMC_DRIPPER;
+ DrawLevelField(x, y);
+ }
+ else if (element == EL_INVISIBLE_STEELWALL ||
+ element == EL_INVISIBLE_WALL ||
+ element == EL_INVISIBLE_SAND)
+ {
+ if (game.lenses_time_left > 0)
+ Feld[x][y] = getInvisibleActiveFromInvisibleElement(element);
+
+ DrawLevelField(x, y);
+
+ /* uncrumble neighbour fields, if needed */
+ if (element == EL_INVISIBLE_SAND)
+ DrawLevelFieldCrumbledSandNeighbours(x, y);
+ }
+ else if (element == EL_INVISIBLE_STEELWALL_ACTIVE ||
+ element == EL_INVISIBLE_WALL_ACTIVE ||
+ element == EL_INVISIBLE_SAND_ACTIVE)
+ {
+ if (game.lenses_time_left == 0)
+ Feld[x][y] = getInvisibleFromInvisibleActiveElement(element);
+
+ DrawLevelField(x, y);
+
+ /* re-crumble neighbour fields, if needed */
+ if (element == EL_INVISIBLE_SAND)
+ DrawLevelFieldCrumbledSandNeighbours(x, y);
+ }
+ }
+}
+
+static void RedrawAllInvisibleElementsForMagnifier()
+{
+ int x, y;
+
+ for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
+ {
+ int element = Feld[x][y];
+
+ if (element == EL_EMC_FAKE_GRASS &&
+ game.magnify_time_left > 0)
+ {
+ Feld[x][y] = EL_EMC_FAKE_GRASS_ACTIVE;
+ 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);
+ }
+ else if (IS_GATE_GRAY(element) &&
+ game.magnify_time_left > 0)
+ {
+ Feld[x][y] = (IS_RND_GATE_GRAY(element) ?
+ element - EL_GATE_1_GRAY + EL_GATE_1_GRAY_ACTIVE :
+ IS_EM_GATE_GRAY(element) ?
+ 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 :
+ element);
+ DrawLevelField(x, y);
+ }
+ else if (IS_GATE_GRAY_ACTIVE(element) &&
+ game.magnify_time_left == 0)
+ {
+ Feld[x][y] = (IS_RND_GATE_GRAY_ACTIVE(element) ?
+ element - EL_GATE_1_GRAY_ACTIVE + EL_GATE_1_GRAY :
+ IS_EM_GATE_GRAY_ACTIVE(element) ?
+ 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 :
+ element);
+ DrawLevelField(x, y);
}
}
}
if (pushed_by_player && !game.use_change_when_pushing_bug)
{
- int dig_side = MV_DIR_OPPOSITE(direction);
+ int push_side = MV_DIR_OPPOSITE(direction);
struct PlayerInfo *player = PLAYERINFO(x, y);
CheckElementChangeByPlayer(newx, newy, element, CE_PUSHED_BY_PLAYER,
- player->index_bit, dig_side);
+ player->index_bit, push_side);
CheckTriggeredElementChangeByPlayer(newx,newy, element, CE_PLAYER_PUSHES_X,
- player->index_bit, dig_side);
+ player->index_bit, push_side);
}
+ CheckTriggeredElementChangeBySide(x, y, element, CE_MOVE_OF_X, direction);
+
TestIfElementTouchesCustomElement(x, y); /* empty or new element */
TestIfElementHitsCustomElement(newx, newy, direction);
if (!change->has_action)
return;
- /* ---------- determine action paramater values ---------- */
+ /* ---------- determine action paramater values -------------------------- */
+
+ int level_time_value =
+ (level.time > 0 ? TimeLeft :
+ TimePlayed);
int action_arg_element =
(action_arg == CA_ARG_PLAYER_TRIGGER ? change->actual_trigger_player :
action_arg == CA_ARG_ELEMENT_TARGET ? change->target_element :
EL_EMPTY);
+ int action_arg_direction =
+ (action_arg >= CA_ARG_DIRECTION_LEFT &&
+ action_arg <= CA_ARG_DIRECTION_DOWN ? action_arg - CA_ARG_DIRECTION :
+ action_arg == CA_ARG_DIRECTION_TRIGGER ?
+ change->actual_trigger_side :
+ action_arg == CA_ARG_DIRECTION_TRIGGER_BACK ?
+ MV_DIR_OPPOSITE(change->actual_trigger_side) :
+ MV_NONE);
+
int action_arg_number_min =
(action_type == CA_SET_PLAYER_SPEED ? MOVE_STEPSIZE_MIN :
CA_ARG_MIN);
int action_arg_number =
(action_arg <= CA_ARG_MAX ? action_arg :
- action_arg >= CA_ARG_SPEED_VERY_SLOW &&
+ action_arg >= CA_ARG_SPEED_NOT_MOVING &&
action_arg <= CA_ARG_SPEED_EVEN_FASTER ? (action_arg - CA_ARG_SPEED) :
action_arg == CA_ARG_SPEED_RESET ? action_arg_number_reset :
action_arg == CA_ARG_NUMBER_MIN ? action_arg_number_min :
action_arg == CA_ARG_NUMBER_CE_VALUE ? ei->custom_value_initial :
#endif
action_arg == CA_ARG_NUMBER_CE_DELAY ? GET_CHANGE_DELAY(change) :
+ action_arg == CA_ARG_NUMBER_LEVEL_TIME ? level_time_value :
+ action_arg == CA_ARG_NUMBER_LEVEL_GEMS ? local_player->gems_still_needed :
+ action_arg == CA_ARG_NUMBER_LEVEL_SCORE ? local_player->score :
action_arg == CA_ARG_ELEMENT_TARGET ? GET_NEW_CUSTOM_VALUE(change->target_element) :
action_arg == CA_ARG_ELEMENT_TRIGGER ? change->actual_trigger_ce_value :
-1);
action_mode, action_arg_number,
action_arg_number_min, action_arg_number_max);
- int action_arg_player_bits =
- (action_arg == CA_ARG_PLAYER_ANY ? PLAYER_BITS_ANY :
- 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 - CA_ARG_1)) :
- action_arg_element >= EL_PLAYER_1 &&
- action_arg_element <= EL_PLAYER_4 ?
- (1 << (action_arg_element - EL_PLAYER_1)) :
- PLAYER_BITS_ANY);
-
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 ---------- */
+ int action_arg_player_bits =
+ (action_arg >= CA_ARG_PLAYER_1 &&
+ action_arg <= CA_ARG_PLAYER_4 ? action_arg - CA_ARG_PLAYER :
+ action_arg == CA_ARG_PLAYER_TRIGGER ? trigger_player_bits :
+ PLAYER_BITS_ANY);
+
+ /* ---------- execute action -------------------------------------------- */
switch(action_type)
{
return;
}
- case CA_EXIT_PLAYER:
+ /* ---------- level actions ------------------------------------------- */
+
+ case CA_RESTART_LEVEL:
{
- for (i = 0; i < MAX_PLAYERS; i++)
- if (action_arg_player_bits & (1 << i))
- stored_player[i].LevelSolved = stored_player[i].GameOver = TRUE;
+ game.restart_level = TRUE;
break;
}
- case CA_KILL_PLAYER:
+ case CA_SHOW_ENVELOPE:
{
- for (i = 0; i < MAX_PLAYERS; i++)
- if (action_arg_player_bits & (1 << i))
- KillPlayer(&stored_player[i]);
+ int element = getSpecialActionElement(action_arg_element,
+ action_arg_number, EL_ENVELOPE_1);
+
+ if (IS_ENVELOPE(element))
+ local_player->show_envelope = element;
break;
}
- case CA_RESTART_LEVEL:
+ case CA_SET_LEVEL_TIME:
{
- game.restart_level = TRUE;
+ if (level.time > 0) /* only modify limited time value */
+ {
+ TimeLeft = action_arg_number_new;
+
+ DrawGameValue_Time(TimeLeft);
+
+ if (!TimeLeft && setup.time_limit)
+ for (i = 0; i < MAX_PLAYERS; i++)
+ KillPlayer(&stored_player[i]);
+ }
break;
}
- case CA_SHOW_ENVELOPE:
+ case CA_SET_LEVEL_SCORE:
{
- int element = getSpecialActionElement(action_arg_element,
- action_arg_number, EL_ENVELOPE_1);
+ local_player->score = action_arg_number_new;
- if (IS_ENVELOPE(element))
- local_player->show_envelope = element;
+ DrawGameValue_Score(local_player->score);
break;
}
- case CA_ADD_KEY:
+ case CA_SET_LEVEL_GEMS:
{
- int element = getSpecialActionElement(action_arg_element,
- action_arg_number, EL_KEY_1);
+ local_player->gems_still_needed = action_arg_number_new;
- 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_Emeralds(local_player->gems_still_needed);
- DrawGameValue_Keys(stored_player[i].key);
+ break;
+ }
- redraw_mask |= REDRAW_DOOR_1;
- }
- }
- }
+ case CA_SET_LEVEL_GRAVITY:
+ {
+ game.gravity = (action_arg == CA_ARG_GRAVITY_OFF ? FALSE :
+ action_arg == CA_ARG_GRAVITY_ON ? TRUE :
+ action_arg == CA_ARG_GRAVITY_TOGGLE ? !game.gravity :
+ game.gravity);
+ break;
+ }
+
+ case CA_SET_LEVEL_WIND:
+ {
+ game.wind_direction = action_arg_direction;
break;
}
- case CA_REMOVE_KEY:
+ /* ---------- player actions ------------------------------------------ */
+
+ case CA_MOVE_PLAYER:
{
+ /* automatically move to the next field in specified direction */
+ for (i = 0; i < MAX_PLAYERS; i++)
+ if (trigger_player_bits & (1 << i))
+ stored_player[i].programmed_action = action_arg_direction;
+
+ break;
+ }
+
+ 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))
+ KillPlayer(&stored_player[i]);
+
+ break;
+ }
+
+ case CA_SET_PLAYER_KEYS:
+ {
+ int key_state = (action_mode == CA_MODE_ADD ? TRUE : FALSE);
int element = getSpecialActionElement(action_arg_element,
action_arg_number, EL_KEY_1);
{
if (trigger_player_bits & (1 << i))
{
- stored_player[i].key[KEY_NR(element)] = FALSE;
+ stored_player[i].key[KEY_NR(element)] = key_state;
DrawGameValue_Keys(stored_player[i].key);
break;
}
-#if 1
case CA_SET_PLAYER_SPEED:
{
for (i = 0; i < MAX_PLAYERS; i++)
/* do no immediately change -- the player might just be moving */
stored_player[i].move_delay_value_next = TILEX / move_stepsize;
-#if 0
- printf("::: move_delay_value == %d [%d]\n",
- stored_player[i].move_delay_value_next, action_arg_number);
-#endif
+ stored_player[i].cannot_move =
+ (action_arg == CA_ARG_SPEED_NOT_MOVING ? TRUE : FALSE);
}
}
break;
}
-#else
- case CA_SET_PLAYER_SPEED:
+
+ case CA_SET_PLAYER_SHIELD:
{
for (i = 0; i < MAX_PLAYERS; i++)
{
if (trigger_player_bits & (1 << i))
{
- int move_stepsize = TILEX / stored_player[i].move_delay_value;
-
- if (action_mode == CA_MODE_ADD || action_mode == CA_MODE_SUBTRACT)
+ if (action_arg == CA_ARG_SHIELD_OFF)
{
- /* translate "+" and "-" to "*" and "/" with powers of two */
- action_arg_number = 1 << action_arg_number;
- action_mode = (action_mode == CA_MODE_ADD ? CA_MODE_MULTIPLY :
- CA_MODE_DIVIDE);
+ stored_player[i].shield_normal_time_left = 0;
+ stored_player[i].shield_deadly_time_left = 0;
+ }
+ else if (action_arg == CA_ARG_SHIELD_NORMAL)
+ {
+ stored_player[i].shield_normal_time_left = 999999;
+ }
+ else if (action_arg == CA_ARG_SHIELD_DEADLY)
+ {
+ stored_player[i].shield_normal_time_left = 999999;
+ stored_player[i].shield_deadly_time_left = 999999;
}
-
- move_stepsize =
- getModifiedActionNumber(move_stepsize,
- action_mode,
- action_arg_number,
- action_arg_number_min,
- action_arg_number_max);
-
- /* make sure that value is power of 2 */
- move_stepsize = (1 << log_2(move_stepsize));
-
- /* do no immediately change -- the player might just be moving */
- stored_player[i].move_delay_value_next = TILEX / move_stepsize;
-
-#if 0
- printf("::: move_delay_value == %d [%d]\n",
- stored_player[i].move_delay_value_next, action_arg_number);
-#endif
}
}
break;
}
-#endif
-
- case CA_SET_PLAYER_GRAVITY:
- {
- game.gravity = (action_arg == CA_ARG_GRAVITY_OFF ? FALSE :
- action_arg == CA_ARG_GRAVITY_ON ? TRUE :
- action_arg == CA_ARG_GRAVITY_TOGGLE ? !game.gravity :
- game.gravity);
- break;
- }
-
- case CA_SET_WIND_DIRECTION:
- {
- game.wind_direction = (action_arg >= CA_ARG_DIRECTION_NONE &&
- action_arg <= CA_ARG_DIRECTION_DOWN ?
- action_arg - CA_ARG_DIRECTION :
- action_arg == CA_ARG_DIRECTION_TRIGGER ?
- MV_DIR_OPPOSITE(change->actual_trigger_side) :
- game.wind_direction);
-
- break;
- }
- case CA_SET_LEVEL_GEMS:
+ case CA_SET_PLAYER_ARTWORK:
{
- local_player->gems_still_needed = action_arg_number_new;
-
- DrawGameValue_Emeralds(local_player->gems_still_needed);
+ for (i = 0; i < MAX_PLAYERS; i++)
+ {
+ if (trigger_player_bits & (1 << i))
+ {
+ int artwork_element = action_arg_element;
- break;
- }
+ if (action_arg == CA_ARG_ELEMENT_RESET)
+ artwork_element = stored_player[i].element_nr;
- case CA_SET_LEVEL_TIME:
- {
- if (level.time > 0) /* only modify limited time value */
- {
- TimeLeft = action_arg_number_new;
+ stored_player[i].artwork_element = artwork_element;
- DrawGameValue_Time(TimeLeft);
+ SetPlayerWaiting(&stored_player[i], FALSE);
- if (!TimeLeft && setup.time_limit)
- for (i = 0; i < MAX_PLAYERS; i++)
- KillPlayer(&stored_player[i]);
+ /* set number of special actions for bored and sleeping animation */
+ stored_player[i].num_special_action_bored =
+ get_num_special_action(artwork_element,
+ ACTION_BORING_1, ACTION_BORING_LAST);
+ stored_player[i].num_special_action_sleeping =
+ get_num_special_action(artwork_element,
+ ACTION_SLEEPING_1, ACTION_SLEEPING_LAST);
+ }
}
break;
}
- case CA_SET_LEVEL_SCORE:
- {
- local_player->score = action_arg_number_new;
-
- DrawGameValue_Score(local_player->score);
-
- break;
- }
+ /* ---------- CE actions ---------------------------------------------- */
case CA_SET_CE_SCORE:
{
break;
}
-#if 0
- 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;
- }
-#endif
-
default:
break;
}
int x, int y, int target_element)
{
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) &&
IS_WALKABLE(Feld[x][y]));
if (element_info[Feld[x][y]].move_direction_initial == MV_START_PREVIOUS)
MovDir[x][y] = previous_move_direction;
+#if USE_NEW_CUSTOM_VALUE
+ if (element_info[Feld[x][y]].use_last_ce_value)
+ CustomValue[x][y] = last_ce_value;
+#endif
+
InitField_WithBug1(x, y, FALSE);
DrawLevelField(x, y);
static void PlayPlayerSound(struct PlayerInfo *player)
{
int jx = player->jx, jy = player->jy;
- int element = player->element_nr;
+ int sound_element = player->artwork_element;
int last_action = player->last_action_waiting;
int action = player->action_waiting;
if (player->is_waiting)
{
if (action != last_action)
- PlayLevelSoundElementAction(jx, jy, element, action);
+ PlayLevelSoundElementAction(jx, jy, sound_element, action);
else
- PlayLevelSoundElementActionIfLoop(jx, jy, element, action);
+ PlayLevelSoundElementActionIfLoop(jx, jy, sound_element, action);
}
else
{
if (action != last_action)
- StopSound(element_info[element].sound[last_action]);
+ StopSound(element_info[sound_element].sound[last_action]);
if (last_action == ACTION_SLEEPING)
- PlayLevelSoundElementAction(jx, jy, element, ACTION_AWAKENING);
+ PlayLevelSoundElementAction(jx, jy, sound_element, ACTION_AWAKENING);
}
}
last_special_action < ACTION_SLEEPING_1 + num_special_action - 1 ?
last_special_action + 1 : ACTION_SLEEPING);
int special_graphic =
- el_act_dir2img(player->element_nr, special_action, move_dir);
+ el_act_dir2img(player->artwork_element, special_action, move_dir);
player->anim_delay_counter =
graphic_info[special_graphic].anim_delay_fixed +
int special_action =
ACTION_BORING_1 + SimpleRND(player->num_special_action_bored);
int special_graphic =
- el_act_dir2img(player->element_nr, special_action, move_dir);
+ el_act_dir2img(player->artwork_element, special_action, move_dir);
player->anim_delay_counter =
graphic_info[special_graphic].anim_delay_fixed +
RemoveField(x, y);
}
+#if USE_NEW_SNAP_DELAY
+ if (Feld[x][y] == EL_ELEMENT_SNAPPING)
+ {
+ MovDelay[x][y]--;
+ if (MovDelay[x][y] <= 0)
+ {
+ RemoveField(x, y);
+ DrawLevelField(x, y);
+
+ TestIfElementTouchesCustomElement(x, y); /* for empty space */
+ }
+ }
+#endif
+
#if DEBUG
if (ChangePage[x][y] != -1 && ChangeDelay[x][y] != 1)
{
CheckForDragon(x, y);
else if (element == EL_EXPLOSION)
; /* drawing of correct explosion animation is handled separately */
+ else if (element == EL_ELEMENT_SNAPPING)
+ {
+#if 1
+ graphic = el_act_dir2img(GfxElement[x][y], GfxAction[x][y],GfxDir[x][y]);
+
+ DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
+#endif
+ }
else if (IS_ANIMATED(graphic) && !IS_CHANGING(x, y))
DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
CloseAllOpenTimegates();
}
+ if (game.lenses_time_left > 0)
+ {
+ game.lenses_time_left--;
+
+ if (game.lenses_time_left == 0)
+ RedrawAllInvisibleElementsForLenses();
+ }
+
+ if (game.magnify_time_left > 0)
+ {
+ game.magnify_time_left--;
+
+ if (game.magnify_time_left == 0)
+ RedrawAllInvisibleElementsForMagnifier();
+ }
+
for (i = 0; i < MAX_PLAYERS; i++)
{
struct PlayerInfo *player = &stored_player[i];
if (!IN_LEV_FIELD(new_jx, new_jy))
return MF_NO_ACTION;
+ if (player->cannot_move)
+ {
+ DigField(player, 0, 0, 0, 0, 0, 0, DF_NO_PUSH);
+ SnapField(player, 0, 0);
+
+ return MF_NO_ACTION;
+ }
+
if (!options.network && !AllPlayersInSight(player, new_jx, new_jy))
return MF_NO_ACTION;
CheckTriggeredElementChangeByPlayer(jx, jy, new_element,
CE_PLAYER_ENTERS_X,
player->index_bit, enter_side);
+
+ CheckTriggeredElementChangeBySide(jx, jy, player->element_nr,
+ CE_MOVE_OF_X, move_direction);
}
if (game.engine_version >= VERSION_IDENT(3,0,7,0))
if (!player->active)
return;
- PlayLevelSoundElementAction(jx, jy, player->element_nr, ACTION_DYING);
+ PlayLevelSoundElementAction(jx, jy, player->artwork_element, ACTION_DYING);
PlayLevelSound(jx, jy, SND_GAME_LOSING);
player->GameOver = TRUE;
ExitY = ZY = jy;
}
+#if USE_NEW_SNAP_DELAY
+static void setFieldForSnapping(int x, int y, int element, int direction)
+{
+ struct ElementInfo *ei = &element_info[element];
+ int direction_bit = MV_DIR_BIT(direction);
+ int graphic_snapping = ei->direction_graphic[ACTION_SNAPPING][direction_bit];
+ int action = (graphic_snapping != IMG_EMPTY_SPACE ? ACTION_SNAPPING :
+ IS_DIGGABLE(element) ? ACTION_DIGGING : ACTION_COLLECTING);
+
+ Feld[x][y] = EL_ELEMENT_SNAPPING;
+ MovDelay[x][y] = MOVE_DELAY_NORMAL_SPEED + 1 - 1;
+
+ ResetGfxAnimation(x, y);
+
+ GfxElement[x][y] = element;
+ GfxAction[x][y] = action;
+ GfxDir[x][y] = direction;
+ GfxFrame[x][y] = -1;
+}
+#endif
+
/*
=============================================================================
checkDiagonalPushing()
if (mode == DF_SNAP && !IS_SNAPPABLE(element) &&
game.engine_version >= VERSION_IDENT(2,2,0,0))
+ {
+ CheckElementChangeByPlayer(x, y, element, CE_SNAPPED_BY_PLAYER,
+ player->index_bit, dig_side);
+ CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_SNAPS_X,
+ player->index_bit, dig_side);
+
+ if (Feld[x][y] != element) /* field changed by snapping */
+ return MF_ACTION;
+
return MF_NO_ACTION;
+ }
if (game.gravity && is_player && !player->is_auto_moving &&
canFallDown(player) && move_direction != MV_DOWN &&
if (!player->key[RND_GATE_GRAY_NR(element)])
return MF_NO_ACTION;
}
+ else if (IS_RND_GATE_GRAY_ACTIVE(element))
+ {
+ if (!player->key[RND_GATE_GRAY_ACTIVE_NR(element)])
+ return MF_NO_ACTION;
+ }
else if (element == EL_EXIT_OPEN ||
element == EL_SP_EXIT_OPEN ||
element == EL_SP_EXIT_OPENING)
if (element_info[sound_element].sound[sound_action] != SND_UNDEFINED)
PlayLevelSoundElementAction(x, y, sound_element, sound_action);
else
- PlayLevelSoundElementAction(x, y, player->element_nr, sound_action);
+ PlayLevelSoundElementAction(x, y, player->artwork_element, sound_action);
}
else if (IS_PASSABLE(element) && canPassField(x, y, move_direction))
{
if (!player->key[EM_GATE_GRAY_NR(element)])
return MF_NO_ACTION;
}
+ else if (IS_EM_GATE_GRAY_ACTIVE(element))
+ {
+ if (!player->key[EM_GATE_GRAY_ACTIVE_NR(element)])
+ return MF_NO_ACTION;
+ }
else if (IS_SP_PORT(element))
{
if (element == EL_SP_GRAVITY_PORT_LEFT ||
player->index_bit, dig_side);
if (mode == DF_SNAP)
- TestIfElementTouchesCustomElement(x, y); /* for empty space */
+ {
+#if USE_NEW_SNAP_DELAY
+ if (level.block_snap_field)
+ setFieldForSnapping(x, y, element, move_direction);
+ else
+ TestIfElementTouchesCustomElement(x, y); /* for empty space */
+#else
+ TestIfElementTouchesCustomElement(x, y); /* for empty space */
+#endif
+
+ CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_SNAPS_X,
+ player->index_bit, dig_side);
+ }
}
else if (IS_COLLECTIBLE(element))
{
{
player->show_envelope = element;
}
+ else if (element == EL_EMC_LENSES)
+ {
+ game.lenses_time_left = level.lenses_time * FRAMES_PER_SECOND;
+
+ RedrawAllInvisibleElementsForLenses();
+ }
+ else if (element == EL_EMC_MAGNIFIER)
+ {
+ game.magnify_time_left = level.magnify_time * FRAMES_PER_SECOND;
+
+ RedrawAllInvisibleElementsForMagnifier();
+ }
else if (IS_DROPPABLE(element) ||
IS_THROWABLE(element)) /* can be collected and dropped */
{
player->index_bit, dig_side);
if (mode == DF_SNAP)
- TestIfElementTouchesCustomElement(x, y); /* for empty space */
+ {
+#if USE_NEW_SNAP_DELAY
+ if (level.block_snap_field)
+ setFieldForSnapping(x, y, element, move_direction);
+ else
+ TestIfElementTouchesCustomElement(x, y); /* for empty space */
+#else
+ TestIfElementTouchesCustomElement(x, y); /* for empty space */
+#endif
+
+ CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_SNAPS_X,
+ player->index_bit, dig_side);
+ }
}
else if (IS_PUSHABLE(element))
{
else if (element == EL_TIME_ORB_FULL)
{
Feld[x][y] = EL_TIME_ORB_EMPTY;
- TimeLeft += level.time_orb_time;
- DrawGameValue_Time(TimeLeft);
+
+ if (level.time > 0 || level.use_time_orb_bug)
+ {
+ TimeLeft += level.time_orb_time;
+ DrawGameValue_Time(TimeLeft);
+ }
ResetGfxAnimation(x, y);
DrawLevelField(x, y);
CheckTriggeredElementChangeByPlayer(x, y, element, CE_SWITCH_OF_X,
player->index_bit, dig_side);
+ CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_SWITCHES_X,
+ player->index_bit, dig_side);
+
CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_PRESSES_X,
player->index_bit, dig_side);
player->index_bit, dig_side);
CheckTriggeredElementChangeByPlayer(x, y, element, CE_SWITCH_OF_X,
player->index_bit, dig_side);
+
+ CheckElementChangeByPlayer(x, y, element, CE_SWITCHED_BY_PLAYER,
+ player->index_bit, dig_side);
+ CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_SWITCHES_X,
+ player->index_bit, dig_side);
}
CheckElementChangeByPlayer(x, y, element, CE_PRESSED_BY_PLAYER,
RaiseScore(level.score[SC_SHIELD]);
break;
case EL_EXTRA_TIME:
- RaiseScore(level.score[SC_TIME_BONUS]);
+ RaiseScore(level.extra_time_score);
break;
case EL_KEY_1:
case EL_KEY_2: