rnd-20031128-1-src
[rocksndiamonds.git] / src / game.c
index 27aa2b4074d6446d47c63875bd3f630e1268a93f..e0423a0cf4bea429d6ced5eb7ad7ce54bf7a08cf 100644 (file)
@@ -186,6 +186,7 @@ static void PlayLevelSound(int, int, int);
 static void PlayLevelSoundNearest(int, int, int);
 static void PlayLevelSoundAction(int, int, int);
 static void PlayLevelSoundElementAction(int, int, int, int);
+static void PlayLevelSoundElementActionIfLoop(int, int, int, int);
 static void PlayLevelSoundActionIfLoop(int, int, int);
 static void StopLevelSoundActionIfLoop(int, int, int);
 static void PlayLevelMusic();
@@ -992,7 +993,7 @@ void InitGame()
   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, x, y;
+  int i, j, k, x, y;
 
   InitGameEngine();
 
@@ -1009,7 +1010,7 @@ void InitGame()
   /* don't play tapes over network */
   network_playing = (options.network && !tape.playing);
 
-  for (i=0; i<MAX_PLAYERS; i++)
+  for (i=0; i < MAX_PLAYERS; i++)
   {
     struct PlayerInfo *player = &stored_player[i];
 
@@ -1029,7 +1030,7 @@ void InitGame()
     player->lights_still_needed = 0;
     player->friends_still_needed = 0;
 
-    for (j=0; j<4; j++)
+    for (j=0; j < 4; j++)
       player->key[j] = FALSE;
 
     player->dynabomb_count = 0;
@@ -1059,6 +1060,51 @@ void InitGame()
     player->is_pushing = FALSE;
     player->is_switching = FALSE;
 
+    player->is_bored = FALSE;
+    player->is_sleeping = FALSE;
+
+    player->frame_counter_bored = -1;
+    player->frame_counter_sleeping = -1;
+
+    player->anim_delay_counter = 0;
+    player->post_delay_counter = 0;
+
+    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;
+    }
+
     player->switch_x = -1;
     player->switch_y = -1;
 
@@ -5944,6 +5990,71 @@ static boolean CheckElementChange(int x, int y, int element, int trigger_event)
   return CheckElementSideChange(x, y, element, CH_SIDE_ANY, trigger_event, -1);
 }
 
+static void SetPlayerWaiting(struct PlayerInfo *player, boolean is_waiting)
+{
+  int jx = player->jx, jy = player->jy;
+  int element = player->element_nr;
+  boolean was_waiting = player->is_waiting;
+
+  if (is_waiting)
+  {
+    int action;
+
+    if (!was_waiting)          /* not waiting -> waiting */
+    {
+      player->is_waiting = TRUE;
+
+      player->frame_counter_bored =
+       FrameCounter +
+       game.player_boring_delay_fixed +
+       SimpleRND(game.player_boring_delay_random);
+      player->frame_counter_sleeping =
+       FrameCounter +
+       game.player_sleeping_delay_fixed +
+       SimpleRND(game.player_sleeping_delay_random);
+
+      InitPlayerGfxAnimation(player, ACTION_WAITING, player->MovDir);
+    }
+
+    if (game.player_sleeping_delay_fixed != -1 &&
+       game.player_sleeping_delay_random != -1 &&
+       player->anim_delay_counter == 0 &&
+       player->post_delay_counter == 0 &&
+       FrameCounter >= player->frame_counter_sleeping)
+      player->is_sleeping = TRUE;
+    else if (game.player_boring_delay_fixed != -1 &&
+            game.player_boring_delay_random != -1 &&
+            FrameCounter >= player->frame_counter_bored)
+      player->is_bored = TRUE;
+
+    action = (player->is_sleeping ? ACTION_SLEEPING :
+             player->is_bored ? ACTION_BORING : ACTION_WAITING);
+
+    if (!was_waiting)
+      PlayLevelSoundElementAction(jx, jy, element, action);
+    else
+      PlayLevelSoundElementActionIfLoop(jx, jy, element, action);
+  }
+  else if (was_waiting)                /* waiting -> not waiting */
+  {
+    if (player->is_sleeping)
+      PlayLevelSoundElementAction(jx, jy, element, ACTION_AWAKENING);
+
+    player->is_waiting = FALSE;
+    player->is_bored = FALSE;
+    player->is_sleeping = FALSE;
+
+    player->frame_counter_bored = -1;
+    player->frame_counter_sleeping = -1;
+
+    player->anim_delay_counter = 0;
+    player->post_delay_counter = 0;
+
+    player->special_action_bored = ACTION_DEFAULT;
+    player->special_action_sleeping = ACTION_DEFAULT;
+  }
+}
+
 #if 1
 static byte PlayerActions(struct PlayerInfo *player, byte player_action)
 {
@@ -5998,6 +6109,8 @@ static byte PlayerActions(struct PlayerInfo *player, byte player_action)
       }
     }
 
+    SetPlayerWaiting(player, FALSE);
+
 #if 1
     return player_action;
 #else
@@ -6017,7 +6130,7 @@ static byte PlayerActions(struct PlayerInfo *player, byte player_action)
     CheckGravityMovement(player);
 
     if (player->MovPos == 0)
-      InitPlayerGfxAnimation(player, ACTION_DEFAULT, player->MovDir);
+      SetPlayerWaiting(player, TRUE);
 
     if (player->MovPos == 0)   /* needed for tape.playing */
       player->is_moving = FALSE;
@@ -6201,6 +6314,9 @@ void GameActions()
 
     tape_action[i] = PlayerActions(&stored_player[i], actual_player_action);
 
+    if (tape.recording && tape_action[i] && !tape.player_participates[i])
+      tape.player_participates[i] = TRUE;    /* player just appeared from CE */
+
     ScrollPlayer(&stored_player[i], SCROLL_GO_ON);
   }
 
@@ -8591,6 +8707,15 @@ static void PlayLevelSoundElementAction(int x, int y, int element, int action)
     PlayLevelSound(x, y, sound_effect);
 }
 
+static void PlayLevelSoundElementActionIfLoop(int x, int y, int element,
+                                             int action)
+{
+  int sound_effect = element_info[element].sound[action];
+
+  if (sound_effect != SND_UNDEFINED && IS_LOOP_SOUND(sound_effect))
+    PlayLevelSound(x, y, sound_effect);
+}
+
 static void PlayLevelSoundActionIfLoop(int x, int y, int action)
 {
   int sound_effect = element_info[Feld[x][y]].sound[action];
@@ -8610,10 +8735,10 @@ static void StopLevelSoundActionIfLoop(int x, int y, int action)
 static void PlayLevelMusic()
 {
 #if 1
-  if (levelset.music[game_status][level_nr] != MUS_UNDEFINED)
-    PlayMusic(levelset.music[game_status][level_nr]);
+  if (levelset.music[level_nr] != MUS_UNDEFINED)
+    PlayMusic(levelset.music[level_nr]);       /* from config file */
   else
-    PlayMusic(-(level_nr + 1));
+    PlayMusic(-(level_nr + 1));                        /* from music dir */
 #else
   PlayMusic(level_nr);
 #endif