fixed bug with not recognizing ".mode_loop: false" for music
[rocksndiamonds.git] / src / tools.c
index f06ddb8efbb5333c0359667199131c4c6c443c29..a11f692eb2d66a2abd495ceab77017d10b0de2ca 100644 (file)
@@ -981,6 +981,8 @@ static void FadeExt(int fade_mask, int fade_mode, int fade_type)
                draw_border_function);
 
   redraw_mask &= ~fade_mask;
+
+  ClearEventQueue();
 }
 
 static void SetScreenStates_BeforeFadingIn()
@@ -2800,6 +2802,8 @@ void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
 
     SkipUntilDelayReached(&anim_delay, anim_delay_value, &i, last_frame);
   }
+
+  ClearEventQueue();
 }
 
 void ShowEnvelope(int envelope_nr)
@@ -3083,6 +3087,8 @@ void AnimateEnvelopeRequest(int anim_mode, int action)
 
     SkipUntilDelayReached(&anim_delay, anim_delay_value, &i, last_frame);
   }
+
+  ClearEventQueue();
 }
 
 void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
@@ -3504,9 +3510,85 @@ static void DrawPreviewLevelExt(boolean restart)
   }
 }
 
+void DrawPreviewPlayers()
+{
+  if (game_status != GAME_MODE_MAIN)
+    return;
+
+  if (!network.enabled && !setup.team_mode)
+    return;
+
+  boolean player_found[MAX_PLAYERS];
+  int num_players = 0;
+  int i, x, y;
+
+  for (i = 0; i < MAX_PLAYERS; i++)
+    player_found[i] = FALSE;
+
+  /* check which players can be found in the level (simple approach) */
+  for (x = 0; x < lev_fieldx; x++)
+  {
+    for (y = 0; y < lev_fieldy; y++)
+    {
+      int element = level.field[x][y];
+
+      if (ELEM_IS_PLAYER(element))
+      {
+       int player_nr = GET_PLAYER_NR(element);
+
+       player_nr = MIN(MAX(0, player_nr), MAX_PLAYERS - 1);
+
+       if (!player_found[player_nr])
+         num_players++;
+
+       player_found[player_nr] = TRUE;
+      }
+    }
+  }
+
+  struct TextPosInfo *pos = &menu.main.preview_players;
+  int tile_size = pos->tile_size;
+  int border_size = pos->border_size;
+  int player_xoffset_raw = (pos->vertical ? 0 : tile_size + border_size);
+  int player_yoffset_raw = (pos->vertical ? tile_size + border_size : 0);
+  int player_xoffset = (pos->xoffset != -1 ? pos->xoffset : player_xoffset_raw);
+  int player_yoffset = (pos->yoffset != -1 ? pos->yoffset : player_yoffset_raw);
+  int max_players_width  = (MAX_PLAYERS - 1) * player_xoffset + tile_size;
+  int max_players_height = (MAX_PLAYERS - 1) * player_yoffset + tile_size;
+  int all_players_width  = (num_players - 1) * player_xoffset + tile_size;
+  int all_players_height = (num_players - 1) * player_yoffset + tile_size;
+  int max_xpos = SX + ALIGNED_XPOS(pos->x, max_players_width,  pos->align);
+  int max_ypos = SY + ALIGNED_YPOS(pos->y, max_players_height, pos->valign);
+  int xpos = SX + ALIGNED_XPOS(pos->x, all_players_width,  pos->align);
+  int ypos = SY + ALIGNED_YPOS(pos->y, all_players_height, pos->valign);
+
+  /* clear area in which the players will be drawn */
+  ClearRectangleOnBackground(drawto, max_xpos, max_ypos,
+                            max_players_width, max_players_height);
+
+  /* only draw players if level is suited for team mode */
+  if (num_players < 2)
+    return;
+
+  /* draw all players that were found in the level */
+  for (i = 0; i < MAX_PLAYERS; i++)
+  {
+    if (player_found[i])
+    {
+      int graphic = el2img(EL_PLAYER_1 + i);
+
+      DrawSizedGraphicThruMaskExt(drawto, xpos, ypos, graphic, 0, tile_size);
+
+      xpos += player_xoffset;
+      ypos += player_yoffset;
+    }
+  }
+}
+
 void DrawPreviewLevelInitial()
 {
   DrawPreviewLevelExt(TRUE);
+  DrawPreviewPlayers();
 }
 
 void DrawPreviewLevelAnimation()
@@ -3514,6 +3596,99 @@ void DrawPreviewLevelAnimation()
   DrawPreviewLevelExt(FALSE);
 }
 
+static void DrawNetworkPlayer(int x, int y, int player_nr, int tile_size,
+                             int border_size, int font_nr)
+{
+  int graphic = el2img(EL_PLAYER_1 + player_nr);
+  int font_height = getFontHeight(font_nr);
+  int player_height = MAX(tile_size, font_height);
+  int xoffset_text = tile_size + border_size;
+  int yoffset_text    = (player_height - font_height) / 2;
+  int yoffset_graphic = (player_height - tile_size) / 2;
+  char *player_name = getNetworkPlayerName(player_nr + 1);
+
+  DrawSizedGraphicThruMaskExt(drawto, x, y + yoffset_graphic, graphic, 0,
+                             tile_size);
+  DrawText(x + xoffset_text, y + yoffset_text, player_name, font_nr);
+}
+
+void DrawNetworkPlayersExt(boolean force)
+{
+  if (game_status != GAME_MODE_MAIN)
+    return;
+
+  if (!network.connected && !force)
+    return;
+
+  int num_players = 0;
+  int i;
+
+  for (i = 0; i < MAX_PLAYERS; i++)
+    if (stored_player[i].connected_network)
+      num_players++;
+
+  struct TextPosInfo *pos = &menu.main.network_players;
+  int tile_size = pos->tile_size;
+  int border_size = pos->border_size;
+  int xoffset_text = tile_size + border_size;
+  int font_nr = pos->font;
+  int font_width = getFontWidth(font_nr);
+  int font_height = getFontHeight(font_nr);
+  int player_height = MAX(tile_size, font_height);
+  int player_yoffset = player_height + border_size;
+  int max_players_width = xoffset_text + MAX_PLAYER_NAME_LEN * font_width;
+  int max_players_height = MAX_PLAYERS * player_yoffset - border_size;
+  int all_players_height = num_players * player_yoffset - border_size;
+  int max_xpos = SX + ALIGNED_XPOS(pos->x, max_players_width,  pos->align);
+  int max_ypos = SY + ALIGNED_YPOS(pos->y, max_players_height, pos->valign);
+  int ypos = SY + ALIGNED_YPOS(pos->y, all_players_height, pos->valign);
+
+  ClearRectangleOnBackground(drawto, max_xpos, max_ypos,
+                            max_players_width, max_players_height);
+
+  /* first draw local network player ... */
+  for (i = 0; i < MAX_PLAYERS; i++)
+  {
+    if (stored_player[i].connected_network &&
+       stored_player[i].connected_locally)
+    {
+      char *player_name = getNetworkPlayerName(i + 1);
+      int player_width = xoffset_text + getTextWidth(player_name, font_nr);
+      int xpos = SX + ALIGNED_XPOS(pos->x, player_width,  pos->align);
+
+      DrawNetworkPlayer(xpos, ypos, i, tile_size, border_size, font_nr);
+
+      ypos += player_yoffset;
+    }
+  }
+
+  /* ... then draw all other network players */
+  for (i = 0; i < MAX_PLAYERS; i++)
+  {
+    if (stored_player[i].connected_network &&
+       !stored_player[i].connected_locally)
+    {
+      char *player_name = getNetworkPlayerName(i + 1);
+      int player_width = xoffset_text + getTextWidth(player_name, font_nr);
+      int xpos = SX + ALIGNED_XPOS(pos->x, player_width,  pos->align);
+
+      DrawNetworkPlayer(xpos, ypos, i, tile_size, border_size, font_nr);
+
+      ypos += player_yoffset;
+    }
+  }
+}
+
+void DrawNetworkPlayers()
+{
+  DrawNetworkPlayersExt(FALSE);
+}
+
+void ClearNetworkPlayers()
+{
+  DrawNetworkPlayersExt(TRUE);
+}
+
 inline static void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
                                           int graphic, int sync_frame,
                                           int mask_mode)
@@ -4392,13 +4567,12 @@ static boolean RequestDoor(char *text, unsigned int req_state)
 
   SetMouseCursor(CURSOR_DEFAULT);
 
-#if defined(NETWORK_AVALIABLE)
   /* pause network game while waiting for request to answer */
-  if (options.network &&
+  if (network.enabled &&
       game_status == GAME_MODE_PLAYING &&
+      !AllPlayersGone &&
       req_state & REQUEST_WAIT_FOR_INPUT)
     SendToServer_PausePlaying();
-#endif
 
   old_door_state = GetDoorState();
 
@@ -4534,13 +4708,12 @@ static boolean RequestDoor(char *text, unsigned int req_state)
     SetDrawBackgroundMask(REDRAW_FIELD);
   }
 
-#if defined(NETWORK_AVALIABLE)
   /* continue network game after request */
-  if (options.network &&
+  if (network.enabled &&
       game_status == GAME_MODE_PLAYING &&
+      !AllPlayersGone &&
       req_state & REQUEST_WAIT_FOR_INPUT)
     SendToServer_ContinuePlaying();
-#endif
 
   /* restore deactivated drawing when quick-loading level tape recording */
   if (tape.playing && tape.deactivate_display)
@@ -4562,13 +4735,12 @@ static boolean RequestEnvelope(char *text, unsigned int req_state)
 
   SetMouseCursor(CURSOR_DEFAULT);
 
-#if defined(NETWORK_AVALIABLE)
   /* pause network game while waiting for request to answer */
-  if (options.network &&
+  if (network.enabled &&
       game_status == GAME_MODE_PLAYING &&
+      !AllPlayersGone &&
       req_state & REQUEST_WAIT_FOR_INPUT)
     SendToServer_PausePlaying();
-#endif
 
   /* simulate releasing mouse button over last gadget, if still pressed */
   if (button_status)
@@ -4621,13 +4793,12 @@ static boolean RequestEnvelope(char *text, unsigned int req_state)
     SetDrawBackgroundMask(REDRAW_FIELD);
   }
 
-#if defined(NETWORK_AVALIABLE)
   /* continue network game after request */
-  if (options.network &&
+  if (network.enabled &&
       game_status == GAME_MODE_PLAYING &&
+      !AllPlayersGone &&
       req_state & REQUEST_WAIT_FOR_INPUT)
     SendToServer_ContinuePlaying();
-#endif
 
   /* restore deactivated drawing when quick-loading level tape recording */
   if (tape.playing && tape.deactivate_display)
@@ -5258,6 +5429,8 @@ unsigned int MoveDoor(unsigned int door_state)
   DrawMaskedBorder(REDRAW_DOOR_1);
   DrawMaskedBorder(REDRAW_DOOR_2);
 
+  ClearEventQueue();
+
   return (door1 | door2);
 }
 
@@ -7942,7 +8115,7 @@ int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
 
 boolean getTeamMode_EM()
 {
-  return game.team_mode;
+  return game.team_mode || network_playing;
 }
 
 int getGameFrameDelay_EM(int native_em_game_frame_delay)
@@ -9042,7 +9215,10 @@ void PlayMenuMusicExt(int music)
   if (!setup.sound_music)
     return;
 
-  PlayMusic(music);
+  if (IS_LOOP_MUSIC(music))
+    PlayMusicLoop(music);
+  else
+    PlayMusic(music);
 }
 
 void PlayMenuMusic()
@@ -9218,6 +9394,13 @@ void ResetFontStatus()
   SetFontStatus(-1);
 }
 
+void SetLevelSetInfo(char *identifier, int level_nr)
+{
+  setString(&levelset.identifier, identifier);
+
+  levelset.level_nr = level_nr;
+}
+
 boolean CheckIfPlayfieldViewportHasChanged()
 {
   // if game status has not changed, playfield viewport has not changed either