Logo Search packages:      
Sourcecode: widelands version File versions  Download package

editor_player_menu.cc

/*
 * Copyright (C) 2002-2004, 2006-2007 by the Widelands Development Team
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include "editor_player_menu.h"

#include "editor.h"
#include "editorinteractive.h"
#include "editor_set_starting_pos_tool.h"
#include "error.h"
#include "graphic.h"
#include "i18n.h"
#include "map.h"
#include "overlay_manager.h"
#include "player.h"
#include "tribe.h"
#include "warehouse.h"
#include "wexception.h"

#include "ui_editbox.h"
#include "ui_modal_messagebox.h"
#include "ui_textarea.h"


Editor_Player_Menu::Editor_Player_Menu
(Editor_Interactive & parent, UI::UniqueWindow::Registry * registry)
:
UI::UniqueWindow(&parent, registry, 340, 400, _("Player Options")),

m_add_player
(this,
 5, 5, 20, 20,
 1,
 g_gr->get_picture(PicMod_Game, "pics/scrollbar_up.png"),
 &Editor_Player_Menu::clicked_add_player, this,
 _("Add player"),
 parent.egbase().map().get_nrplayers() < MAX_PLAYERS),

m_remove_last_player
(this,
 get_inner_w() - 5 - 20, 5, 20, 20,
 1,
 g_gr->get_picture(PicMod_Game, "pics/scrollbar_down.png"),
 &Editor_Player_Menu::clicked_remove_last_player, this,
 _("Remove last player"),
 1 < parent.egbase().map().get_nrplayers())

{
   // User Interface
   int spacing=5;
   int width=20;
   int posy= 0;

      Tribe_Descr::get_all_tribenames(m_tribes);

   set_inner_size(375, 135);

      UI::Textarea * ta =
            new UI::Textarea(this, 0, 0, _("Number of Players"), Align_Left);
      ta->set_pos(Point((get_inner_w() - ta->get_w()) / 2, posy + 5));
   posy+=spacing+width;

   m_nr_of_players_ta=new UI::Textarea(this, 0, 0, "5", Align_Left);
   m_nr_of_players_ta->set_pos
            (Point((get_inner_w() - m_nr_of_players_ta->get_w()) / 2, posy + 5));
   posy+=width+spacing+spacing;

   m_posy=posy;

   int i=0;
   for (i=0; i<MAX_PLAYERS; i++) {
      m_plr_names[i]=0;
      m_plr_set_pos_buts[i]=0;
      m_plr_set_tribes_buts[i]=0;
//       m_plr_make_infrastructure_buts[i]=0;
//       m_plr_allowed_buildings[i]=0;
      }
   update();

   set_think(true);
}

/*
 * Think function. Some things may change while this window
 * is open
 */
void Editor_Player_Menu::think() {
   update();
}

/*
===============
Editor_Player_Menu::update()

Update all
===============
*/
void Editor_Player_Menu::update() {
      if (is_minimal()) return;

      Map & map =
            dynamic_cast<const Editor_Interactive &>(*get_parent()).egbase().map();
      const Player_Number nr_players = map.get_nrplayers();
   std::string text="";
   if (nr_players/10) text+=static_cast<char>(nr_players/10 + 0x30);
   text+=static_cast<char>((nr_players%10) + 0x30);

   m_nr_of_players_ta->set_text(text.c_str());

   // Now remove all the unneeded stuff
   int i=0;
   for (i=nr_players; i<MAX_PLAYERS; i++) {
         delete m_plr_names[i];
         m_plr_names[i]=0;
         delete m_plr_set_pos_buts[i];
         m_plr_set_pos_buts[i]=0;
         delete m_plr_set_tribes_buts[i];
         m_plr_set_tribes_buts[i]=0;
#if 0
         delete m_plr_make_infrastructure_buts[i];
         m_plr_make_infrastructure_buts[i]=0;
         delete m_plr_allowed_buildings[i];
         m_plr_allowed_buildings[i]=0;
#endif
      }
   int posy=m_posy;
   int spacing=5;
   int size=20;


   // And recreate the needed
   for (i=0; i<nr_players; i++) {
      // Check if starting position is valid
      bool start_pos_valid=true;
            const Coords start_pos = map.get_starting_pos(i + 1);
            if (start_pos.isNull()) start_pos_valid = false;

            int posx = spacing;
      if (!m_plr_names[i]) {
          m_plr_names[i]=new UI::Edit_Box(this, posx, posy, 140, size, 0, i);
          m_plr_names[i]->changedid.set(this, &Editor_Player_Menu::name_changed);
          posx+=140+spacing;
                  m_plr_names[i]->set_text(map.get_scenario_player_name(i + 1).c_str());
            }

      if (!m_plr_set_tribes_buts[i]) {
                  m_plr_set_tribes_buts[i] =
                        new UI::IDButton<Editor_Player_Menu, const Player_Number>
                        (this,
                         posx, posy, 140, size,
                         0,
                         &Editor_Player_Menu::player_tribe_clicked, this, i,
                         std::string());
         posx+=140+spacing;
            }
            if (map.get_scenario_player_tribe(i + 1) != "<undefined>")
                  m_plr_set_tribes_buts[i]->set_title
                        (map.get_scenario_player_tribe(i + 1).c_str());
      else {
         m_plr_set_tribes_buts[i]->set_title(m_tribes[0].c_str());
                  map.set_scenario_player_tribe(i + 1, m_tribes[0]);
            }

      // Set Starting pos button
      if (!m_plr_set_pos_buts[i]) {
                  m_plr_set_pos_buts[i] =
                        new UI::IDButton<Editor_Player_Menu, const Player_Number>
                        (this,
                         posx, posy, size, size,
                         0,
                         0, //  set below
                         &Editor_Player_Menu::set_starting_pos_clicked, this, i + 1,
                         std::string());
          posx+=size+spacing;
            }
      text="pics/fsel_editor_set_player_";
      text+=static_cast<char>(((i+1)/10) + 0x30);
      text+=static_cast<char>(((i+1)%10) + 0x30);
      text+="_pos.png";
      m_plr_set_pos_buts[i]->set_pic(g_gr->get_picture(PicMod_Game,  text.c_str()));
#if 0
      // Build infrastructure but
      if (!m_plr_make_infrastructure_buts[i]) {
                  m_plr_make_infrastructure_buts[i] =
                        new UI::IDButton<Editor_Player_Menu, const Player_Number>
                        (this,
                         posx, posy, size, size,
                         0,
                         &Editor_Player_Menu::make_infrastructure_clicked, this, i + 1,
                         _("I"), //  TODO come up with a picture for this
                         _("Make infrastructure"));
         posx+=size+spacing;
            }
            m_plr_make_infrastructure_buts[i]->set_enabled(start_pos_valid);

      // Allowed buildings
      if (!m_plr_allowed_buildings[i]) {
                  m_plr_allowed_buildings[i] =
                        new UI::IDButton<Editor_Player_Menu, const Player_Number>
                        (this,
                         posx, posy, size, size,
                         0,
                         &Editor_Player_Menu::allowed_buildings_clicked, this, i + 1,
                         _("B"), //  TODO come up with a picture for this
                         _("Allow/forbid buildidngs"),
                        start_pos_valid);
         posx+=size+spacing;
            }
         m_plr_allowed_buildings[i]->set_enabled(start_pos_valid);
#endif
      posy+=size+spacing;
      }
   set_inner_size(get_inner_w(), posy+spacing);
}

void Editor_Player_Menu::clicked_add_player() {
      Editor_Interactive & parent =
            dynamic_cast<Editor_Interactive &>(*get_parent());
      Map & map = parent.egbase().map();
      const Player_Number nr_players = map.get_nrplayers() + 1;
      assert(nr_players <= MAX_PLAYERS);
      // register new default name for this players
      char c1=  (nr_players/10) ? (nr_players/10) + 0x30 : 0;
      char c2= (nr_players%10) + 0x30;
      std::string name=_("Player ");
      if (c1) name.append(1, c1);
      name.append(1, c2);
            map.set_nrplayers(nr_players);
            map.set_scenario_player_name(nr_players, name);
            map.set_scenario_player_tribe(nr_players, m_tribes[0]);
            parent.set_need_save(true);
      m_add_player        .set_enabled(nr_players < MAX_PLAYERS);
      m_remove_last_player.set_enabled(true);
      update();
}


void Editor_Player_Menu::clicked_remove_last_player() {
      Editor_Interactive & parent =
            dynamic_cast<Editor_Interactive &>(*get_parent());
      Map & map = parent.egbase().map();
      const Player_Number old_nr_players = map.get_nrplayers();
      const Player_Number nr_players = old_nr_players - 1;
      assert(1 <= nr_players);
      if (not parent.is_player_tribe_referenced(nr_players)) {
            {
                  const Coords starting_pos = map.get_starting_pos(old_nr_players);
                  if (not starting_pos.isNull()) {
                        //  Remove starting position marker.
                        std::string picsname = "pics/editor_player_";
                        picsname += static_cast<char>(old_nr_players / 10 + 0x30);
                        picsname += static_cast<char>(old_nr_players % 10 + 0x30);
                        picsname += "_starting_pos.png";
                        map.overlay_manager().remove_overlay
                              (starting_pos, g_gr->get_picture(PicMod_Game, picsname.c_str()));
                  }
            }
                  std::string name  = map.get_scenario_player_name (nr_players);
                  std::string tribe = map.get_scenario_player_tribe(nr_players);
                  map.set_nrplayers(nr_players);
                  map.set_scenario_player_name(nr_players, name);
                  map.set_scenario_player_tribe(nr_players, tribe);
                  parent.set_need_save(true);
            m_add_player        .set_enabled(true);
            m_remove_last_player.set_enabled(1 < nr_players);
            if
                  (&parent.tools.current() == &parent.tools.set_starting_pos
                   and
                   parent.tools.set_starting_pos.get_current_player() == old_nr_players)
                  //  The starting position tool is the currently active editor tool and
                  //  the sel picture is the one with the color of
                  //  the player that is being removed. Make sure that it is fixed in
                  //  that case by by switching the tool to the previous player and
                  //  reselecting the tool.
                  set_starting_pos_clicked(nr_players); //  This calls update().
            else update();
            } else {
                  UI::Modal_Message_Box mmb
                        (&parent,
                         _("Error!"),
                         _("Can't remove player. It is referenced in some place. Remove "
                           "all buildings, bobs, triggers and events that depend on this "
                           "player and try again"),
                         UI::Modal_Message_Box::OK);
                  mmb.run();
            }
}


/*
 * Player Tribe Button clicked
 */
void Editor_Player_Menu::player_tribe_clicked(const Uint8 n) {
      Editor_Interactive & parent =
            dynamic_cast<Editor_Interactive &>(*get_parent());
   // Tribe button has been clicked
      if (not parent.is_player_tribe_referenced(n + 1)) {
      std::string t = m_plr_set_tribes_buts[n]->get_title();
      if (!Tribe_Descr::exists_tribe(t))
         throw wexception("Map defines tribe %s, but it doesn't exist!\n", t.c_str());
      uint i;
      for (i=0; i<m_tribes.size(); i++)
         if (m_tribes[i]==t) break;
      if (i==m_tribes.size()-1) t=m_tribes[0];
      else t=m_tribes[++i];
            parent.egbase().map().set_scenario_player_tribe(n+1, t);
            parent.set_need_save(true);
      } else {
            UI::Modal_Message_Box mmb
                  (&parent,
                   _("Error!"),
                   _("Can't change player tribe. It is referenced in some place. Remove "
                     "all buildings, bobs, triggers and events that depend on this "
                     "tribe and try again"),
                   UI::Modal_Message_Box::OK);
            mmb.run();
      }
   update();
}


/*
 * Set Current Start Position button selected
 */
void Editor_Player_Menu::set_starting_pos_clicked(const Uint8 n) {
      Editor_Interactive & parent =
            dynamic_cast<Editor_Interactive &>(*get_parent());
   // jump to the current field
      Map & map =parent.egbase().map();
      const Coords c = map.get_starting_pos(n);
   if (not c.isNull()) parent.move_view_to(c);

   // If the player is already created in the editor, this means
   // that there might be already a hq placed somewhere. This needs to be
   // deleted before a starting position change can occure
      if (parent.editor().get_player(n)) {
            if (not map.get_starting_pos(n).isNull()) {
                  if
                        (dynamic_cast<const Building *>
                         (map[map.get_starting_pos(n)].get_immovable()))
                        return;
            }
      }

   // Select tool set mplayer
      parent.select_tool(parent.tools.set_starting_pos, Editor_Tool::First);
      parent.tools.set_starting_pos.set_current_player(n);

   // Reselect tool, so everything is in a defined state
      parent.select_tool(parent.tools.current(), Editor_Tool::First);

   // Register callback function to make sure that only valid fields are selected.
      map.overlay_manager().register_overlay_callback_function
            (&Editor_Tool_Set_Starting_Pos_Callback, &map);
      map.recalc_whole_map();
   update();
}

/*
 * Player name has changed
 */
void Editor_Player_Menu::name_changed(int m) {
   // Player name has been changed
   std::string text=m_plr_names[m]->get_text();
      Editor_Interactive & parent =
            dynamic_cast<Editor_Interactive &>(*get_parent());
      Map & map = parent.egbase().map();
   if (text=="") {
            text = map.get_scenario_player_name(m + 1);
      m_plr_names[m]->set_text(text.c_str());
      }
      map.set_scenario_player_name(m + 1, text);
      m_plr_names[m]->set_text(map.get_scenario_player_name(m + 1).c_str());
      parent.set_need_save(true);
}

#if 0
/*
 * Make infrastructure button clicked
 */
void Editor_Player_Menu::make_infrastructure_clicked(const Uint8 n) {
      Editor_Interactive & parent =
            dynamic_cast<Editor_Interactive &>(*get_parent());
   // Check if starting position is valid (was checked before
   // so must be true)
      Editor & editor = parent.editor();
      Map             & map             = editor.map();
      Overlay_Manager & overlay_manager = map.overlay_manager();
      const Coords start_pos = map.get_starting_pos(n);
   assert(start_pos.is_valid());

      Player * p = editor.get_player(n);
   if (!p) {
      // This player is unknown, register it, place a hq and reference the tribe
      // so that this tribe can not be changed
            editor.add_player
                  (n,
                   Player::Local,
                   m_plr_set_tribes_buts[n - 1]->get_title(),
                   m_plr_names[n - 1]->get_text());

            p = editor.get_player(n);
      p->init(false);
      }

   // If the player is already created in the editor, this means
   // that there might be already a hq placed somewhere. This needs to be
   // deleted before a starting position change can occure
      const Player_Number player_number = p->get_player_number();
      const Coords starting_pos = map.get_starting_pos(player_number);
      BaseImmovable * const imm = map[starting_pos].get_immovable();
      if (not imm) {
      // place HQ
            const Tribe_Descr & tribe = p->tribe();
      const int idx = tribe.get_building_index("headquarters");
      if (idx < 0)
         throw wexception("Tribe %s lacks headquarters", tribe.name().c_str());
            Warehouse & headquarter = dynamic_cast<Warehouse &>
                  (*editor.warp_building(starting_pos, player_number, idx));
            editor.conquer_area
                  (Player_Area
                   (player_number, Area(starting_pos, headquarter.get_conquers())));
            tribe.load_warehouse_with_start_wares(editor, headquarter);

            parent.reference_player_tribe(n, &tribe);

      // Remove the player overlay from this starting pos.
      // A HQ is overlay enough
      std::string picsname="pics/editor_player_";
      picsname+=static_cast<char>((n/10) + 0x30);
      picsname+=static_cast<char>((n%10) + 0x30);
      picsname+="_starting_pos.png";
      int picid=g_gr->get_picture(PicMod_Game,  picsname.c_str());
      // Remove old overlay if any
            overlay_manager.remove_overlay(start_pos, picid);
      }

      parent.select_tool(parent.tools.make_infrastructure, Editor_Tool::First);
      parent.tools.make_infrastructure.set_player(n);
      overlay_manager.register_overlay_callback_function
            (&Editor_Make_Infrastructure_Tool_Callback,
             static_cast<void *>(&editor),
             n);
      map.recalc_whole_map();
}

/*
 * Allowed building button clicked
 */
void Editor_Player_Menu::allowed_buildings_clicked(const Uint8 n) {
      Editor_Interactive & parent =
            dynamic_cast<Editor_Interactive &>(*get_parent());
      Editor & editor = parent.editor();

      if (not editor.get_player(n)) {
      // The player is not yet really on the map, call make infrastructure button first
      make_infrastructure_clicked(n);
      }

   // Create the menu
   if (m_allow_buildings_menu.window) {
      delete m_allow_buildings_menu.window;
      }
      else new Editor_Player_Menu_Allowed_Buildings_Menu
            (&parent, editor.get_player(n), &m_allow_buildings_menu);
}
#endif

Generated by  Doxygen 1.6.0   Back to index