replaced flag for game/tape mouse actions by bitmask
[rocksndiamonds.git] / src / game.c
index a82ca0798b9e1dacd6c368dd896d86220d182413..36fc3b6835a4dd14edec4d2acc095f647b3dc7ae 100644 (file)
@@ -3279,6 +3279,30 @@ static void InitGameEngine(void)
   // Supaplex levels with time limit currently unsupported -- should be added
   if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
     level.time = 0;
+
+  // ---------- initialize mask for handling game action events ---------------
+
+  // set game action events mask to default value
+  game.event_mask = GAME_EVENTS_DEFAULT;
+
+  // when using Mirror Magic game engine, handle mouse events only
+  if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
+    game.event_mask = GAME_EVENTS_MOUSE;
+
+  // check for custom elements with mouse click events
+  if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
+  {
+    for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+    {
+      int element = EL_CUSTOM_START + i;
+
+      if (HAS_CHANGE_EVENT(element, CE_CLICKED_BY_MOUSE) ||
+         HAS_CHANGE_EVENT(element, CE_PRESSED_BY_MOUSE) ||
+         HAS_CHANGE_EVENT(element, CE_MOUSE_CLICKED_ON_X) ||
+         HAS_CHANGE_EVENT(element, CE_MOUSE_PRESSED_ON_X))
+       game.event_mask = GAME_EVENTS_MOUSE;
+    }
+  }
 }
 
 static int get_num_special_action(int element, int action_first,
@@ -3391,6 +3415,10 @@ void InitGame(void)
   InitGameEngine();
   InitGameControlValues();
 
+  // initialize tape action events from game when recording tape
+  if (tape.recording)
+    tape.event_mask = game.event_mask;
+
   // don't play tapes over network
   network_playing = (network.enabled && !tape.playing);
 
@@ -9880,11 +9908,14 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
     // ---------- player actions  ---------------------------------------------
 
     case CA_MOVE_PLAYER:
+    case CA_MOVE_PLAYER_NEW:
     {
       // 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;
+         if (action_type == CA_MOVE_PLAYER ||
+             stored_player[i].MovPos == 0)
+           stored_player[i].programmed_action = action_arg_direction;
 
       break;
     }
@@ -11145,7 +11176,7 @@ static byte PlayerActions(struct PlayerInfo *player, byte player_action)
 static void SetMouseActionFromTapeAction(struct MouseActionInfo *mouse_action,
                                         byte *tape_action)
 {
-  if (!tape.use_mouse)
+  if (tape.event_mask != GAME_EVENTS_MOUSE)
     return;
 
   mouse_action->lx     = tape_action[TAPE_ACTION_LX];
@@ -11156,7 +11187,7 @@ static void SetMouseActionFromTapeAction(struct MouseActionInfo *mouse_action,
 static void SetTapeActionFromMouseAction(byte *tape_action,
                                         struct MouseActionInfo *mouse_action)
 {
-  if (!tape.use_mouse)
+  if (tape.event_mask != GAME_EVENTS_MOUSE)
     return;
 
   tape_action[TAPE_ACTION_LX]     = mouse_action->lx;
@@ -11354,7 +11385,7 @@ static void GameActionsExt(void)
   unsigned int game_frame_delay_value;
   byte *recorded_player_action;
   byte summarized_player_action = 0;
-  byte tape_action[MAX_PLAYERS];
+  byte tape_action[MAX_TAPE_ACTIONS] = { 0 };
   int i;
 
   // detect endless loops, caused by custom element programming
@@ -11687,6 +11718,8 @@ void GameActions_RND_Main(void)
 
 void GameActions_RND(void)
 {
+  static struct MouseActionInfo mouse_action_last = { 0 };
+  struct MouseActionInfo mouse_action = local_player->effective_mouse_action;
   int magic_wall_x = 0, magic_wall_y = 0;
   int i, x, y, element, graphic, last_gfx_frame;
 
@@ -11873,6 +11906,24 @@ void GameActions_RND(void)
 #endif
   }
 
+  if (mouse_action.button)
+  {
+    int new_button = (mouse_action.button && mouse_action_last.button == 0);
+
+    x = local_player->mouse_action.lx;
+    y = local_player->mouse_action.ly;
+    element = Feld[x][y];
+
+    if (new_button)
+    {
+      CheckElementChange(x, y, element, EL_UNDEFINED, CE_CLICKED_BY_MOUSE);
+      CheckTriggeredElementChange(x, y, element, CE_MOUSE_CLICKED_ON_X);
+    }
+
+    CheckElementChange(x, y, element, EL_UNDEFINED, CE_PRESSED_BY_MOUSE);
+    CheckTriggeredElementChange(x, y, element, CE_MOUSE_PRESSED_ON_X);
+  }
+
   SCAN_PLAYFIELD(x, y)
   {
     element = Feld[x][y];
@@ -12214,6 +12265,8 @@ void GameActions_RND(void)
   // use random number generator in every frame to make it less predictable
   if (game.engine_version >= VERSION_IDENT(3,1,1,0))
     RND(1);
+
+  mouse_action_last = mouse_action;
 }
 
 static boolean AllPlayersInSight(struct PlayerInfo *player, int x, int y)