#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))
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)
+ 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
}
player->is_bored = FALSE;
player->is_sleeping = FALSE;
+ player->cannot_move = FALSE;
+
player->frame_counter_bored = -1;
player->frame_counter_sleeping = -1;
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];
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);
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_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);
+ 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)
break;
}
+ 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_RESTART_LEVEL:
{
game.restart_level = TRUE;
break;
}
- case CA_ADD_KEY:
+ 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)] = TRUE;
+ stored_player[i].key[KEY_NR(element)] = key_state;
DrawGameValue_Keys(stored_player[i].key);
break;
}
- case CA_REMOVE_KEY:
- {
- int element = getSpecialActionElement(action_arg_element,
- action_arg_number, EL_KEY_1);
-
- if (IS_KEY(element))
- {
- for (i = 0; i < MAX_PLAYERS; i++)
- {
- if (trigger_player_bits & (1 << i))
- {
- stored_player[i].key[KEY_NR(element)] = FALSE;
-
- DrawGameValue_Keys(stored_player[i].key);
-
- redraw_mask |= REDRAW_DOOR_1;
- }
- }
- }
-
- 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;
+ break;
+ }
-#if 0
- printf("::: move_delay_value == %d [%d]\n",
- stored_player[i].move_delay_value_next, action_arg_number);
-#endif
- }
+ case CA_SET_PLAYER_ARTWORK:
+ {
+ for (i = 0; i < MAX_PLAYERS; i++)
+ {
+ int element = action_arg_element;
}
break;
}
-#endif
- case CA_SET_PLAYER_GRAVITY:
+ case CA_SET_LEVEL_GRAVITY:
{
game.gravity = (action_arg == CA_ARG_GRAVITY_OFF ? FALSE :
action_arg == CA_ARG_GRAVITY_ON ? TRUE :
break;
}
- case CA_SET_WIND_DIRECTION:
+ case CA_SET_LEVEL_WIND:
{
- 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);
+ game.wind_direction = action_arg_direction;
break;
}
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);
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);
+ }
+ }
+#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);
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;
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()
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);
+#endif
+ }
}
else if (IS_COLLECTIBLE(element))
{
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);
+#endif
+ }
}
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);