+ case CA_SET_LEVEL_WIND:
+ {
+ game.wind_direction = action_arg_direction;
+
+ break;
+ }
+
+ /* ---------- 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 (IS_KEY(element))
+ {
+ for (i = 0; i < MAX_PLAYERS; i++)
+ {
+ if (trigger_player_bits & (1 << i))
+ {
+ stored_player[i].key[KEY_NR(element)] = key_state;
+
+#if 1
+ DrawGameDoorValues();
+#else
+ DrawGameValue_Keys(stored_player[i].key);
+#endif
+
+ redraw_mask |= REDRAW_DOOR_1;
+ }
+ }
+ }
+
+ break;
+ }
+
+ case CA_SET_PLAYER_SPEED:
+ {
+ 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_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 :
+ CA_MODE_MULTIPLY);
+ }
+ else if (action_arg == CA_ARG_NUMBER_RESET)
+ {
+ action_arg_number = level.initial_player_stepsize[i];
+ }
+
+ move_stepsize =
+ getModifiedActionNumber(move_stepsize,
+ action_mode,
+ action_arg_number,
+ 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));
+
+ /* do no immediately change -- the player might just be moving */
+ stored_player[i].move_delay_value_next = TILEX / move_stepsize;
+
+ stored_player[i].cannot_move =
+ (action_arg == CA_ARG_SPEED_NOT_MOVING ? TRUE : FALSE);
+#endif
+ }
+ }
+
+ break;
+ }
+
+ case CA_SET_PLAYER_SHIELD:
+ {
+ for (i = 0; i < MAX_PLAYERS; i++)
+ {
+ if (trigger_player_bits & (1 << i))
+ {
+ if (action_arg == CA_ARG_SHIELD_OFF)
+ {
+ 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;
+ }
+ }
+ }
+
+ break;
+ }
+
+#if USE_PLAYER_GRAVITY
+ case CA_SET_PLAYER_GRAVITY:
+ {
+ for (i = 0; i < MAX_PLAYERS; i++)
+ {
+ if (trigger_player_bits & (1 << i))
+ {
+ stored_player[i].gravity =
+ (action_arg == CA_ARG_GRAVITY_OFF ? FALSE :
+ action_arg == CA_ARG_GRAVITY_ON ? TRUE :
+ action_arg == CA_ARG_GRAVITY_TOGGLE ? !stored_player[i].gravity :
+ stored_player[i].gravity);
+ }
+ }
+
+ break;
+ }
+#endif
+
+ case CA_SET_PLAYER_ARTWORK:
+ {
+ for (i = 0; i < MAX_PLAYERS; i++)
+ {
+ if (trigger_player_bits & (1 << i))
+ {
+ int artwork_element = action_arg_element;
+
+ if (action_arg == CA_ARG_ELEMENT_RESET)
+ artwork_element =
+ (level.use_artwork_element[i] ? level.artwork_element[i] :
+ stored_player[i].element_nr);
+
+ stored_player[i].artwork_element = artwork_element;
+
+ SetPlayerWaiting(&stored_player[i], FALSE);
+
+ /* 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;
+ }
+
+ /* ---------- CE actions ---------------------------------------------- */
+
+ case CA_SET_CE_VALUE:
+ {
+#if USE_NEW_CUSTOM_VALUE
+ int last_ce_value = CustomValue[x][y];
+
+ CustomValue[x][y] = action_arg_number_new;
+
+#if 0
+ printf("::: CE value == %d\n", CustomValue[x][y]);
+#endif
+
+ if (CustomValue[x][y] != last_ce_value)
+ {
+ CheckElementChange(x, y, element, EL_UNDEFINED, CE_VALUE_CHANGES);
+ CheckTriggeredElementChange(x, y, element, CE_VALUE_CHANGES_OF_X);
+
+ if (CustomValue[x][y] == 0)
+ {
+#if 0
+ printf("::: CE_VALUE_GETS_ZERO\n");
+#endif
+
+ CheckElementChange(x, y, element, EL_UNDEFINED, CE_VALUE_GETS_ZERO);
+ CheckTriggeredElementChange(x, y, element, CE_VALUE_GETS_ZERO_OF_X);
+
+#if 0
+ printf("::: RESULT: %d, %d\n", Feld[x][y], ChangePage[x][y]);
+#endif
+ }
+ }
+
+#endif
+
+ break;
+ }
+
+ case CA_SET_CE_SCORE:
+ {
+#if USE_NEW_CUSTOM_VALUE
+ int last_ce_score = ei->collect_score;
+
+ ei->collect_score = action_arg_number_new;
+
+#if 0
+ printf("::: CE score == %d\n", ei->collect_score);
+#endif
+
+ if (ei->collect_score != last_ce_score)
+ {
+ CheckElementChange(x, y, element, EL_UNDEFINED, CE_SCORE_CHANGES);
+ CheckTriggeredElementChange(x, y, element, CE_SCORE_CHANGES_OF_X);
+
+ if (ei->collect_score == 0)
+ {
+#if 0
+ printf("::: CE_SCORE_GETS_ZERO\n");
+#endif
+
+ CheckElementChange(x, y, element, EL_UNDEFINED, CE_SCORE_GETS_ZERO);
+ CheckTriggeredElementChange(x, y, element, CE_SCORE_GETS_ZERO_OF_X);
+
+#if 0
+ printf("::: RESULT: %d, %d\n", Feld[x][y], ChangePage[x][y]);
+#endif
+ }
+ }
+
+#endif
+
+ break;
+ }
+
+ /* ---------- engine actions ------------------------------------------ */
+
+ case CA_SET_ENGINE_SCAN_MODE:
+ {
+ InitPlayfieldScanMode(action_arg);
+
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+static void CreateFieldExt(int x, int y, int element, boolean is_change)
+{
+ int old_element = Feld[x][y];
+ int new_element = get_element_from_group_element(element);
+ int previous_move_direction = MovDir[x][y];
+#if USE_NEW_CUSTOM_VALUE
+ int last_ce_value = CustomValue[x][y];
+#endif
+ boolean new_element_is_player = ELEM_IS_PLAYER(new_element);
+ boolean add_player_onto_element = (new_element_is_player &&
+ new_element != EL_SOKOBAN_FIELD_PLAYER &&
+ IS_WALKABLE(old_element));
+
+#if 0
+ /* check if element under the 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(old_element) && !IS_ACCESSIBLE(new_element))
+ {