=== modified file 'libsiedler2/src/ArchivItem_Ini.h' --- libsiedler2/src/ArchivItem_Ini.h 2009-07-13 22:00:41 +0000 +++ libsiedler2/src/ArchivItem_Ini.h 2009-07-23 09:27:09 +0000 @@ -83,7 +83,7 @@ } } - inline void setValue(const char *name, unsigned int value) + inline void setValue(const char *name, int value) { char temp[512]; snprintf(temp, 256, "%d", value); === modified file 'src/CMakeLists.txt' --- src/CMakeLists.txt 2009-07-19 22:00:41 +0000 +++ src/CMakeLists.txt 2009-07-21 22:21:02 +0000 @@ -45,6 +45,7 @@ ctrlProgress.cpp ctrlProgress.h ctrlRectangle.cpp ctrlRectangle.h ctrlScrollBar.cpp ctrlScrollBar.h + ctrlSpinbox.cpp ctrlSpinbox.h ctrlTab.cpp ctrlTab.h ctrlTable.cpp ctrlTable.h ctrlText.cpp ctrlText.h @@ -83,6 +84,7 @@ iwDirectIPCreate.cpp iwDirectIPCreate.h iwDistribution.cpp iwDistribution.h iwEndgame.cpp iwEndgame.h + iwEnhancements.cpp iwEnhancements.h iwHelp.cpp iwHelp.h iwHQ.cpp iwHQ.h iwInventory.cpp iwInventory.h @@ -122,11 +124,14 @@ CollisionDetection.cpp CollisionDetection.h ClientInterface.cpp ClientInterface.h colors.h + const_enhancements.cpp const_enhancements.h const_gui_ids.h controls.h customborderbuilder.h customborderbuilder.cpp Desktop.cpp Desktop.h DoorConsts.h + enhOptions.cpp enhOptions.h + Enhancements.cpp Enhancements.h EventManager.cpp EventManager.h ExtensionList.cpp ExtensionList.h FileChecksum.cpp FileChecksum.h === added file 'src/Enhancements.cpp' --- src/Enhancements.cpp 1970-01-01 00:00:00 +0000 +++ src/Enhancements.cpp 2009-07-22 12:41:17 +0000 @@ -0,0 +1,82 @@ +// $Id: Enhancements.cpp 5171 2009-07-02 20:21:42Z Divan $ +// +// Copyright (c) 2005-2009 Settlers Freaks (sf-team at siedler25.org) +// +// This file is part of Siedler II.5 RTTR. +// +// Siedler II.5 RTTR 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. +// +// Siedler II.5 RTTR 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 Siedler II.5 RTTR. If not, see . + +#include + +#include "Enhancements.h" + +// Destructor +Enhancements::~Enhancements() +{ + enh_by_id.clear(); + if (enh_by_order.size() > 0) + for(unsigned int i = 0; i > enh_by_order.size(); ++i) + delete enh_by_order[i]; +} + +const std::string Enhancements::GetValueAsString(const unsigned int &id, const int &value) const +{ + std::string s = ""; + enhOption enh = by_id(id); + switch(enh.type) + { + case ENH_OPT_BOOL: + { + s = (value == 1 ? _("Enabled") : _("Disabled")); + } break; + case ENH_OPT_SELECT: + { + int max = enh.selections.size() - 1; + assert(value <= max && value >= 0); + s = enh.selections[value]; + } break; + case ENH_OPT_INT: + { + std::stringstream ss; + ss << value; + s = ss.str(); + } break; + } + return s; +} + +void Enhancements::Add(const enhOption &enh) +{ + enhOption *enh2 = new enhOption; + *enh2 = enh; + // Autoset min/max + switch(enh2->type) + { + case ENH_OPT_BOOL: + { + enh2->min = 0; + enh2->max = 1; + } break; + case ENH_OPT_SELECT: + { + enh2->min = 0; + enh2->max = enh2->selections.size()-1; + } break; + default: {} + } + // Add to stack + enh_by_order.push_back(enh2); + enh_by_id.insert(std::make_pair(enh2->id, enh2)); +} + === added file 'src/Enhancements.h' --- src/Enhancements.h 1970-01-01 00:00:00 +0000 +++ src/Enhancements.h 2009-07-23 09:27:09 +0000 @@ -0,0 +1,83 @@ +// $Id: Enhancements.h 5171 2009-07-02 20:21:42Z Divan $ +// +// Copyright (c) 2005-2009 Settlers Freaks (sf-team at siedler25.org) +// +// This file is part of Siedler II.5 RTTR. +// +// Siedler II.5 RTTR 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. +// +// Siedler II.5 RTTR 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 Siedler II.5 RTTR. If not, see . +#ifndef ENHANCEMENTS_H_INCLUDED +#define ENHANCEMENTS_H_INCLUDED + +#pragma once + +/////////////////////////////////////////////////////////////////////////////// +// Header +#include +#include + +#include "Singleton.h" +#include "enhOptions.h" + +/////////////////////////////////////////////////////////////////////////////// +// Class for Enhancements +// +// This class contains the available enhancement options +// and is used to access their properties. +// In the games, we only want to store the id-value pairs. +class Enhancements : public Singleton +{ +public: + Enhancements() {} + ~Enhancements(); + + // This function fills in the options. + // It is implemented in const_enhancements.cpp + void Initialize(); + + inline const unsigned char size() const + { + return enh_by_order.size(); + } + + inline bool isValidId(const unsigned int &id) const + { + return (by_id(id).id == id); + } + // get Option by ID + inline const enhOption& by_id(const unsigned int &id) const + { + return *((enh_by_id.find(id))->second); + } + // get Option by number (for having a definable order) + inline const enhOption& by_order(const unsigned int &i) const + { + assert(i < enh_by_order.size()); + return *(enh_by_order.at(i)); + } + + // returns the value as a printable string + const std::string GetValueAsString(const unsigned int &id, const int &value) const; + +protected: + std::map enh_by_id; + std::map name_id_to_id; + std::vector enh_by_order; + void Add(const enhOption &enh); +}; + +/////////////////////////////////////////////////////////////////////////////// +// Makros / Defines +#define ENHANCEMENTS Enhancements::inst() + +#endif // ENHANCEMENTS_H_INCLUDED === modified file 'src/GameClient.cpp' --- src/GameClient.cpp 2009-07-22 22:00:51 +0000 +++ src/GameClient.cpp 2009-07-23 07:09:53 +0000 @@ -1004,10 +1004,12 @@ { LOG.write("<<< NMS_GGS_CHANGE\n"); + // First inform the interface so it can make a diff + if(ci) + ci->CI_GGSChanged(msg.ggs); + + // Then update ggs = msg.ggs; - - if(ci) - ci->CI_GGSChanged(ggs); } /////////////////////////////////////////////////////////////////////////////// === modified file 'src/GameClient.h' --- src/GameClient.h 2009-07-15 22:00:51 +0000 +++ src/GameClient.h 2009-07-19 20:31:24 +0000 @@ -105,7 +105,6 @@ /// Fügt ein GameCommand für den Spieler hinzu und gibt bei Erfolg true zurück, ansonstn false (in der Pause oder wenn Spieler besiegt ist) bool AddGC(gc::GameCommand * gc); - void Command_SetFlag2(int x, int y, unsigned char player); void Command_Chat(const std::string& text, const ChatDestination cd ); void Command_ToggleNation(); === modified file 'src/GameCommands.cpp' --- src/GameCommands.cpp 2009-07-19 22:00:41 +0000 +++ src/GameCommands.cpp 2009-07-22 21:38:30 +0000 @@ -23,12 +23,12 @@ #include "GameCommands.h" #include "GameClient.h" #include "GameClientPlayer.h" +#include "GameServer.h" #include "GameWorld.h" #include "nobShipYard.h" #include "nobMilitary.h" #include "nobBaseWarehouse.h" #include "nobHarborBuilding.h" - using namespace gc; GameCommand * GameCommand::CreateGameCommand(const Type gst, Serializer * ser) @@ -62,6 +62,7 @@ case CANCELPACT: return new CancelPact(ser); case CHANGESHIPYARDMODE: return new ChangeShipYardMode(ser); case STARTEXPEDITION: return new StartExpedition(ser); + case CHANGEGGS: return new ChangeGGS(ser); case SURRENDER: return new Surrender(ser); case CHEAT_ARMAGEDDON: return new CheatArmageddon(ser); case DESTROYALL: return new DestroyAll(ser); @@ -163,6 +164,12 @@ gwg.GetSpecObj(x,y)->SetRealReserve(rank,count); } + +void ChangeGGS::Execute(GameWorldGame& gwg, GameClientPlayer& player, const unsigned char playerid) +{ + GAMESERVER.ChangeGlobalGameSettings(this->ggs); +} + void Surrender::Execute(GameWorldGame& gwg, GameClientPlayer& player, const unsigned char playerid) { player.Surrender(); === modified file 'src/GameCommands.h' --- src/GameCommands.h 2009-07-19 22:00:41 +0000 +++ src/GameCommands.h 2009-07-22 12:14:59 +0000 @@ -7,6 +7,8 @@ #include #include +#include "GlobalGameSettings.h" + class GameClient; class GameServer; class GameWorldGame; @@ -46,7 +48,8 @@ STARTEXPEDITION, STARTATTACKINGEXPEDITION, EXPEDITION_COMMAND, - SURRENDER, + SURRENDER, + CHANGEGGS, CHEAT_ARMAGEDDON, DESTROYALL }; @@ -574,6 +577,35 @@ /// Führt das GameCommand aus void Execute(GameWorldGame& gwg, GameClientPlayer& player, const unsigned char playerid); }; + +/// GGS ändern +class ChangeGGS : public GameCommand +{ + // Wir müssen GlobalGameSettings.h eh inkludieren, da können wir's + // uns auch einfach machen mit dem Speichern. + GlobalGameSettings ggs; + +public: + ChangeGGS(const GlobalGameSettings & ggs) + : GameCommand(CHANGEGGS) + { + this->ggs = ggs; + } + + ChangeGGS(Serializer * ser) + : GameCommand(CHANGEGGS) + { + ggs.Deserialize(ser); + } + + virtual void Serialize(Serializer *ser) const + { + ggs.Serialize(ser); + } + + /// Führt das GameCommand aus + void Execute(GameWorldGame& gwg, GameClientPlayer& player, const unsigned char playerid); +}; /// Aufgeben class Surrender : public GameCommand === modified file 'src/GameManager.cpp' --- src/GameManager.cpp 2009-07-13 22:00:41 +0000 +++ src/GameManager.cpp 2009-07-21 22:21:02 +0000 @@ -24,6 +24,7 @@ #include "GlobalVars.h" #include "Settings.h" +#include "Enhancements.h" #include "SoundManager.h" #include "WindowManager.h" @@ -70,6 +71,10 @@ */ bool GameManager::Start() { + // Enhancements initialisieren, damit im Konstuktor keine gettext-Sachen + // stehen müssen. Muss vor SETTINGS.Load() stehen. + ENHANCEMENTS.Initialize(); + // Einstellungen laden if(!SETTINGS.Load()) return false; === modified file 'src/GameServer.cpp' --- src/GameServer.cpp 2009-07-02 22:00:36 +0000 +++ src/GameServer.cpp 2009-07-22 19:41:01 +0000 @@ -223,6 +223,10 @@ mapinfo.partcount = mapinfo.ziplength / MAP_PART_SIZE + ( (mapinfo.ziplength%MAP_PART_SIZE) ? 1 : 0); + // Lieblings-Enhancement-options rüberkopieren, später mal + // ganze GGS + ggs.enhancements = SETTINGS.enhancements.preferred; + // Speicher für Spieler anlegen for(unsigned i =0;iPushUnsignedChar(static_cast(exploration)); ser->PushBool(team_view); ser->PushUnsignedChar(static_cast(demolition_prohibition)); + enhancements.Serialize(*ser); } void GlobalGameSettings::Deserialize(Serializer * ser) @@ -51,4 +52,5 @@ exploration = static_cast(ser->PopUnsignedChar()); team_view = ser->PopBool(); demolition_prohibition = static_cast(ser->PopUnsignedChar()); + enhancements.Deserialize(*ser); } === modified file 'src/GlobalGameSettings.h' --- src/GlobalGameSettings.h 2009-07-02 22:00:36 +0000 +++ src/GlobalGameSettings.h 2009-07-22 12:41:17 +0000 @@ -23,6 +23,7 @@ #include "Singleton.h" #include "GameConsts.h" #include "GameProtocol.h" +#include "enhOptions.h" #include "Settings.h" class Serializer; @@ -44,11 +45,8 @@ bool team_view; /// Abriss bei Angriff erlaubt? enum DemolitionProhibition { DP_OFF = 0, DP_UNDERATTACK, DP_NEARFRONTIERS } demolition_prohibition; - - - /// Größe des Serialisierungsbuffers - // static const unsigned GGS_BUFFER_SIZE = 7; - unsigned GetLength() const {return 7; } + /// Erweiterungs-Einstellungen + enhOptions enhancements; /// Serialisierung und Deserialisierung void Serialize(Serializer * ser) const; === modified file 'src/Settings.cpp' --- src/Settings.cpp 2009-07-14 22:00:39 +0000 +++ src/Settings.cpp 2009-07-23 09:27:09 +0000 @@ -25,6 +25,9 @@ #include "files.h" #include "Loader.h" #include "languages.h" +#include "Serializer.h" +#include +#include "Enhancements.h" /////////////////////////////////////////////////////////////////////////////// // Makros / Defines @@ -34,10 +37,10 @@ static char THIS_FILE[] = __FILE__; #endif -const unsigned int Settings::SETTINGS_VERSION = 9; -const unsigned int Settings::SETTINGS_SECTIONS = 8; +const unsigned int Settings::SETTINGS_VERSION = 10; +const unsigned int Settings::SETTINGS_SECTIONS = 9; const std::string Settings::SETTINGS_SECTION_NAMES[] = { - "global", "video", "language", "driver", "sound", "lobby", "server", "savegames" + "global", "video", "language", "driver", "sound", "lobby", "server", "savegames", "enhancements" }; /////////////////////////////////////////////////////////////////////////////// @@ -109,6 +112,10 @@ savegames.autosave_interval = 0; // } + // enhancements + // { + // } + Save(); return true; @@ -132,9 +139,10 @@ const libsiedler2::ArchivItem_Ini *lobby = LOADER.GetSettingsIniN("lobby"); const libsiedler2::ArchivItem_Ini *server = LOADER.GetSettingsIniN("server"); const libsiedler2::ArchivItem_Ini *savegames = LOADER.GetSettingsIniN("savegames"); + const libsiedler2::ArchivItem_Ini *enhancements = LOADER.GetSettingsIniN("enhancements"); // ist eine der Kategorien nicht vorhanden? - if(!global || !video || !language || !driver || !sound || !lobby || !server || !savegames || + if(!global || !video || !language || !driver || !sound || !lobby || !server || !savegames || !enhancements || // stimmt die Settingsversion? ((unsigned int)global->getValueI("version") != SETTINGS_VERSION) ) @@ -219,6 +227,26 @@ this->savegames.autosave_interval = server->getValueI("autosave_interval"); // } + // enhancements + { + std::string value; + enhOption enh; + for (unsigned char i = 0; i < ENHANCEMENTS.size(); ++i) + { + // Do we have stored the option? + enh = ENHANCEMENTS.by_order(i); + // We can't use getValueI, because it would return 0 + // if the option isn't stored in the file. + value = enhancements->getValue(enh.id_name.c_str()); + // If so, set value accordingly + if (value != "") + this->enhancements.preferred.Set(enh.id, + atoi(value.c_str())); + // If not, enhOption cares about returning the default + // value by itself, nothing to do. + } + } + return true; } @@ -245,9 +273,10 @@ libsiedler2::ArchivItem_Ini *lobby = LOADER.GetSettingsIniN("lobby"); libsiedler2::ArchivItem_Ini *server = LOADER.GetSettingsIniN("server"); libsiedler2::ArchivItem_Ini *savegames = LOADER.GetSettingsIniN("savegames"); + libsiedler2::ArchivItem_Ini *enhancements = LOADER.GetSettingsIniN("enhancements"); // ist eine der Kategorien nicht vorhanden? - assert(global && video && language && driver && sound && lobby && server && savegames); + assert(global && video && language && driver && sound && lobby && server && savegames && enhancements); // global // { @@ -302,5 +331,17 @@ server->setValue("autosave_interval", this->savegames.autosave_interval); // } + // enhancements + { + enhOption enh; + int value; + for (unsigned char i = 0; i < ENHANCEMENTS.size(); ++i) + { + enh = ENHANCEMENTS.by_order(i); + value = this->enhancements.preferred.Get(enh.id); + enhancements->setValue(enh.id_name.c_str(), value); + } + } + LOADER.SaveSettings(); } === modified file 'src/Settings.h' --- src/Settings.h 2009-07-13 22:00:41 +0000 +++ src/Settings.h 2009-07-18 19:41:08 +0000 @@ -24,6 +24,7 @@ /////////////////////////////////////////////////////////////////////////////// // Header #include "Singleton.h" +#include "enhOptions.h" /////////////////////////////////////////////////////////////////////////////// // Klasse für die Konfiguration @@ -82,6 +83,10 @@ unsigned int autosave_interval; } savegames; + struct { + enhOptions preferred; + } enhancements; + private: static const unsigned int SETTINGS_VERSION; static const unsigned int SETTINGS_SECTIONS; === modified file 'src/Window.cpp' --- src/Window.cpp 2009-07-22 22:00:51 +0000 +++ src/Window.cpp 2009-07-23 07:09:53 +0000 @@ -730,6 +730,36 @@ /////////////////////////////////////////////////////////////////////////////// /** + * fügt ein SpinboxCtrl hinzu. + * + * @author Divan + */ +ctrlSpinbox *Window::AddSpinbox(unsigned int id, + unsigned short x, + unsigned short y, + unsigned short width, + unsigned short height, + TextureColor tc, + glArchivItem_Font *font, + bool disabled, + bool notify, + int min, + int max) +{ + if(scale) + { + x = ScaleX(x); + y = ScaleY(y); + width = ScaleX(width); + height = ScaleY(height); + } + + return AddCtrl(id, new ctrlSpinbox(this, id, x, y, width, height, tc, font, disabled, notify, min, max)); +} + + +/////////////////////////////////////////////////////////////////////////////// +/** * fügt ein TabCtrl hinzu. * * @author OLiver === modified file 'src/Window.h' --- src/Window.h 2009-05-26 22:00:35 +0000 +++ src/Window.h 2009-07-19 20:31:24 +0000 @@ -50,6 +50,7 @@ class ctrlPercent; class ctrlProgress; class ctrlScrollBar; +class ctrlSpinbox; class ctrlTab; class ctrlTable; class ctrlText; @@ -174,6 +175,8 @@ const std::string& tooltip = "", unsigned short x_padding = 0, unsigned short y_padding = 0, unsigned int force_color = 0, const std::string& button_minus_tooltip = "", const std::string& button_plus_tooltip = ""); /// fügt eine Scrollbar hinzu. ctrlScrollBar *AddScrollBar(unsigned int id, unsigned short x, unsigned short y, unsigned short width, unsigned short height, unsigned short button_height, TextureColor tc, unsigned short page_size); + /// fügt ein SpinboxCtrl hinzu. + ctrlSpinbox *AddSpinbox(unsigned int id, unsigned short x, unsigned short y, unsigned short width, unsigned short height, TextureColor tc, glArchivItem_Font *font, bool disabled = false, bool notify = false, int min = 0, int max = 0xFF); /// fügt ein TabCtrl hinzu. ctrlTab *AddTabCtrl(unsigned int id, unsigned short x, unsigned short y, unsigned short width); /// fügt eine Tabelle hinzu. === added file 'src/const_enhancements.cpp' --- src/const_enhancements.cpp 1970-01-01 00:00:00 +0000 +++ src/const_enhancements.cpp 2009-07-23 09:27:09 +0000 @@ -0,0 +1,84 @@ +// $Id: const_enhancements.cpp 5178 2009-07-03 11:55:24Z Divan $ +// +// Copyright (c) 2005-2009 Settlers Freaks (sf-team at siedler25.org) +// +// This file is part of Siedler II.5 RTTR. +// +// Siedler II.5 RTTR 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. +// +// Siedler II.5 RTTR 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 Siedler II.5 RTTR. If not, see . + +#include "const_enhancements.h" +#include "Enhancements.h" + +void Enhancements::Initialize() +{ + /* First, explainations: + + // Define an Id in const_enhancements.h! + + // The following values have to be set: + // id - Your chosen Id + // type - One of ENH_OPT_BOOL, ENH_OPT_SELECT, ENH_OPT_INT + // def - A default value. + // For ENH_OPT_BOOL, values translate true = 1, + // false = 0. For ENH_OPT_SELECT, values are an index, + // starting with 0. + // original - Which value reproduces the original game's behaviour? + // Choose def, if not applicable. + // min, max - For ENH_OPT_INT, you have to set the limits. Values + // are implemented as 4-byte int, this should fit any + // purpose. For ENH_OPT_SELECT and ENH_OPT_BOOL, the + // values are set automatically. + // name - A short name string. Enclose in gettext_noop("") + // for translation. + // name_id - An id for saving to CONFIG.INI. Please only use lower + // case letters and numbers and the underscore, and + // don't enclose for translation. + // description - Set the description text. + // This should make clear what this option does - the + // user can't be required to start a game to test the + // effect. Using \n for newline or \n\n for an empty + // line makes long texts a lot easier to read. Don't put + // spaces around the \n's! + // ingameChangeable - Whether the option may be changed while + // playing + // group - one of ENH_OPT_NONE, ENH_OPT_MILITARY, + // ENH_OPT_ECONOMY, ENH_OPT_CONSTRUCTION, ENH_OPT_SAILING + // This had no effect yet, but maybe we will once need + // grouping. + + // For ENH_OPT_SELECT, you now have to define the choices: + // enh.selections.push_back(gettext_noop("First option")); + // enh.selections.push_back(gettext_noop("Second option")); + // enh.selections.push_back(gettext_noop("Third option")); + + */ + + // Waterway length + { + enhOption enh; + enh.id = ENH_WATERWAY_LENGTH; + enh.type = ENH_OPT_INT; + enh.def = 5; + enh.original = 5; + enh.min = 0; + enh.max = 255; + enh.name = gettext_noop("Waterway length"); + enh.id_name = "waterway_length"; + enh.description = gettext_noop("Limits the distance settlers may travel per boat.\n\n\"0\" allows any length.\n\"1\" actually prevents usage of waterways."); + enh.ingameChangeable = true; + enh.group = ENH_OPT_CONSTRUCTION; + Add(enh); + } +} + === added file 'src/const_enhancements.h' --- src/const_enhancements.h 1970-01-01 00:00:00 +0000 +++ src/const_enhancements.h 2009-07-22 13:25:34 +0000 @@ -0,0 +1,46 @@ +// $Id: const_enhancements.h 5178 2009-07-03 11:55:24Z Divan $ +// +// Copyright (c) 2005-2009 Settlers Freaks (sf-team at siedler25.org) +// +// This file is part of Siedler II.5 RTTR. +// +// Siedler II.5 RTTR 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. +// +// Siedler II.5 RTTR 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 Siedler II.5 RTTR. If not, see . +#ifndef CONST_ENHANCEMENTS_H_INCLUDED +#define CONST_ENHANCEMENTS_H_INCLUDED + +#pragma once + +/// numerical constants for possible enhancement options. +/// +/// the DO's and DON'T's: +/// Please only use numbers between 10000000 and 19999999. +/// Don't ever change the numbers, or savegames will mess up. +/// Don't ever reuse numbers for options that fell out of the list for +/// other than the same option. Please just comment out outdated lines. +/// +/// The options appearance order is determined by the definition order +/// in const_enhancements.cpp, therefore we can keep this list ordered +/// lexicographically. +/// My idea is using the mid digits of the id for identifying the +/// enhancement's code's author for easier blaming ;) This would make +/// +/// Divan: 01 +/// +enum ENH_ID +{ + ENH_STATISTICS_VISIBILITY = 10001002, + ENH_WATERWAY_LENGTH = 10001001 +}; + +#endif // !CONST_ENHANCEMENTS_H_INCLUDED === modified file 'src/const_gui_ids.h' --- src/const_gui_ids.h 2009-07-03 14:19:25 +0000 +++ src/const_gui_ids.h 2009-07-19 20:31:24 +0000 @@ -28,6 +28,7 @@ CGI_DIRECTIPCONNECT, CGI_DIRECTIPCREATE, CGI_ENDGAME, + CGI_ENHANCEMENTS, CGI_LOBBYCONNECT, CGI_LOBBYADDSERVER, CGI_LOBBYRANKING, === modified file 'src/controls.h' --- src/controls.h 2009-04-27 22:00:38 +0000 +++ src/controls.h 2009-07-19 20:31:24 +0000 @@ -35,6 +35,7 @@ #include "ctrlPercent.h" #include "ctrlProgress.h" #include "ctrlScrollBar.h" +#include "ctrlSpinbox.h" #include "ctrlTab.h" #include "ctrlTable.h" #include "ctrlText.h" === modified file 'src/ctrlCheck.h' --- src/ctrlCheck.h 2009-04-27 22:00:38 +0000 +++ src/ctrlCheck.h 2009-07-19 20:31:24 +0000 @@ -32,6 +32,8 @@ bool GetCheck() const { return check; } void SetReadOnly(bool readonly) { this->readonly = readonly; } bool GetReadOnly() const { return readonly; } + /// Setzt Text + void SetText(const std::string& text) { this->text = text; } virtual bool Msg_LeftDown(const MouseCoords& mc); === modified file 'src/ctrlComboBox.cpp' --- src/ctrlComboBox.cpp 2009-07-11 22:00:41 +0000 +++ src/ctrlComboBox.cpp 2009-07-21 22:21:02 +0000 @@ -64,7 +64,8 @@ void ctrlComboBox::Msg_PaintAfter() { // Button und Liste malen - DrawControls(); + if (visible) + DrawControls(); } /////////////////////////////////////////////////////////////////////////////// === modified file 'src/ctrlComboBox.h' --- src/ctrlComboBox.h 2009-05-07 22:00:30 +0000 +++ src/ctrlComboBox.h 2009-07-19 20:31:24 +0000 @@ -36,6 +36,8 @@ unsigned short GetSelection() const { return selection; }; unsigned short GetCount() const { return GetCtrl(0)->GetLineCount(); } const std::string& GetText(unsigned short item) const { return GetCtrl(0)->GetItemText(item); } + void SetReadOnly(bool readonly) { this->readonly = readonly; } + bool GetReadOnly() const { return readonly; } virtual void Msg_PaintAfter(); virtual bool Msg_MouseMove(const MouseCoords& mc); === modified file 'src/ctrlMultiline.cpp' --- src/ctrlMultiline.cpp 2009-06-28 22:00:40 +0000 +++ src/ctrlMultiline.cpp 2009-07-19 20:31:24 +0000 @@ -53,35 +53,24 @@ AddScrollBar(0, width - SCROLLBAR_WIDTH, 0, SCROLLBAR_WIDTH, height, SCROLLBAR_WIDTH, tc, lines_in_control); } - ///////////////////////////////////////////////////////////////////////////////// -///** -// * fügt einen mehrzeiligen Text hinzu. -// * -// * @author FloSoft -// */ -//void ctrlMultiline::AddText(const std::string& text, unsigned int color) -//{ -// size_t i; -// size_t length = strlen(text); -// char *temp = new char[length + 1]; -// char *s = temp; -// -// // In temporaeren String kopieren, damit man diesen zerlegen kann -// memcpy(temp, text, length); -// -// // Zeilenweise einfuegen -// for (i = 0; i < length; ++i) { -// if(temp[i] == '\n') { -// temp[i] = '\0'; -// AddString(s, color, false); -// s = &temp[i + 1]; -// } -// } -// if (s < &temp[i]) AddString(s, color, false); - -// delete[] temp; -//} +/** + * fügt einen mehrzeiligen Text hinzu. + * + * @author FloSoft + */ +void ctrlMultiline::AddText(const std::string& text, unsigned int color) +{ + glArchivItem_Font::WrapInfo wi; + font->GetWrapInfo(text, GetWidth(), GetWidth(), wi); + if (wi.count > lines_in_control) + font->GetWrapInfo(text, GetWidth()-ctrlMultiline::SCROLLBAR_WIDTH, GetWidth()-ctrlMultiline::SCROLLBAR_WIDTH, wi); + std::string * lines = new std::string[wi.count]; + wi.CreateSingleStrings(text, lines); + for (unsigned i = 0; i < wi.count; ++i) + AddString(lines[i], color, false); + delete [] lines; +} /////////////////////////////////////////////////////////////////////////////// /** @@ -97,9 +86,22 @@ ctrlScrollBar *scrollbar = GetCtrl(0); scrollbar->SetRange(unsigned(lines.size())); - if (scroll && (scrollbar->GetPos() == (unsigned(lines.size()) - 1) - lines_in_control)) { + if (scroll && (scrollbar->GetPos() == (unsigned(lines.size()) - 1) - lines_in_control)) scrollbar->SetPos(scrollbar->GetPos() + 1); - } +} + +/////////////////////////////////////////////////////////////////////////////// +/** + * deletes all text + * + * @author OLiver + */ +void ctrlMultiline::DeleteAllItems() +{ + lines.clear(); + ctrlScrollBar *scrollbar = GetCtrl(0); + scrollbar->SetRange(0); + scrollbar->SetPos(0); } /////////////////////////////////////////////////////////////////////////////// === modified file 'src/ctrlMultiline.h' --- src/ctrlMultiline.h 2009-06-28 22:00:40 +0000 +++ src/ctrlMultiline.h 2009-07-19 20:31:24 +0000 @@ -31,12 +31,13 @@ public: ctrlMultiline(Window *parent, unsigned int id, unsigned short x, unsigned short y, unsigned short width, unsigned short height, TextureColor tc, glArchivItem_Font *font, unsigned int format = 0); - //void AddText(const std::string& text, unsigned int color); + void AddText(const std::string& text, unsigned int color); void AddString(const std::string& str, unsigned int color, bool scroll = true); unsigned GetLineCount() { return unsigned(lines.size()); } /// Gibt den index-ten Eintrag zurück const std::string& GetLine(const unsigned index) const { return lines[index].str; } void SetLine(const unsigned index, const std::string& str, unsigned int color); + void DeleteAllItems(); /// Schaltet Box ein und aus void EnableBox(const bool enable) { draw_box = enable; } === added file 'src/ctrlSpinbox.cpp' --- src/ctrlSpinbox.cpp 1970-01-01 00:00:00 +0000 +++ src/ctrlSpinbox.cpp 2009-07-22 19:41:01 +0000 @@ -0,0 +1,285 @@ +// $Id: ctrlEdit.cpp 5105 2009-03-29 10:10:02Z Divan $ +// +// Copyright (c) 2005-2009 Settlers Freaks (sf-team at siedler25.org) +// +// This file is part of Siedler II.5 RTTR. +// +// Siedler II.5 RTTR 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. +// +// Siedler II.5 RTTR 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 Siedler II.5 RTTR. If not, see . + +/////////////////////////////////////////////////////////////////////////////// +// Header +#include "main.h" +#include "ctrlSpinbox.h" +#include "ctrlEdit.h" +#include "ctrlButton.h" + +#include "VideoDriverWrapper.h" + +#include +#include +/////////////////////////////////////////////////////////////////////////////// +// Makros / Defines +#if defined _WIN32 && defined _DEBUG && defined _MSC_VER + #define new new(_NORMAL_BLOCK, THIS_FILE, __LINE__) + #undef THIS_FILE + static char THIS_FILE[] = __FILE__; +#endif + +/////////////////////////////////////////////////////////////////////////////// +/** + * Konstruktor von @p ctrlEdit. + * + * @author OLiver + */ +ctrlSpinbox::ctrlSpinbox(Window *parent, + unsigned int id, + unsigned short x, + unsigned short y, + unsigned short width, + unsigned short height, + TextureColor tc, + glArchivItem_Font *font, + bool disabled /*= false*/, + bool notify /*= false*/, + int min /*= -0x80000000*/, + int max /*= 0x7FFFFFFF*/) + : Window(x, y, id, parent), + width(width), height(height), tc(tc), font(font), password(password), disabled(disabled), + focus(false), newfocus(false), notify(notify), + value(min), min(min), max(max) +{ + AddEdit(0,0,0,width-height,height, tc, font, 11, false, disabled, notify); + + AddImageButton(1, width-height, 0, height, height/2, tc, LOADER.GetImageN("io", 33)); + AddImageButton(2, width-height, height/2, height, height-height/2, tc, LOADER.GetImageN("io", 34)); +} + +void ctrlSpinbox::SetValue(const int value) +{ + if (value <= max && value >= min) + { + this->value = value; + ctrlEdit *edit = GetCtrl(0); + std::stringstream ss; + ss << value; + edit->SetText(ss.str()); + } +} + +/////////////////////////////////////////////////////////////////////////////// +/** + * zeichnet das Fenster. + * + * @todo muss alles überarbeitet werden + * + * @author OLiver + */ +bool ctrlSpinbox::Draw_(void) +{ +// ctrlEdit *edit = GetCtrl(0); +// ctrl *buttonUp = GetCtrl(1); +// ctrl *buttonDown = GetCtrl(2); + + DrawControls(); + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +/** + * benachrichtigt das Parent ("OnChange") + * + * @author FloSoft + */ +void ctrlSpinbox::Notify() +{ + if(!notify || !parent) + return; + + parent->Msg_EditChange(GetID()); +} + +void ctrlSpinbox::SetFocus(bool focus) +{ + newfocus = focus; + GetCtrl(0)->SetFocus(focus); +} +void ctrlSpinbox::SetDisabled(bool disabled) +{ + this->disabled = disabled; + GetCtrl(0)->SetDisabled(disabled); + GetCtrl(1)->SetVisible(!disabled); + GetCtrl(2)->SetVisible(!disabled); +} +void ctrlSpinbox::SetNotify(bool notify) +{ + this->notify = notify; + GetCtrl(0)->SetNotify(notify); +} + +/////////////////////////////////////////////////////////////////////////////// +/** + * + * + * @author OLiver + */ +void ctrlSpinbox::Msg_PaintAfter() +{ + focus = newfocus; +} + +bool ctrlSpinbox::Msg_MouseMove(const MouseCoords& mc) +{ + return RelayMouseMessage(&Window::Msg_MouseMove, mc); +} + +/////////////////////////////////////////////////////////////////////////////// +/** + * Maustaste-gedrückt Callback + * + * @author OLiver + */ +bool ctrlSpinbox::Msg_LeftDown(const MouseCoords& mc) +{ + bool ret = RelayMouseMessage(&Window::Msg_LeftDown, mc); + if(Coll(mc.x, mc.y, GetX(), GetY(), width, height)) + { + SetFocus(true); + return ret; + } + else + return false; +} + +// vorläufig +bool ctrlSpinbox::Msg_LeftDown_After(const MouseCoords& mc) +{ +// RelayMouseMessage(&Window::Msg_LeftDown_After, mc); + + if(!Coll(mc.x, mc.y, GetX(), GetY(), width, height)) + SetFocus(false); + + return false; +} + +/////////////////////////////////////////////////////////////////////////////// +/** + * + * + * @author Divan + */ +bool ctrlSpinbox::Msg_WheelUp(const MouseCoords& mc) +{ + if ((newfocus = Coll(mc.x, mc.y, GetX(), GetY(), width, height)) + && !disabled) + { + Msg_ButtonClick(1); + return true; + } + else + return false; +} + +/////////////////////////////////////////////////////////////////////////////// +/** + * + * + * @author Divan + */ +bool ctrlSpinbox::Msg_WheelDown(const MouseCoords& mc) +{ + if ((newfocus = Coll(mc.x, mc.y, GetX(), GetY(), width, height)) + && !disabled) + { + Msg_ButtonClick(2); + return true; + } + else + return false; +} + +/////////////////////////////////////////////////////////////////////////////// +/** + * Taste-gedrückt Callback + * + * @author Divan + */ +bool ctrlSpinbox::Msg_KeyDown(const KeyEvent& ke) +{ + if (!focus) + return false; + + // First we let the edit process the key + RelayKeyboardMessage(&Window::Msg_KeyDown, ke); + + // And now let there only be a number + std::string text_in, text_out; + text_in = GetCtrl(0)->GetText(); + unsigned char l = text_in.size(); + bool bad_char_found = false; + if (l > 0) + { + for (unsigned char i = 0; i < l; ++i) + { + char c = text_in[i]; + // Because this function gets called after every + // keypress, there can only be 1 unwanted character + // in the text. So if we had one, all following + // characters are "good" + if (bad_char_found + || + (i == 0 && c == '-') + || + ( c >= '0' && c <= '9' ) + ) + { + text_out += c; + } + else + bad_char_found = true; + } + // Update the value and the edit text only if + // - text isn't only "-" (otherwise it would vanish because + // atoi makes a "0" of it) or + // - we really had to correct something. + // Otherwise we would prevent cursor movement. + int new_value = atoi(text_out.c_str()); + if (text_out != "-" && bad_char_found) + { + GetCtrl(0)->SetText(text_out); + SetValue(new_value); + } + else + if (new_value <= max && new_value >= min) + value = new_value; + Notify(); + } + return true; +} + +void ctrlSpinbox::Msg_ButtonClick(const unsigned int ctrl_id) +{ + switch(ctrl_id) + { + case 1: + { + SetValue(value+1); + Notify(); + } break; + case 2: + { + SetValue(value-1); + Notify(); + } break; + } +} === added file 'src/ctrlSpinbox.h' --- src/ctrlSpinbox.h 1970-01-01 00:00:00 +0000 +++ src/ctrlSpinbox.h 2009-07-22 12:14:59 +0000 @@ -0,0 +1,74 @@ +// $Id: ctrlEdit.h 5105 2009-03-29 10:10:02Z Divan $ +// +// Copyright (c) 2005-2009 Settlers Freaks (sf-team at siedler25.org) +// +// This file is part of Siedler II.5 RTTR. +// +// Siedler II.5 RTTR 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. +// +// Siedler II.5 RTTR 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 Siedler II.5 RTTR. If not, see . +#ifndef CTRLSPINBOX_H_INCLUDED +#define CTRLSPINBOX_H_INCLUDED + +#pragma once + +#include "Window.h" + +class ctrlSpinbox : public Window +{ +public: + ctrlSpinbox(Window *parent, unsigned int id, unsigned short x, unsigned short y, unsigned short width, unsigned short height, TextureColor tc, glArchivItem_Font *font, bool disabled, bool notify, int min, int max); + + const int GetValue(void) const { return value; } + void SetValue(const int value); + void SetMin(const int min) { this->min = min; } + void SetMax(const int max) { this->max = max; } + + void SetFocus(bool focus = true); + void SetDisabled(bool disabled = true); + void SetNotify(bool notify = true); + + virtual void Msg_PaintAfter(); + virtual bool Msg_MouseMove(const MouseCoords& mc); + virtual bool Msg_LeftDown(const MouseCoords& mc); + virtual bool Msg_LeftDown_After(const MouseCoords& mc); + virtual bool Msg_LeftUp(const MouseCoords& mc) { return RelayMouseMessage(&Window::Msg_LeftUp, mc); } + virtual bool Msg_WheelUp(const MouseCoords& mc); + virtual bool Msg_WheelDown(const MouseCoords& mc); + virtual bool Msg_KeyDown(const KeyEvent& ke); + virtual void Msg_EditChange(const unsigned int ctrl_id) { parent->Msg_EditChange(id); } + virtual void Msg_ButtonClick(const unsigned int ctrl_id); + +protected: + virtual bool Draw_(void); + +private: + void Notify(void); + +private: + unsigned short width; + unsigned short height; + + TextureColor tc; + glArchivItem_Font *font; + bool password; + bool disabled; + bool focus; + bool newfocus; + bool notify; + + int value, min, max; + +}; + +#endif // !CTRLSPINBOX_H_INCLUDED + === modified file 'src/dskGameInterface.cpp' --- src/dskGameInterface.cpp 2009-07-13 22:00:41 +0000 +++ src/dskGameInterface.cpp 2009-07-22 21:38:30 +0000 @@ -38,6 +38,11 @@ #include "LobbyClient.h" #include "ctrlButton.h" #include "GameMessages.h" +#include "const_enhancements.h" +#include "Enhancements.h" +#include "enhOptions.h" +#include +#include #include "iwChat.h" #include "iwHQ.h" @@ -237,7 +242,9 @@ if(road.mode) { // in "richtige" Map-Koordinaten Konvertieren, den aktuellen selektierten Punkt - unsigned short cselx=gwv->GetSelX(),csely = gwv->GetSelY(); + int cselx=gwv->GetSelX(),csely = gwv->GetSelY(); + // Um auf Wasserweglängenbegrenzun reagieren zu können: + int cselx2 = cselx, csely2 = csely; if(cselx == road.point_x && csely == road.point_y) { @@ -265,18 +272,27 @@ else { if(BuildRoadPart(cselx,csely,1)) - CommandBuildRoad(); + { + // Ist der Zielpunkt der gleiche geblieben? + if (cselx2==cselx && csely2==csely) + CommandBuildRoad(); + } else - ShowRoadWindow(mc.x,mc.y); + if (cselx2==cselx && csely2==csely) + ShowRoadWindow(mc.x,mc.y); } } // Wurde auf eine Flagge geklickt und ist diese Flagge nicht der Weganfangspunkt? else if(gwv->GetNO(cselx,csely)->GetType() == NOP_FLAG && !(cselx == road.start_x && csely == road.start_y)) { if(BuildRoadPart(cselx,csely,1)) - CommandBuildRoad(); + { + if (cselx2==cselx && csely2==csely) + CommandBuildRoad(); + } else - ShowRoadWindow(mc.x,mc.y); + if (cselx2==cselx && csely2==csely) + ShowRoadWindow(mc.x,mc.y); } else @@ -658,7 +674,7 @@ * * @author OLiver */ -bool dskGameInterface::BuildRoadPart(const int cselx, const int csely,bool end) +bool dskGameInterface::BuildRoadPart(int &cselx, int &csely,bool end) { std::vector new_route; bool path_found = gwv->FindRoadPath(road.point_x,road.point_y,cselx,csely,new_route, road.mode == RM_BOAT); @@ -666,6 +682,20 @@ // Weg gefunden? if(!path_found) return false; + + // Test on water way length + if(road.mode == RM_BOAT) + { + unsigned short max_length = GAMECLIENT.GetGGS().enhancements.Get(ENH_WATERWAY_LENGTH); + unsigned short length = road.route.size() + new_route.size(); + // max_length == 0 heißt beliebig lang, ansonsten + // Weg zurechtstutzen. + if (max_length > 0) while(length > max_length) + { + new_route.pop_back(); + --length; + } + } // Weg (visuell) bauen for(unsigned i = 0;iGetPointA(road.point_x,road.point_y, new_route[i]); gwv->CalcRoad(road.point_x,road.point_y,GAMECLIENT.GetPlayerID()); } + // Zielpunkt updaten (für Wasserweg) + cselx = road.point_x; + csely = road.point_y; road.route.insert(road.route.end(), new_route.begin(), new_route.end()); @@ -814,10 +847,11 @@ void dskGameInterface::CI_GGSChanged(const GlobalGameSettings& ggs) { - // TODO: print what has changed - char text[256]; - snprintf(text, 256, _("Note: Game settings changed by the server%s"),""); - messenger.AddMessage("", 0, CD_SYSTEM, text); + const std::string text = _("Game settings changed:") + + ggs.enhancements.CompareMessage(GAMECLIENT.GetGGS().enhancements); + char from[256]; + snprintf(from, 256, _("<%s> "), _("SYSTEM")); + messenger.AddMessage(from, COLOR_GREY, CD_SYSTEM, text.c_str()); } void dskGameInterface::CI_Chat(const unsigned player_id, const ChatDestination cd, const std::string& msg) === modified file 'src/dskGameInterface.h' --- src/dskGameInterface.h 2009-06-21 22:00:39 +0000 +++ src/dskGameInterface.h 2009-07-22 12:14:59 +0000 @@ -119,7 +119,10 @@ friend class RoadSegment; // Sucht einen Weg von road_point_x/y zu cselx/y und baut ihn ( nur visuell ) - bool BuildRoadPart(const int cselx, const int csely,bool end); + // Bei Wasserwegen kann die Reichweite nicht bis zum gewünschten + // Punkt reichen. Dann werden die Zielkoordinaten geändert, daher + // call-by-reference + bool BuildRoadPart(int &cselx, int &csely, bool end); // Prft, ob x;y auf der bereits gebauten Strecke liegt und gibt die Position+1 zurck vom Startpunkt der Strecke aus // wenn der Punkt nicht draufliegt, kommt 0 zurck unsigned TestBuiltRoad(const int x, const int y); === modified file 'src/dskHostGame.cpp' --- src/dskHostGame.cpp 2009-07-11 22:00:41 +0000 +++ src/dskHostGame.cpp 2009-07-23 09:27:09 +0000 @@ -34,6 +34,10 @@ #include "dskLobby.h" #include "iwMsgbox.h" +#include "iwEnhancements.h" +#include +#include + /////////////////////////////////////////////////////////////////////////////// // Makros / Defines #if defined _WIN32 && defined _DEBUG && defined _MSC_VER @@ -50,7 +54,7 @@ * @author FloSoft */ dskHostGame::dskHostGame() : - Desktop(LOADER.GetImageN("setup015", 0)), temppunkte(1000) + Desktop(LOADER.GetImageN("setup015", 0)), temppunkte(1000), ggs_changed(false) { // Kartenname AddText(0, 400, 5,GAMECLIENT.GetGameName().c_str(), COLOR_YELLOW, glArchivItem_Font::DF_CENTER, LargeFont); @@ -159,7 +163,9 @@ UpdatePlayerRow(i-1); //// GGS aktualisieren, zum ersten Mal - this->CI_GGSChanged(GameClient::inst().GetGGS()); + // unnötig, da der GameClient sich gleich beim Server anmeldet und + // dann sowieso die Info bekommt. + LOBBYCLIENT.SetInterface(this); if(LOBBYCLIENT.LoggedIn()) @@ -449,6 +455,22 @@ WindowManager::inst().Show(new iwMsgbox(_("Error"), _("Game can only be started as soon as everybody has a unique color,everyone is ready and all free slots are closed."), this, MSB_OK, MSB_EXCLAMATIONRED, 10)); } } break; + // Enhancements + case 22: + { + iwEnhancements::editing_policy policy; + if (GAMECLIENT.IsHost()) + { + policy = (GAMECLIENT.IsSavegame() ? iwEnhancements::HOSTMENUINGAME : iwEnhancements::HOSTMENU); + } + else + { + policy = iwEnhancements::READONLY; + } + WindowManager::inst().Show(new iwEnhancements( + &(ggs.enhancements), + policy)); + } break; case 102: { CreateMapPreview(); @@ -715,6 +737,19 @@ void dskHostGame::CI_GGSChanged(const GlobalGameSettings& ggs) { + std::string text = ggs.enhancements.CompareMessage( + GAMECLIENT.GetGGS().enhancements); + + if (text != "") + { + text = ( ggs_changed ? _("Game settings changed:") + : _("Server settings (non-default):")) + + text; + + GetCtrl(1)->AddMessage("", _("SYSTEM"), COLOR_GREY, text.c_str(), 0xFFFFFF00); + } + + ggs_changed = true; this->ggs = ggs; // Geschwindigkeit === modified file 'src/dskHostGame.h' --- src/dskHostGame.h 2009-05-26 22:00:35 +0000 +++ src/dskHostGame.h 2009-07-22 21:38:30 +0000 @@ -90,6 +90,7 @@ private: int temppunkte; // TODO - wegmachen und durch korrekte punkte ersetzen! + bool ggs_changed; // Abfangen der ersten enhancement-options Nachricht glArchivItem_Bitmap_Raw preview; GlobalGameSettings ggs; }; === modified file 'src/dskOptions.cpp' --- src/dskOptions.cpp 2009-07-13 22:00:41 +0000 +++ src/dskOptions.cpp 2009-07-22 12:41:17 +0000 @@ -31,6 +31,7 @@ #include "dskMainMenu.h" #include "iwMusicPlayer.h" +#include "iwEnhancements.h" #include "languages.h" @@ -447,6 +448,12 @@ WindowManager::inst().Switch(new dskMainMenu); } break; + case 14: // "Enhancements" + { + WindowManager::inst().Show(new iwEnhancements( + &(SETTINGS.enhancements.preferred), + iwEnhancements::ALL)); + } break; } } === added file 'src/enhOptions.cpp' --- src/enhOptions.cpp 1970-01-01 00:00:00 +0000 +++ src/enhOptions.cpp 2009-07-22 21:38:30 +0000 @@ -0,0 +1,150 @@ +// $Id: optOption.h 4830 2009-05-07 18:59:21Z Divan $ +// +// Copyright (c) 2005-2009 Settlers Freaks (sf-team at siedler25.org) +// +// This file is part of Siedler II.5 RTTR. +// +// Siedler II.5 RTTR 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. +// +// Siedler II.5 RTTR 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 Siedler II.5 RTTR. If not, see . + +#include +#include +#include + +#include "main.h" +#include "enhOptions.h" +#include "Enhancements.h" + +////////////////////////////////////////////////// +// Class enhOptions + +enhOptions::enhOptions(void) +{ +} + + +void enhOptions::Serialize(Serializer &ser) const +{ + ser.PushUnsignedChar(values.size()); + + for (std::map::const_iterator it = values.begin(); it != values.end(); ++it) + { + ser.PushUnsignedInt(it->first); + ser.PushSignedInt(it->second); + } +} + +void enhOptions::Deserialize(Serializer & ser) +{ + values.clear(); + + unsigned char count = ser.PopUnsignedChar(); + + unsigned int id; int value; + for(unsigned char i=0; i < count; ++i) + { + id = ser.PopUnsignedInt(); + value = ser.PopSignedInt(); + if (ENHANCEMENTS.isValidId(id)) + { + Set(id, value); + } + else + { + LOG.lprintf("Warning: The game settings either loaded from Savegame or received from server contain an unknown option with ID %d (and value %d).\n", id, value); + } + } +} + +std::queue > > enhOptions::Compare(const enhOptions& other) const +{ + std::queue > > result; + int oldvalue, newvalue; + unsigned int id; + for (unsigned short i = 0; i < ENHANCEMENTS.size(); ++i) + { + id = ENHANCEMENTS.by_order(i).id; + oldvalue = other.Get(id); + newvalue = Get(id); + if (oldvalue != newvalue) + result.push(std::make_pair(id, std::make_pair(oldvalue, newvalue))); + } + return result; +} + +std::string enhOptions::CompareMessage(const enhOptions &other) const +{ + // To send a message to the chat if enhancement options were changed + // for they are not visible otherwise. + // Sorry, that's actually a GUI function. If we wanted to place it + // in the GUI code we had to place it twice, in dskGameInterface and + // dskHostGame. + std::string text = ""; + std::queue > > diff = Compare(other); + if (!diff.empty()) + { + std::pair > entry; + enhOption enh; + while (!diff.empty()) + { + entry = diff.front(); diff.pop(); + enh = ENHANCEMENTS.by_id(entry.first); + text += "\n\"" + enh.name + "\" from \"" + + ENHANCEMENTS.GetValueAsString(enh.id, entry.second.first) + + "\" to \"" + + ENHANCEMENTS.GetValueAsString(enh.id, entry.second.second) + + "\""; + } + } + + return text; +} + +int enhOptions::Get(const unsigned int &id) const +{ + unsigned int id2 = values.find(id)->first; + if (id2 == id) + // if we have the option + { + return values.find(id)->second; + } + // if we don't, return default + else + return ENHANCEMENTS.by_id(id).def; +} + +void enhOptions::Set(const unsigned int &id, int value) +{ + if (ENHANCEMENTS.isValidId(id)) + { + // Is the value valid? + if (value < ENHANCEMENTS.by_id(id).min + || value > ENHANCEMENTS.by_id(id).max) + { + value = ENHANCEMENTS.by_id(id).def; + } + + std::map::iterator it; + it = values.find(id); + if (it->first == id) + // if we have the option + { + it->second = value; + } + // if we don't, insert it + else + { + values.insert(std::make_pair(id, value)); + } + } +} === added file 'src/enhOptions.h' --- src/enhOptions.h 1970-01-01 00:00:00 +0000 +++ src/enhOptions.h 2009-07-23 09:27:09 +0000 @@ -0,0 +1,95 @@ +// $Id: optOption.h 4830 2009-05-07 18:59:21Z Divan $ +// +// Copyright (c) 2005-2009 Settlers Freaks (sf-team at siedler25.org) +// +// This file is part of Siedler II.5 RTTR. +// +// Siedler II.5 RTTR 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. +// +// Siedler II.5 RTTR 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 +// aint with Siedler II.5 RTTR. If not, see . + +#ifndef ENH_OPTIONS_H_INCLUDED +#define ENH_OPTIONS_H_INCLUDED + +#include +#include +#include +#include +#include "main.h" +#include "Serializer.h" + +enum OptType +{ + ENH_OPT_BOOL, + ENH_OPT_SELECT, + ENH_OPT_INT +}; + +enum OptGroup +{ + ENH_OPT_NONE, + ENH_OPT_MILITARY, + ENH_OPT_ECONOMY, + ENH_OPT_CONSTRUCTION, + ENH_OPT_SAILING +}; + +// struct for an enhancement option + +// See const_enhancements.cpp for intended usage +// and to define a new option. + +struct enhOption +{ + unsigned int id; // an identifyer defined above + OptType type; // one of boolean, choice, numerical + int def; // default value + int original; // original behaviour by this value + int min; // for numerical values + int max; // == + std::string name; // a short name + std::string id_name; // only lower case, numbers, underscore + std::string description; // a longer description, explaining + // possible values if necessary + bool ingameChangeable; // may this option be changed + // while playing? + OptGroup group; // one of the groups defined above + std::vector selections; // the strings +}; + + +// container class +class enhOptions +{ +public: + // Constructor + enhOptions(void); + + void Serialize(Serializer &serializer) const; + void Deserialize(Serializer &serializer); + + // To keep track of changes + // returns queue of nested pairs: < id, < old value, new value > > + std::queue > > Compare(const enhOptions& other) const; + // returns a message that informs players of the changes + std::string CompareMessage(const enhOptions &other) const; + + int Get(const unsigned int &id) const; + void Set(const unsigned int &id, int value); + +private: + bool isValidId(const unsigned int &id); + +protected: + std::map values; +}; +#endif // !ENH_OPTION_H_INCLUDED === modified file 'src/glArchivItem_Font.cpp' --- src/glArchivItem_Font.cpp 2009-07-11 22:00:41 +0000 +++ src/glArchivItem_Font.cpp 2009-07-21 22:21:02 +0000 @@ -344,8 +344,8 @@ // Leerzeichen, Umbruch oder ende? if(text[i] == '\n' || text[i] == ' ' || i == length) { - // Passt das letzte Wort mit auf die Zeile? (bzw bei newline immer neue zeile anfangen) - if(text[i] != '\n' && word_width + line_width <= ((wi.count==1) ? primary_width : secondary_width)) + // Passt das letzte Wort mit auf die Zeile? + if(word_width + line_width <= ((wi.count==1) ? primary_width : secondary_width)) { // Länge des Leerzeichens mit draufaddieren line_width += word_width; @@ -405,6 +405,14 @@ word_width = 0; } } + } + // Bei Newline immer neue Zeile anfangen, aber erst jetzt und nicht schon oben! + if(text[i] == '\n' && i < length-1) + { + word_start = i+1; + word_width = 0; + line_width = 0; + wi.positions[wi.count++] = word_start; } } else === added file 'src/iwEnhancements.cpp' --- src/iwEnhancements.cpp 1970-01-01 00:00:00 +0000 +++ src/iwEnhancements.cpp 2009-07-23 09:27:09 +0000 @@ -0,0 +1,327 @@ +// $Id: iwEnhancements.cpp 4800 2009-03-29 10:10:02Z Divan $ +// +// Copyright (c) 2005-2009 Settlers Freaks (sf-team at siedler25.org) +// +// This file is part of Siedler II.5 RTTR. +// +// Siedler II.5 RTTR 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. +// +// Siedler II.5 RTTR 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 Siedler II.5 RTTR. If not, see . + +/////////////////////////////////////////////////////////////////////////////// +// Header +#include "main.h" +#include "iwEnhancements.h" +#include "controls.h" + +#include "Enhancements.h" +#include "Settings.h" + +#include "GameServer.h" +#include "GameClient.h" +#include "GameCommands.h" +#include "GlobalVars.h" +#include "WindowManager.h" + +/////////////////////////////////////////////////////////////////////////////// +// Makros / Defines +#if defined _WIN32 && defined _DEBUG && defined _MSC_VER + #define new new(_NORMAL_BLOCK, THIS_FILE, __LINE__) + #undef THIS_FILE + static char THIS_FILE[] = __FILE__; +#endif + +/////////////////////////////////////////////////////////////////////////////// +/** + * Konstruktor von @p iwEnhancements. + * + * @author Divan + */ +iwEnhancements::iwEnhancements(enhOptions *original, const editing_policy policy) + : IngameWindow(CGI_ENHANCEMENTS, 0xFFFF, 0xFFFF, 700, 500, _("Game Settings"), + LOADER.GetImageN("resource", 41), + true /*(policy == ALL || policy == READONLY ? false : true)*/), + original(original), policy(policy), selection_id(0) +{ + switch(policy) + { + case HOSTMENU: + case HOSTMENUINGAME: + { + // make a local copy so we can apply changes later + enhancements = new enhOptions(*original); + } break; + case SERVERINGAME: + { + // we don't wan't the window opening this one have to include the GameClient stuff + enhancements = new enhOptions(GAMECLIENT.GetGGS().enhancements); + // Are we really allowed to change something or does someone want to trick us? + if (!GAMECLIENT.IsHost()) + this->policy = READONLY; + } break; + case ALL: + case READONLY: + { + // we don't need a copy + enhancements = original; + } break; + } + + // Buttons + switch(this->policy) + { + case HOSTMENU: + case HOSTMENUINGAME: + case SERVERINGAME: + { + AddTextButton(1, width - 220, height - 45 , 200, 22, TC_GREEN2, _("Apply Changes"),NormalFont); + AddTextButton(2, 20, height - 45 , 200, 22, TC_RED1, _("Discard Changes"),NormalFont); + } break; + case ALL: + case READONLY: + { + AddTextButton(2, width - 220, height - 45 , 200, 22, TC_GREEN2, _("Continue"),NormalFont); + } break; + } + + AddText(3,20,30,_("Modified:"), COLOR_YELLOW, 0, NormalFont); + AddText(4,width-230+20,30,_("Available:"), COLOR_YELLOW, 0, NormalFont); + + AddList(5,20,50,230-2*20,height-75-2*20, TC_GREY, NormalFont); + ctrlList *list_all = AddList(6,width-230+20,50,230-2*20,height-75-2*20, TC_GREY, NormalFont); + list_ids = new unsigned int[ENHANCEMENTS.size()]; + + enhOption enh; + for (unsigned int i = 0; i < ENHANCEMENTS.size(); ++i) + { + enh = ENHANCEMENTS.by_order(i); + list_all->AddString(_(enh.name)); + } + UpdateList(); + + name = AddMultiline(7, 230, 50, 240, 3*NormalFont->getHeight()+4 , TC_GREEN1, NormalFont, glArchivItem_Font::DF_LEFT | glArchivItem_Font::DF_TOP); + name->EnableBox(false); + def = AddMultiline(8, 230, 50+4*14, 240, 4*NormalFont->getHeight()+4 , TC_GREEN1, NormalFont, glArchivItem_Font::DF_LEFT | glArchivItem_Font::DF_TOP); + def->EnableBox(false); + text = AddText(9,230+2,50 + 9*14, _("Current value:"), COLOR_YELLOW, 0, NormalFont); + text->SetVisible(false); + check = AddCheckBox(100, 230, 50+10*14, 240, 22, TC_GREY, _("Enabled"), NormalFont); + check->SetVisible(false); + combo = AddComboBox(101, 230, 50+10*14, 240, 22, TC_GREY, NormalFont, height-50-10*14-30); + combo->SetVisible(false); + edit = AddSpinbox(102, 230, 50+10*14, 240, 22, TC_GREY, NormalFont, false, true); + edit->SetVisible(false); + desc = AddMultiline(13, 230, 50+13*14, 240, GetHeight()-65-50-11*14 , TC_GREEN1, NormalFont, glArchivItem_Font::DF_LEFT | glArchivItem_Font::DF_TOP); + +} + +/** + * Destructor von @p iwEnhancements. + * + * @author Divan + */ +iwEnhancements::~iwEnhancements() +{ + delete [] list_ids; + // If we made up an EnhOptions own instance, destroy it! + // We could as well check the value of policy here + if (original != enhancements) + if(enhancements != NULL) + delete enhancements; +} + +/** + * Message handler for value changing + * + * @author Divan + */ +void iwEnhancements::Msg_CheckboxChange(const unsigned int ctrl_id, const bool check) +{ + enhancements->Set(selection_id, (check ? 1 : 0)); + this->check->SetText(check ? _("Enabled") : _("Disabled")); + UpdateList(); +} +void iwEnhancements::Msg_ComboSelectItem(const unsigned int ctrl_id, const unsigned short selection) +{ + enhancements->Set(selection_id, selection); + UpdateList(); +} +void iwEnhancements::Msg_EditChange(const unsigned int ctrl_id) +{ + enhancements->Set(selection_id, edit->GetValue()); + UpdateList(); +} + +/** + * Msg_ButtonClick + * + * @author Divan + */ +void iwEnhancements::Msg_ButtonClick(const unsigned int ctrl_id) +{ + switch(ctrl_id) + { + // Save Changes + case 1: + { + // Submit changes + if (policy >= HOSTMENU && policy <= HOSTMENUINGAME) + { + // Don't overwrite GGS now, but wait for the server message + GlobalGameSettings ggs = GAMECLIENT.GetGGS(); + ggs.enhancements = *enhancements; + GAMESERVER.ChangeGlobalGameSettings(ggs); + } + else if (policy == SERVERINGAME) + { + // Also just inform GAMESERVER, which sends the + // message to all players. + GlobalGameSettings ggs = GAMECLIENT.GetGGS(); + ggs.enhancements = *enhancements; + GAMESERVER.ChangeGlobalGameSettings(ggs); + } + Close(); + } break; + // Discard Changes + case 2: + { + Close(); + } break; + } +} + +/** + * Message handler for selecting an item in the lists + * + * @author Divan + */ +void iwEnhancements::Msg_ListSelectItem(const unsigned int ctrl_id, const unsigned short selection) +{ + ctrlList * list = GetCtrl(ctrl_id); + switch(ctrl_id) + { + case 6: /*list of all available options*/ + { + // Hide all editing controls, + name->DeleteAllItems(); + def->DeleteAllItems(); + text->SetVisible(false); + desc->DeleteAllItems(); + check->SetVisible(false); + combo->DeleteAllItems(); + combo->SetVisible(false); + edit->SetVisible(false); + // Did the user click on an option? + if (selection < list->GetLineCount()) + { + enhOption enh = ENHANCEMENTS.by_order(selection); + selection_id = enh.id; + const int value = enhancements->Get(selection_id); + + text->SetVisible(true); + name->AddText(_(enh.name), COLOR_YELLOW); + desc->AddText(_(enh.description), COLOR_YELLOW); + + bool isChangeable = + (policy < READONLY) + && + (policy <= HOSTMENU + || + enh.ingameChangeable + ); + check->SetReadOnly(!isChangeable); + combo->SetReadOnly(!isChangeable); + edit->SetDisabled(!isChangeable); + + text->SetColor(isChangeable ? COLOR_YELLOW : COLOR_GREY); + def->AddText(std::string(_("Default") + std::string(": ")) + ENHANCEMENTS.GetValueAsString(selection_id, enh.def), COLOR_YELLOW); + if (enh.def != enh.original) + def->AddText(std::string(_("Settlers II") + std::string(": ")) + ENHANCEMENTS.GetValueAsString(selection_id, enh.original), COLOR_YELLOW); + else + def->AddText("", COLOR_YELLOW); + + // Activate only the needed controls + switch(enh.type) + { + case ENH_OPT_BOOL: + { + check->SetCheck(value == 1); + check->SetText(value == 1 ? _("Enabled") : _("Disabled")); + check->SetVisible(true); + } break; + case ENH_OPT_SELECT: + { + assert(enh.max >= 0); + for(int j = 0; j <= enh.max; ++j) + combo->AddString(_(enh.selections[j])); + combo->SetSelection(value); + combo->SetVisible(true); + } break; + case ENH_OPT_INT: + { + def->AddText(std::string(_("Range") + std::string(": ")) + ENHANCEMENTS.GetValueAsString(selection_id, enh.min) + " - " + ENHANCEMENTS.GetValueAsString(selection_id, enh.max), COLOR_YELLOW); + edit->SetMin(enh.min); + edit->SetMax(enh.max); + edit->SetValue(value); + edit->SetVisible(true); + } break; + } + } + else //deselected + selection_id = 0; + } break; + case 5: /*list of modified options*/ + { + if (selection < list->GetLineCount()) + { + enhOption enh = ENHANCEMENTS.by_id(list_ids[selection / 2]); + selection_id = enh.id; + + for (unsigned int i = 0; i < ENHANCEMENTS.size(); ++i) + { + if (ENHANCEMENTS.by_order(i).id == selection_id) + { + Msg_ListSelectItem(6, i); + GetCtrl(6)->SetSelection(i); + break; + } + } + list->SetSelection(2 * (selection / 2)); + } + } break; + } +} + +/** + * Updates the left lists depending on current option values / group + * + * @author Divan + */ +void iwEnhancements::UpdateList() +{ + ctrlList * list = GetCtrl(5); // left list + list->DeleteAllItems(); + + enhOption enh; + for (unsigned int i = 0; i < ENHANCEMENTS.size(); ++i) + { + enh = ENHANCEMENTS.by_order(i); + const int value = enhancements->Get(enh.id); + if (value != enh.original) + { + list_ids[list->GetLineCount()/2] = enh.id; + list->AddString(_(enh.name + ":")); + list->AddString(" " + ENHANCEMENTS.GetValueAsString(enh.id, value)); + } + } +} + === added file 'src/iwEnhancements.h' --- src/iwEnhancements.h 1970-01-01 00:00:00 +0000 +++ src/iwEnhancements.h 2009-07-22 12:14:59 +0000 @@ -0,0 +1,74 @@ +// $Id: iwEnhancements.h 4800 2009-05-11 10:10:02Z Divan $ +// +// Copyright (c) 2005-2009 Settlers Freaks (sf-team at siedler25.org) +// +// This file is part of Siedler II.5 RTTR. +// +// Siedler II.5 RTTR 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. +// +// Siedler II.5 RTTR 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 Siedler II.5 RTTR. If not, see . +#ifndef iwENHANCEMENTS_H_INCLUDED +#define iwENHANCEMENTS_H_INCLUDED + +#pragma once + +#include "IngameWindow.h" +#include "enhOptions.h" +#include "dskHostGame.h" + +class iwEnhancements : public IngameWindow +{ +public: + enum editing_policy + { + ALL, + HOSTMENU, + HOSTMENUINGAME, + SERVERINGAME, + READONLY + }; + +public: + iwEnhancements(enhOptions * original = NULL, + const editing_policy policy = READONLY); + ~iwEnhancements(void); + +private: + void SetText(const std::string& text, unsigned int color, bool button); + + void Msg_CheckboxChange(const unsigned int ctrl_id, const bool check); + void Msg_ComboSelectItem(const unsigned int ctrl_id, const unsigned short selection); + void Msg_EditChange(const unsigned int ctrl_id); + void Msg_ButtonClick(const unsigned int ctrl_id); + void Msg_ListSelectItem(const unsigned int ctrl_id, const unsigned short selection); + +private: + void UpdateList(); + +protected: + enhOptions *enhancements, *original; + editing_policy policy; + + unsigned int selection_id; + ctrlMultiline * name; + ctrlMultiline * desc; + ctrlMultiline * def; + ctrlText * text; + + ctrlCheck * check; + ctrlComboBox * combo; + ctrlSpinbox * edit; + + unsigned int * list_ids; //stores the ids of the options in the left list (the modified ones) +}; + +#endif // !iwENHANCEMENTS_H_INCLUDED === modified file 'src/iwMainMenu.cpp' --- src/iwMainMenu.cpp 2009-07-09 22:00:40 +0000 +++ src/iwMainMenu.cpp 2009-07-22 12:14:59 +0000 @@ -36,6 +36,7 @@ #include "iwBuildingProductivities.h" #include "iwStatistics.h" #include "iwDiplomacy.h" +#include "iwEnhancements.h" /////////////////////////////////////////////////////////////////////////////// // Makros / Defines @@ -80,8 +81,8 @@ AddImageButton( 10, 12, 166, 53, 44, TC_GREY, LOADER.GetImageN("io", 24), _("Series sequence")); // Diplomatie (todo: besseres Bild suchen) AddImageButton( 11, 68, 166, 53, 44, TC_GREY, LOADER.GetImageN("io", 190), _("Diplomacy")); - //// Schiffe - //AddImageButton( 9, 124, 118, 53, 44, TC_GREY, LOADER.GetImageN("io", 175), _("Ship register")); + // Enhancement options (todo: auch Bild finden) + AddImageButton( 12, 124, 166, 53, 44, TC_GREY, LOADER.GetImageN("io", 79), _("Enhancements")); // Optionen AddImageButton(30, 12, 231, 165, 32, TC_GREY, LOADER.GetImageN("io", 37), _("Options")); @@ -135,6 +136,12 @@ { WindowManager::inst().Show(new iwDiplomacy); } break; + case 12: // Enhancement + { + // The window checks if we are the host by itself + // and if so disallows modifications. + WindowManager::inst().Show(new iwEnhancements(NULL, iwEnhancements::SERVERINGAME)); + } break; case 30: // Optionen === modified file 'win32/vs2008/s25client.vcproj' --- win32/vs2008/s25client.vcproj 2009-07-15 22:00:51 +0000 +++ win32/vs2008/s25client.vcproj 2009-07-22 13:25:34 +0000 @@ -253,6 +253,14 @@ RelativePath="..\..\src\WindowManager.h" > + + + + @@ -405,6 +413,14 @@ > + + + + @@ -688,6 +704,14 @@ > + + + + @@ -1138,6 +1162,22 @@ > + + + + + + + +