summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2012-03-04 16:32:40 +0300
committerAndrei Karas <akaras@inbox.ru>2012-03-04 16:33:19 +0300
commit8fd450f698f8277eb8348da914d3dcbc11890ea6 (patch)
treeebaddac087d5e5b29f23a2aa01dd2758c3b8f68a /src
parentc6d7f7ed3d6d7827b820670faf6c48f0689fd5c2 (diff)
parentf74202392745923f9ce372a6bdcd0a45db6bcd08 (diff)
downloadplus-8fd450f698f8277eb8348da914d3dcbc11890ea6.tar.gz
plus-8fd450f698f8277eb8348da914d3dcbc11890ea6.tar.bz2
plus-8fd450f698f8277eb8348da914d3dcbc11890ea6.tar.xz
plus-8fd450f698f8277eb8348da914d3dcbc11890ea6.zip
Merge branch 'master' into stripped
Conflicts: configure.ac data/Makefile.am data/fonts/liberationsans-bold.ttf data/fonts/liberationsans.ttf data/fonts/liberationsansmono-bold.ttf data/fonts/liberationsansmono.ttf data/themes/redandblack/CMakeLists.txt data/themes/redandblack/Makefile.am po/cs.po po/de.po po/es.po po/fi.po po/fr.po po/id.po po/ja.po po/manaplus.pot po/nl_BE.po po/pl.po po/pt.po po/pt_BR.po po/ru.po po/zh_CN.po src/guichan/color.cpp src/guichan/defaultfont.cpp src/guichan/focushandler.cpp src/guichan/include/guichan/actionlistener.hpp src/guichan/include/guichan/deathlistener.hpp src/guichan/include/guichan/focushandler.hpp src/guichan/include/guichan/focuslistener.hpp src/guichan/include/guichan/graphics.hpp src/guichan/include/guichan/keylistener.hpp src/guichan/include/guichan/listmodel.hpp src/guichan/include/guichan/mouselistener.hpp src/guichan/include/guichan/sdl/sdlpixel.hpp src/guichan/include/guichan/widget.hpp src/guichan/include/guichan/widgetlistener.hpp src/guichan/include/guichan/widgets/listbox.hpp src/guichan/include/guichan/widgets/slider.hpp src/guichan/sdl/sdlgraphics.cpp src/guichan/sdl/sdlimage.cpp src/guichan/widgets/scrollarea.cpp src/guichan/widgets/slider.cpp src/guichan/widgets/tabbedarea.cpp src/guichan/widgets/textbox.cpp src/guichan/widgets/window.cpp src/net/manaserv/attributes.cpp src/net/manaserv/beinghandler.cpp src/net/manaserv/charhandler.cpp src/net/manaserv/gamehandler.h src/net/manaserv/inventoryhandler.cpp src/net/manaserv/inventoryhandler.h src/net/manaserv/itemhandler.cpp src/net/manaserv/loginhandler.cpp src/net/manaserv/network.cpp
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt6
-rw-r--r--src/Makefile.am6
-rw-r--r--src/actorspritelistener.h3
-rw-r--r--src/actorspritemanager.cpp6
-rw-r--r--src/being.cpp8
-rw-r--r--src/client.cpp62
-rw-r--r--src/client.h6
-rw-r--r--src/commandhandler.cpp14
-rw-r--r--src/commandhandler.h5
-rw-r--r--src/configlistener.h3
-rw-r--r--src/configuration.cpp71
-rw-r--r--src/configuration.h2
-rw-r--r--src/defaults.cpp15
-rw-r--r--src/effectmanager.h1
-rw-r--r--src/equipment.h5
-rw-r--r--src/game.cpp22
-rw-r--r--src/graphics.cpp23
-rw-r--r--src/graphics.h3
-rw-r--r--src/graphicsvertexes.h3
-rw-r--r--src/gui/changeemaildialog.cpp3
-rw-r--r--src/gui/changepassworddialog.cpp3
-rw-r--r--src/gui/charcreatedialog.cpp14
-rw-r--r--src/gui/charselectdialog.cpp2
-rw-r--r--src/gui/chatwindow.cpp4
-rw-r--r--src/gui/confirmdialog.cpp2
-rw-r--r--src/gui/debugwindow.cpp2
-rw-r--r--src/gui/editserverdialog.cpp5
-rw-r--r--src/gui/editserverdialog.h3
-rw-r--r--src/gui/equipmentwindow.cpp10
-rw-r--r--src/gui/itempopup.cpp2
-rw-r--r--src/gui/minimap.cpp46
-rw-r--r--src/gui/minimap.h2
-rw-r--r--src/gui/npcdialog.cpp16
-rw-r--r--src/gui/npcdialog.h2
-rw-r--r--src/gui/okdialog.cpp10
-rw-r--r--src/gui/okdialog.h11
-rw-r--r--src/gui/outfitwindow.cpp2
-rw-r--r--src/gui/popupmenu.cpp39
-rw-r--r--src/gui/popupmenu.h2
-rw-r--r--src/gui/register.cpp2
-rw-r--r--src/gui/sdlinput.h3
-rw-r--r--src/gui/serverdialog.cpp4
-rw-r--r--src/gui/setup.cpp2
-rw-r--r--src/gui/setup_audio.cpp226
-rw-r--r--src/gui/setup_audio.h19
-rw-r--r--src/gui/setup_joystick.cpp31
-rw-r--r--src/gui/setup_keyboard.cpp2
-rw-r--r--src/gui/setup_other.cpp5
-rw-r--r--src/gui/setup_relations.cpp8
-rw-r--r--src/gui/setup_theme.cpp33
-rw-r--r--src/gui/setup_video.cpp246
-rw-r--r--src/gui/setup_video.h30
-rw-r--r--src/gui/setup_visual.cpp118
-rw-r--r--src/gui/setup_visual.h50
-rw-r--r--src/gui/shopwindow.cpp2
-rw-r--r--src/gui/socialwindow.cpp6
-rw-r--r--src/gui/textcommandeditor.cpp6
-rw-r--r--src/gui/theme.cpp19
-rw-r--r--src/gui/theme.h2
-rw-r--r--src/gui/unregisterdialog.cpp3
-rw-r--r--src/gui/updaterwindow.cpp32
-rw-r--r--src/gui/viewport.cpp23
-rw-r--r--src/gui/viewport.h2
-rw-r--r--src/gui/whoisonline.cpp8
-rw-r--r--src/gui/widgets/avatarlistbox.cpp3
-rw-r--r--src/gui/widgets/browserbox.cpp22
-rw-r--r--src/gui/widgets/browserbox.h3
-rw-r--r--src/gui/widgets/button.cpp190
-rw-r--r--src/gui/widgets/button.h31
-rw-r--r--src/gui/widgets/chattab.cpp21
-rw-r--r--src/gui/widgets/chattab.h2
-rw-r--r--src/gui/widgets/flowcontainer.h3
-rw-r--r--src/gui/widgets/guildchattab.cpp6
-rw-r--r--src/gui/widgets/guildchattab.h2
-rw-r--r--src/gui/widgets/guitable.cpp9
-rw-r--r--src/gui/widgets/horizontcontainer.cpp7
-rw-r--r--src/gui/widgets/horizontcontainer.h2
-rw-r--r--src/gui/widgets/linkhandler.h3
-rw-r--r--src/gui/widgets/listbox.cpp10
-rw-r--r--src/gui/widgets/listbox.h2
-rw-r--r--src/gui/widgets/namesmodel.cpp51
-rw-r--r--src/gui/widgets/namesmodel.h51
-rw-r--r--src/gui/widgets/setupitem.cpp416
-rw-r--r--src/gui/widgets/setupitem.h149
-rw-r--r--src/gui/widgets/setuptabscroll.cpp9
-rw-r--r--src/gui/widgets/setuptabscroll.h4
-rw-r--r--src/gui/widgets/sliderlist.cpp216
-rw-r--r--src/gui/widgets/sliderlist.h83
-rw-r--r--src/gui/widgets/tablemodel.h3
-rw-r--r--src/gui/widgets/textfield.cpp2
-rw-r--r--src/gui/worldselectdialog.cpp3
-rw-r--r--src/guildmanager.cpp6
-rw-r--r--src/localplayer.cpp23
-rw-r--r--src/logger.cpp31
-rw-r--r--src/logger.h13
-rw-r--r--src/main.h4
-rw-r--r--src/map.cpp4
-rw-r--r--src/net/ea/charserverhandler.cpp4
-rw-r--r--src/net/ea/gamehandler.cpp2
-rw-r--r--src/net/ea/gui/guildtab.cpp6
-rw-r--r--src/net/ea/gui/guildtab.h2
-rw-r--r--src/net/ea/gui/partytab.cpp5
-rw-r--r--src/net/ea/gui/partytab.h2
-rw-r--r--src/net/ea/playerhandler.cpp13
-rw-r--r--src/net/manaserv/attributes.cpp412
-rw-r--r--src/net/manaserv/beinghandler.cpp388
-rw-r--r--src/net/manaserv/charhandler.cpp407
-rw-r--r--src/net/manaserv/gamehandler.h72
-rw-r--r--src/net/manaserv/inventoryhandler.cpp220
-rw-r--r--src/net/manaserv/inventoryhandler.h104
-rw-r--r--src/net/manaserv/itemhandler.cpp91
-rw-r--r--src/net/manaserv/loginhandler.cpp499
-rw-r--r--src/net/manaserv/network.cpp177
-rw-r--r--src/net/messagein.cpp2
-rw-r--r--src/net/tmwa/network.cpp4
-rw-r--r--src/net/tmwa/playerhandler.cpp4
-rw-r--r--src/opengl1graphics.cpp85
-rw-r--r--src/opengl1graphics.h13
-rw-r--r--src/openglgraphics.cpp114
-rw-r--r--src/openglgraphics.h17
-rw-r--r--src/particlecontainer.h3
-rw-r--r--src/particleemitterprop.h1
-rw-r--r--src/resources/action.cpp13
-rw-r--r--src/resources/action.h6
-rw-r--r--src/resources/animation.cpp14
-rw-r--r--src/resources/animation.h8
-rw-r--r--src/resources/image.cpp7
-rw-r--r--src/resources/image.h3
-rw-r--r--src/resources/spritedef.cpp22
-rw-r--r--src/resources/spritedef.h7
-rw-r--r--src/sound.cpp16
-rw-r--r--src/sound.h11
-rw-r--r--src/sprite.h3
-rw-r--r--src/utils/checkutils.cpp2
-rw-r--r--src/utils/copynpaste.cpp10
-rw-r--r--src/utils/langs.cpp8
-rw-r--r--src/utils/mathutils.h7
-rw-r--r--src/utils/physfsrwops.cpp24
-rw-r--r--src/utils/process.cpp6
-rw-r--r--src/utils/stringutils.cpp6
140 files changed, 4808 insertions, 722 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4f54be8c4..ecb65c884 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -165,6 +165,8 @@ SET(SRCS
gui/widgets/listbox.cpp
gui/widgets/listbox.h
gui/widgets/mouseevent.h
+ gui/widgets/namesmodel.cpp
+ gui/widgets/namesmodel.h
gui/widgets/passwordfield.cpp
gui/widgets/passwordfield.h
gui/widgets/playerbox.cpp
@@ -195,6 +197,8 @@ SET(SRCS
gui/widgets/shortcutcontainer.h
gui/widgets/slider.cpp
gui/widgets/slider.h
+ gui/widgets/sliderlist.cpp
+ gui/widgets/sliderlist.h
gui/widgets/tab.cpp
gui/widgets/tab.h
gui/widgets/tabbedarea.cpp
@@ -325,6 +329,8 @@ SET(SRCS
gui/setup_players.h
gui/setup_video.cpp
gui/setup_video.h
+ gui/setup_visual.cpp
+ gui/setup_visual.h
gui/sdlfont.cpp
gui/sdlfont.h
gui/shopwindow.cpp
diff --git a/src/Makefile.am b/src/Makefile.am
index 189283fb9..8c3b333a4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -64,6 +64,8 @@ manaplus_SOURCES = gui/widgets/avatarlistbox.cpp \
gui/widgets/listbox.cpp \
gui/widgets/listbox.h \
gui/widgets/mouseevent.h \
+ gui/widgets/namesmodel.cpp \
+ gui/widgets/namesmodel.h \
gui/widgets/passwordfield.cpp \
gui/widgets/passwordfield.h \
gui/widgets/playerbox.cpp \
@@ -94,6 +96,8 @@ manaplus_SOURCES = gui/widgets/avatarlistbox.cpp \
gui/widgets/shortcutcontainer.h \
gui/widgets/slider.cpp \
gui/widgets/slider.h \
+ gui/widgets/sliderlist.cpp \
+ gui/widgets/sliderlist.h \
gui/widgets/tab.cpp \
gui/widgets/tab.h \
gui/widgets/tabbedarea.cpp \
@@ -224,6 +228,8 @@ manaplus_SOURCES = gui/widgets/avatarlistbox.cpp \
gui/setup_relations.h \
gui/setup_video.cpp \
gui/setup_video.h \
+ gui/setup_visual.cpp \
+ gui/setup_visual.h \
gui/sdlfont.cpp \
gui/sdlfont.h \
gui/shopwindow.cpp \
diff --git a/src/actorspritelistener.h b/src/actorspritelistener.h
index 314825fc7..7fdb99dc4 100644
--- a/src/actorspritelistener.h
+++ b/src/actorspritelistener.h
@@ -30,7 +30,8 @@ class ActorSpriteListener
/**
* Destructor.
*/
- virtual ~ActorSpriteListener() {}
+ virtual ~ActorSpriteListener()
+ { }
/**
* Called when the ActorSprite has been destroyed. The listener will
diff --git a/src/actorspritemanager.cpp b/src/actorspritemanager.cpp
index 803a30e7e..758a452b1 100644
--- a/src/actorspritemanager.cpp
+++ b/src/actorspritemanager.cpp
@@ -203,11 +203,7 @@ ActorSpriteManager::ActorSpriteManager() :
ActorSpriteManager::~ActorSpriteManager()
{
- config.removeListener("targetDeadPlayers", this);
- config.removeListener("targetOnlyReachable", this);
- config.removeListener("cyclePlayers", this);
- config.removeListener("cycleMonsters", this);
- config.removeListener("extMouseTargeting", this);
+ config.removeListeners(this);
storeAttackList();
clear();
}
diff --git a/src/being.cpp b/src/being.cpp
index e1cb9b0ae..664eecd1d 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -1380,8 +1380,10 @@ void Being::drawEmotion(Graphics *graphics, int offsetX, int offsetY)
if (emotionIndex >= 0 && emotionIndex <= EmoteDB::getLast())
{
- if (EmoteDB::getAnimation(emotionIndex))
+ if (EmoteDB::getAnimation(emotionIndex, true))
EmoteDB::getAnimation(emotionIndex)->draw(graphics, px, py);
+ else
+ mEmotion = 0;
}
}
@@ -2320,7 +2322,7 @@ void Being::recalcSpritesOrder()
int val = slotRemap.at(slot);
int id = 0;
- if ((int)mSpriteIDs.size() > val)
+ if (static_cast<int>(mSpriteIDs.size()) > val)
id = mSpriteIDs[val];
int idx = -1;
@@ -2525,7 +2527,6 @@ void Being::saveComment(const std::string &name,
void Being::setState(Uint8 state)
{
- mAdvanced = true;
bool shop = (state & FLAG_SHOP);
bool away = (state & FLAG_AWAY);
bool inactive = (state & FLAG_INACTIVE);
@@ -2548,6 +2549,7 @@ void Being::setEmote(Uint8 emotion, int emote_time)
if ((emotion & FLAG_SPECIAL) == FLAG_SPECIAL)
{
setState(emotion);
+ mAdvanced = true;
}
else
{
diff --git a/src/client.cpp b/src/client.cpp
index e6aeb22e2..95e49c6aa 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -363,7 +363,7 @@ void Client::gameInit()
logger->log1("Initializing SDL...");
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
{
- logger->error(strprintf("Could not initialize SDL: %s",
+ logger->safeError(strprintf("Could not initialize SDL: %s",
SDL_GetError()));
}
atexit(SDL_Quit);
@@ -555,13 +555,17 @@ void Client::gameInit()
if (!mainGraphics->setVideoMode(oldWidth, oldHeight, bpp,
oldFullscreen, hwaccel, enableResize, noFrame))
{
- logger->error(strprintf("Couldn't restore %dx%dx%d "
+ logger->safeError(strprintf("Couldn't restore %dx%dx%d "
"video mode: %s", oldWidth, oldHeight, bpp,
SDL_GetError()));
}
}
}
+ applyGrabMode();
+ applyGamma();
+ applyVSync();
+
// Initialize for drawing
mainGraphics->_beginDraw();
@@ -663,6 +667,9 @@ void Client::gameInit()
setFramerate(fpsLimit);
config.addListener("fpslimit", this);
config.addListener("guialpha", this);
+ config.addListener("gamma", this);
+ config.addListener("particleEmitterSkip", this);
+ config.addListener("vsync", this);
setGuiAlpha(config.getFloatValue("guialpha"));
optionChanged("fpslimit");
@@ -700,8 +707,7 @@ void Client::gameClear()
{
if (logger)
logger->log1("Quitting1");
- config.removeListener("fpslimit", this);
- config.removeListener("guialpha", this);
+ config.removeListeners(this);
SDL_RemoveTimer(mLogicCounterId);
SDL_RemoveTimer(mSecondsCounterId);
@@ -1317,14 +1323,16 @@ int Client::gameExec()
case STATE_LOGIN_ERROR:
logger->log1("State: LOGIN ERROR");
- mCurrentDialog = new OkDialog(_("Error"), errorMessage);
+ mCurrentDialog = new OkDialog(_("Error"),
+ errorMessage, DIALOG_ERROR);
mCurrentDialog->addActionListener(&loginListener);
mCurrentDialog = nullptr; // OkDialog deletes itself
break;
case STATE_ACCOUNTCHANGE_ERROR:
logger->log1("State: ACCOUNT CHANGE ERROR");
- mCurrentDialog = new OkDialog(_("Error"), errorMessage);
+ mCurrentDialog = new OkDialog(_("Error"),
+ errorMessage, DIALOG_ERROR);
mCurrentDialog->addActionListener(&accountListener);
mCurrentDialog = nullptr; // OkDialog deletes itself
break;
@@ -1360,7 +1368,7 @@ int Client::gameExec()
case STATE_CHANGEPASSWORD_SUCCESS:
logger->log1("State: CHANGE PASSWORD SUCCESS");
mCurrentDialog = new OkDialog(_("Password Change"),
- _("Password changed successfully!"));
+ _("Password changed successfully!"), DIALOG_ERROR);
mCurrentDialog->addActionListener(&accountListener);
mCurrentDialog = nullptr; // OkDialog deletes itself
loginData.password = loginData.newPassword;
@@ -1380,7 +1388,7 @@ int Client::gameExec()
case STATE_CHANGEEMAIL_SUCCESS:
logger->log1("State: CHANGE EMAIL SUCCESS");
mCurrentDialog = new OkDialog(_("Email Change"),
- _("Email changed successfully!"));
+ _("Email changed successfully!"), DIALOG_ERROR);
mCurrentDialog->addActionListener(&accountListener);
mCurrentDialog = nullptr; // OkDialog deletes itself
break;
@@ -1401,7 +1409,7 @@ int Client::gameExec()
Net::getLoginHandler()->disconnect();
mCurrentDialog = new OkDialog(_("Unregister Successful"),
- _("Farewell, come back any time..."));
+ _("Farewell, come back any time..."), DIALOG_ERROR);
loginData.clear();
//The errorlistener sets the state to STATE_CHOOSE_SERVER
mCurrentDialog->addActionListener(&errorListener);
@@ -1458,7 +1466,8 @@ int Client::gameExec()
case STATE_ERROR:
logger->log1("State: ERROR");
logger->log("Error: %s\n", errorMessage.c_str());
- mCurrentDialog = new OkDialog(_("Error"), errorMessage);
+ mCurrentDialog = new OkDialog(_("Error"),
+ errorMessage, DIALOG_ERROR);
mCurrentDialog->addActionListener(&errorListener);
mCurrentDialog = nullptr; // OkDialog deletes itself
Net::getGameHandler()->disconnect();
@@ -1490,6 +1499,19 @@ void Client::optionChanged(const std::string &name)
else if (name == "guialpha")
{
setGuiAlpha(config.getFloatValue("guialpha"));
+ Image::setEnableAlpha(config.getFloatValue("guialpha") != 1.0f);
+ }
+ else if (name == "gamma")
+ {
+ applyGamma();
+ }
+ else if (name == "particleEmitterSkip")
+ {
+ Particle::emitterSkip = config.getIntValue("particleEmitterSkip") + 1;
+ }
+ else if (name == "vsync")
+ {
+ applyVSync();
}
}
@@ -1671,6 +1693,7 @@ void Client::initServerConfig(std::string serverName)
{
fclose(configFile);
serverConfig.init(configPath);
+ serverConfig.setDefaultValues(getConfigDefaults());
logger->log("serverConfigPath: " + configPath);
}
initPacketLimiter();
@@ -2429,3 +2452,22 @@ void Client::resizeVideo(int width, int height, bool always)
config.setValue("screenheight", height);
}
}
+
+void Client::applyGrabMode()
+{
+ SDL_WM_GrabInput(config.getBoolValue("grabinput")
+ ? SDL_GRAB_ON : SDL_GRAB_OFF);
+}
+
+void Client::applyGamma()
+{
+ float val = config.getFloatValue("gamma");
+ SDL_SetGamma(val, val, val);
+}
+
+void Client::applyVSync()
+{
+ int val = config.getIntValue("vsync");
+ if (val > 0 && val < 2)
+ SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, val);
+}
diff --git a/src/client.h b/src/client.h
index 6c93adbdf..54de27824 100644
--- a/src/client.h
+++ b/src/client.h
@@ -273,6 +273,12 @@ public:
static bool isTmw();
+ static void applyGrabMode();
+
+ void applyGamma();
+
+ void applyVSync();
+
void optionChanged(const std::string &name);
void action(const gcn::ActionEvent &event);
diff --git a/src/commandhandler.cpp b/src/commandhandler.cpp
index 9f832c021..67b03e78c 100644
--- a/src/commandhandler.cpp
+++ b/src/commandhandler.cpp
@@ -57,6 +57,10 @@
#include "net/playerhandler.h"
#include "net/tradehandler.h"
+#if defined USE_OPENGL
+#include "openglgraphics.h"
+#endif
+
#ifdef DEBUG_DUMP_LEAKS
#include "resources/image.h"
#include "resources/resource.h"
@@ -207,6 +211,8 @@ void CommandHandler::handleCommand(const std::string &command, ChatTab *tab)
handleDumpGraphics(args, tab);
else if (type == "dumpt")
handleDumpTests(args, tab);
+ else if (type == "dumpogl")
+ handleDumpOGL(args, tab);
else if (tab->handleCommand(type, args))
;
else if (type == "hack")
@@ -1347,3 +1353,11 @@ void CommandHandler::replaceVars(std::string &str)
}
}
}
+
+void CommandHandler::handleDumpOGL(const std::string &args A_UNUSED,
+ ChatTab *tab A_UNUSED)
+{
+#if defined USE_OPENGL
+ OpenGLGraphics::dumpSettings();
+#endif
+}
diff --git a/src/commandhandler.h b/src/commandhandler.h
index cd25c234a..a8f21ac7a 100644
--- a/src/commandhandler.h
+++ b/src/commandhandler.h
@@ -48,7 +48,8 @@ class CommandHandler
/**
* Destructor
*/
- ~CommandHandler() {}
+ ~CommandHandler()
+ { }
/**
* Parse and handle the given command.
@@ -303,6 +304,8 @@ class CommandHandler
void handleDumpTests(const std::string &args, ChatTab *tab);
+ void handleDumpOGL(const std::string &args, ChatTab *tab);
+
void outString(ChatTab *tab, const std::string &str,
const std::string &def);
diff --git a/src/configlistener.h b/src/configlistener.h
index e4bbbee53..28540c564 100644
--- a/src/configlistener.h
+++ b/src/configlistener.h
@@ -37,7 +37,8 @@ class ConfigListener
/**
* Destructor.
*/
- virtual ~ConfigListener() {}
+ virtual ~ConfigListener()
+ { }
/**
* Called when an option changed. The config listener will have to be
diff --git a/src/configuration.cpp b/src/configuration.cpp
index c4f1cc360..624cf7865 100644
--- a/src/configuration.cpp
+++ b/src/configuration.cpp
@@ -217,6 +217,11 @@ int Configuration::getIntValue(const std::string &key) const
defaultValue = 0;
}
}
+ else if (itdef->second->getType() == VariableData::DATA_FLOAT)
+ {
+ defaultValue = static_cast<int>(
+ (static_cast<FloatData*>(itdef->second))->getData());
+ }
}
else
{
@@ -321,11 +326,38 @@ float Configuration::getFloatValue(const std::string &key) const
{
DefaultsData::const_iterator itdef = mDefaultsData->find(key);
- if (itdef != mDefaultsData->end() && itdef->second
- && itdef->second->getType() == VariableData::DATA_FLOAT)
+ if (itdef != mDefaultsData->end() && itdef->second)
{
- defaultValue = static_cast<float>(
- (static_cast<FloatData*>(itdef->second))->getData());
+ if (itdef->second->getType() == VariableData::DATA_FLOAT)
+ {
+ defaultValue = static_cast<float>(
+ (static_cast<FloatData*>(itdef->second))->getData());
+ }
+ else if (itdef->second->getType()
+ == VariableData::DATA_STRING)
+ {
+ defaultValue = atof((static_cast<StringData*>(
+ itdef->second))->getData().c_str());
+ }
+ else if (itdef->second->getType()
+ == VariableData::DATA_BOOL)
+ {
+ if ((static_cast<BoolData*>(
+ itdef->second))->getData())
+ {
+ defaultValue = 1;
+ }
+ else
+ {
+ defaultValue = 0;
+ }
+ }
+ else if (itdef->second->getType()
+ == VariableData::DATA_INT)
+ {
+ defaultValue = (static_cast<IntData*>(
+ itdef->second))->getData();
+ }
}
else
{
@@ -385,6 +417,18 @@ bool Configuration::getBoolValue(const std::string &key) const
defaultValue = false;
}
}
+ if (itdef->second->getType() == VariableData::DATA_FLOAT)
+ {
+ if (static_cast<int>((static_cast<FloatData*>(
+ itdef->second))->getData()) != 0)
+ {
+ defaultValue = true;
+ }
+ else
+ {
+ defaultValue = false;
+ }
+ }
}
else
{
@@ -528,7 +572,8 @@ void ConfigurationObject::writeToXML(XmlTextWriterPtr writer)
elt_it != it->second.end(); ++elt_it)
{
xmlTextWriterStartElement(writer, BAD_CAST name);
- (*elt_it)->writeToXML(writer);
+ if (*elt_it)
+ (*elt_it)->writeToXML(writer);
xmlTextWriterEndElement(writer);
}
@@ -572,14 +617,22 @@ void Configuration::write()
xmlFreeTextWriter(writer);
}
-void Configuration::addListener(
- const std::string &key, ConfigListener *listener)
+void Configuration::addListener(const std::string &key,
+ ConfigListener *listener)
{
mListenerMap[key].push_front(listener);
}
-void Configuration::removeListener(
- const std::string &key, ConfigListener *listener)
+void Configuration::removeListener(const std::string &key,
+ ConfigListener *listener)
{
mListenerMap[key].remove(listener);
}
+
+void Configuration::removeListeners(ConfigListener *listener)
+{
+ ListenerMapIterator it = mListenerMap.begin();
+ ListenerMapIterator it_end = mListenerMap.end();
+ for (; it != it_end; ++ it)
+ (it->second).remove(listener);
+}
diff --git a/src/configuration.h b/src/configuration.h
index 122badfd5..2715ea59c 100644
--- a/src/configuration.h
+++ b/src/configuration.h
@@ -248,6 +248,8 @@ class Configuration : public ConfigurationObject
*/
void removeListener(const std::string &key, ConfigListener *listener);
+ void removeListeners(ConfigListener *listener);
+
void setValue(const std::string &key, const std::string &value);
void setSilent(const std::string &key, const std::string &value);
diff --git a/src/defaults.cpp b/src/defaults.cpp
index b21941bfb..1ca64d4e6 100644
--- a/src/defaults.cpp
+++ b/src/defaults.cpp
@@ -226,6 +226,19 @@ DefaultsData* getConfigDefaults()
AddDEF(configData, "enableresize", true);
AddDEF(configData, "noframe", false);
AddDEF(configData, "groupFriends", true);
+ AddDEF(configData, "grabinput", false);
+ AddDEF(configData, "usefbo", false);
+ AddDEF(configData, "gamma", 1);
+ AddDEF(configData, "vsync", 0);
+ AddDEF(configData, "enableBuggyServers", true);
+ AddDEF(configData, "soundwhisper", "newmessage");
+ AddDEF(configData, "soundhighlight", "reminder");
+ AddDEF(configData, "soundglobal", "email");
+ AddDEF(configData, "sounderror", "error");
+ AddDEF(configData, "soundtrade", "start");
+ AddDEF(configData, "soundinfo", "notify");
+ AddDEF(configData, "soundrequest", "attention");
+ AddDEF(configData, "soundguild", "newmessage");
return configData;
}
@@ -260,6 +273,8 @@ DefaultsData* getBrandingDefaults()
AddDEF(brandingData, "guiThemePath", "themes/");
AddDEF(brandingData, "fontsPath", "fonts/");
+ AddDEF(brandingData, "systemsounds", "sfx/system/");
+
AddDEF(brandingData, "wallpaperFile", "");
AddDEF(brandingData, "dataPath", "");
return brandingData;
diff --git a/src/effectmanager.h b/src/effectmanager.h
index 274a6ad14..7b71069fe 100644
--- a/src/effectmanager.h
+++ b/src/effectmanager.h
@@ -25,6 +25,7 @@
#include <list>
#include <string>
+#include <vector>
class Being;
diff --git a/src/equipment.h b/src/equipment.h
index 50acd60d3..ed38d32ca 100644
--- a/src/equipment.h
+++ b/src/equipment.h
@@ -66,8 +66,11 @@ class Equipment
{
public:
virtual Item *getEquipment(int index) const = 0;
+
virtual void clear() = 0;
- virtual ~Backend() { }
+
+ virtual ~Backend()
+ { }
};
/**
diff --git a/src/game.cpp b/src/game.cpp
index e016d02ff..39d38ac5c 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -461,6 +461,7 @@ static bool saveScreenshot()
if (!config.getBoolValue("showip"))
{
mainGraphics->setSecure(true);
+ mainGraphics->prepareScreenshot();
gui->draw();
screenshot = mainGraphics->getScreenshot();
mainGraphics->setSecure(false);
@@ -561,7 +562,7 @@ void Game::logic()
{
errorMessage = _("The connection to the server was lost.");
disconnectedDialog = new OkDialog(_("Network Error"),
- errorMessage, false);
+ errorMessage, DIALOG_ERROR, false);
disconnectedDialog->addActionListener(&errorListener);
disconnectedDialog->requestMoveToTop();
}
@@ -803,12 +804,13 @@ bool Game::handleSwitchKeys(SDL_Event &event, bool &used)
used = true;
}
}
- if (dialog)
+ if (dialog && !dialog->isInputFocused())
{
- if (keyboard.isActionActive(keyboard.KEY_MOVE_UP))
- dialog->move(1);
- else if (keyboard.isActionActive(keyboard.KEY_MOVE_DOWN))
- dialog->move(-1);
+ if (keyboard.isActionActive(keyboard.KEY_MOVE_UP)
+ || keyboard.isActionActive(keyboard.KEY_MOVE_DOWN))
+ {
+ dialog->refocus();
+ }
}
}
@@ -1316,7 +1318,8 @@ void Game::handleMoveAndAttack(SDL_Event &event, bool wasDown)
if (player_node->isAlive() && (!Being::isTalking()
|| keyboard.getKeyIndex(event.key.keysym.sym)
== KeyboardConfig::KEY_TALK)
- && chatWindow && !chatWindow->isInputFocused() && !quitDialog)
+ && chatWindow && !chatWindow->isInputFocused()
+ && !InventoryWindow::isAnyInputFocused() && !quitDialog)
{
// Get the state of the keyboard keys
keyboard.refreshActiveKeys();
@@ -1796,8 +1799,9 @@ void Game::changeMap(const std::string &mapPath)
if (!newMap)
{
logger->log("Error while loading %s", fullMap.c_str());
- new OkDialog(_("Could Not Load Map"),
- strprintf(_("Error while loading %s"), fullMap.c_str()));
+ new OkDialog(_("Could Not Load Map"), strprintf(
+ _("Error while loading %s"), fullMap.c_str()),
+ DIALOG_ERROR, false);
}
if (mCurrentMap)
diff --git a/src/graphics.cpp b/src/graphics.cpp
index 5241bbcc6..e6841fa5c 100644
--- a/src/graphics.cpp
+++ b/src/graphics.cpp
@@ -845,7 +845,8 @@ void Graphics::fillRectangle(const gcn::Rectangle& rectangle)
case 1:
for (y = y1; y < y2; y++)
{
- Uint8 *p = (Uint8 *)mTarget->pixels + y * mTarget->pitch;
+ Uint8 *p = static_cast<Uint8 *>(mTarget->pixels)
+ + y * mTarget->pitch;
for (x = x1; x < x2; x++)
*(p + x) = pixel;
}
@@ -853,12 +854,14 @@ void Graphics::fillRectangle(const gcn::Rectangle& rectangle)
case 2:
for (y = y1; y < y2; y++)
{
- Uint8 *p0 = (Uint8 *)mTarget->pixels + y * mTarget->pitch;
+ Uint8 *p0 = static_cast<Uint8 *>(mTarget->pixels)
+ + y * mTarget->pitch;
for (x = x1; x < x2; x++)
{
Uint8 *p = p0 + x * 2;
- *(Uint16 *)p = gcn::SDLAlpha16(
- pixel, *(Uint32 *)p, mColor.a, mTarget->format);
+ *reinterpret_cast<Uint16 *>(p) = gcn::SDLAlpha16(
+ pixel, *reinterpret_cast<Uint32 *>(p),
+ mColor.a, mTarget->format);
}
}
break;
@@ -871,7 +874,8 @@ void Graphics::fillRectangle(const gcn::Rectangle& rectangle)
for (y = y1; y < y2; y++)
{
- Uint8 *p0 = (Uint8 *)mTarget->pixels + y * mTarget->pitch;
+ Uint8 *p0 = static_cast<Uint8 *>(mTarget->pixels)
+ + y * mTarget->pitch;
for (x = x1; x < x2; x++)
{
Uint8 *p = p0 + x * 3;
@@ -896,18 +900,19 @@ void Graphics::fillRectangle(const gcn::Rectangle& rectangle)
const unsigned a1 = (255 - mColor.a);
for (y = y1; y < y2; y++)
{
- Uint8 *p0 = (Uint8 *)mTarget->pixels + y * mTarget->pitch;
+ Uint8 *p0 = static_cast<Uint8 *>(mTarget->pixels)
+ + y * mTarget->pitch;
for (x = x1; x < x2; x++)
{
Uint8 *p = p0 + x * 4;
- Uint32 dst = *(Uint32 *)p;
+ Uint32 dst = *reinterpret_cast<Uint32 *>(p);
const unsigned int b = (pb + (dst & 0xff) * a1) >> 8;
const unsigned int g = (pg + (dst & 0xff00) * a1) >> 8;
const unsigned int r = (pr
+ (dst & 0xff0000) * a1) >> 8;
- *(Uint32 *)p = ((b & 0xff) | (g & 0xff00)
- | (r & 0xff0000));
+ *reinterpret_cast<Uint32 *>(p) = ((b & 0xff)
+ | (g & 0xff00) | (r & 0xff0000));
}
}
break;
diff --git a/src/graphics.h b/src/graphics.h
index 5d496d654..03eecefff 100644
--- a/src/graphics.h
+++ b/src/graphics.h
@@ -251,6 +251,9 @@ class Graphics : public gcn::SDLGraphics
*/
virtual SDL_Surface *getScreenshot();
+ virtual void prepareScreenshot()
+ { }
+
virtual bool drawNet(int x1, int y1, int x2, int y2,
int width, int height);
diff --git a/src/graphicsvertexes.h b/src/graphicsvertexes.h
index 4245e8bf5..452cebc29 100644
--- a/src/graphicsvertexes.h
+++ b/src/graphicsvertexes.h
@@ -28,7 +28,8 @@
#include "localconsts.h"
#ifdef USE_OPENGL
-#define NO_SDL_GLEXT
+//#define NO_SDL_GLEXT
+#define GL_GLEXT_PROTOTYPES 1
#include <SDL_opengl.h>
diff --git a/src/gui/changeemaildialog.cpp b/src/gui/changeemaildialog.cpp
index 518ed3da1..1a468d44f 100644
--- a/src/gui/changeemaildialog.cpp
+++ b/src/gui/changeemaildialog.cpp
@@ -154,7 +154,8 @@ void ChangeEmailDialog::action(const gcn::ActionEvent &event)
else if (error == 2)
mWrongDataNoticeListener->setTarget(this->mSecondEmailField);
- OkDialog *dlg = new OkDialog(_("Error"), errorMsg.str());
+ OkDialog *dlg = new OkDialog(_("Error"),
+ errorMsg.str(), DIALOG_ERROR);
if (dlg)
dlg->addActionListener(mWrongDataNoticeListener);
}
diff --git a/src/gui/changepassworddialog.cpp b/src/gui/changepassworddialog.cpp
index 8082b8d58..a58d8616b 100644
--- a/src/gui/changepassworddialog.cpp
+++ b/src/gui/changepassworddialog.cpp
@@ -144,7 +144,8 @@ void ChangePasswordDialog::action(const gcn::ActionEvent &event)
else if (error == 3)
mWrongDataNoticeListener->setTarget(this->mSecondPassField);
- OkDialog *dlg = new OkDialog(_("Error"), errorMsg.str());
+ OkDialog *dlg = new OkDialog(_("Error"),
+ errorMsg.str(), DIALOG_ERROR);
dlg->addActionListener(mWrongDataNoticeListener);
}
else
diff --git a/src/gui/charcreatedialog.cpp b/src/gui/charcreatedialog.cpp
index 8d4767a15..124476f1c 100644
--- a/src/gui/charcreatedialog.cpp
+++ b/src/gui/charcreatedialog.cpp
@@ -270,8 +270,8 @@ void CharCreateDialog::action(const gcn::ActionEvent &event)
else
{
new OkDialog(_("Error"),
- _("Your name needs to be at least 4 characters."),
- true, this);
+ _("Your name needs to be at least 4 characters."),
+ DIALOG_ERROR, true, this);
}
}
else if (id == "cancel")
@@ -474,8 +474,11 @@ void CharCreateDialog::updateHair()
mHairStyle %= Being::getNumOfHairstyles();
if (mHairStyle < 0)
mHairStyle += Being::getNumOfHairstyles();
- if (mHairStyle < (signed)minHairStyle || mHairStyle > (signed)maxHairStyle)
+ if (mHairStyle < static_cast<signed>(minHairStyle)
+ || mHairStyle > static_cast<signed>(maxHairStyle))
+ {
mHairStyle = minHairStyle;
+ }
const ItemInfo &item = ItemDB::get(-mHairStyle);
mHairStyleNameLabel->setCaption(item.getName());
mHairStyleNameLabel->adjustSize();
@@ -483,8 +486,11 @@ void CharCreateDialog::updateHair()
mHairColor %= ColorDB::getHairSize();
if (mHairColor < 0)
mHairColor += ColorDB::getHairSize();
- if (mHairColor < (signed)minHairColor || mHairColor > (signed)maxHairColor)
+ if (mHairColor < static_cast<signed>(minHairColor)
+ || mHairColor > static_cast<signed>(maxHairColor))
+ {
mHairColor = minHairColor;
+ }
mHairColorNameLabel->setCaption(ColorDB::getHairColorName(mHairColor));
mHairColorNameLabel->adjustSize();
diff --git a/src/gui/charselectdialog.cpp b/src/gui/charselectdialog.cpp
index d2b74a632..b1b8009a4 100644
--- a/src/gui/charselectdialog.cpp
+++ b/src/gui/charselectdialog.cpp
@@ -253,7 +253,7 @@ void CharSelectDialog::action(const gcn::ActionEvent &event)
}
else
{
- new OkDialog(_("Error"), _("Incorrect password"));
+ new OkDialog(_("Error"), _("Incorrect password"), DIALOG_ERROR);
}
mDeleteIndex = -1;
}
diff --git a/src/gui/chatwindow.cpp b/src/gui/chatwindow.cpp
index 69e4d703f..eb8669223 100644
--- a/src/gui/chatwindow.cpp
+++ b/src/gui/chatwindow.cpp
@@ -133,7 +133,8 @@ const char *COLOR_NAME[14] =
class ColorListModel : public gcn::ListModel
{
public:
- virtual ~ColorListModel() { }
+ virtual ~ColorListModel()
+ { }
virtual int getNumberOfElements()
{
@@ -306,6 +307,7 @@ void ChatWindow::fillCommands()
mCommands.push_back("/serverunignoreall");
mCommands.push_back("/dumpg");
mCommands.push_back("/dumpt");
+ mCommands.push_back("/dumpogl");
mCommands.push_back("/pseudoaway ");
mCommands.push_back("<PLAYER>");
mCommands.push_back("<MONSTER>");
diff --git a/src/gui/confirmdialog.cpp b/src/gui/confirmdialog.cpp
index 22acf5116..a2fb7b6cc 100644
--- a/src/gui/confirmdialog.cpp
+++ b/src/gui/confirmdialog.cpp
@@ -97,7 +97,7 @@ ConfirmDialog::ConfirmDialog(const std::string &title, const std::string &msg,
}
setVisible(true);
yesButton->requestFocus();
- sound.playGuiSfx("system/newmessage.ogg");
+ sound.playGuiSound(SOUND_REQUEST);
}
void ConfirmDialog::action(const gcn::ActionEvent &event)
diff --git a/src/gui/debugwindow.cpp b/src/gui/debugwindow.cpp
index b65068dc5..fa01b5aa8 100644
--- a/src/gui/debugwindow.cpp
+++ b/src/gui/debugwindow.cpp
@@ -390,7 +390,7 @@ void NetDebugTab::logic()
if (player_node && player_node->getPingTime() != 0)
{
mPingLabel->setCaption(strprintf(_("Ping: %s ms"),
- toString((int)player_node->getPingTime()).c_str()));
+ toString(static_cast<int>(player_node->getPingTime())).c_str()));
}
else
{
diff --git a/src/gui/editserverdialog.cpp b/src/gui/editserverdialog.cpp
index 8a4a9579d..ca1afeaba 100644
--- a/src/gui/editserverdialog.cpp
+++ b/src/gui/editserverdialog.cpp
@@ -173,7 +173,7 @@ void EditServerDialog::action(const gcn::ActionEvent &event)
{
OkDialog *dlg = new OkDialog(_("Error"),
_("Please at least type both the address and the port "
- "of the server."));
+ "of the server."), DIALOG_ERROR);
dlg->addActionListener(this);
}
else
@@ -184,7 +184,8 @@ void EditServerDialog::action(const gcn::ActionEvent &event)
mServer.name = mNameField->getText();
mServer.description = mDescriptionField->getText();
mServer.hostname = mServerAddressField->getText();
- mServer.port = (short) atoi(mPortField->getText().c_str());
+ mServer.port = static_cast<short>(atoi(
+ mPortField->getText().c_str()));
if (mTypeField)
{
diff --git a/src/gui/editserverdialog.h b/src/gui/editserverdialog.h
index 6035b0e50..4ad6b8fcb 100644
--- a/src/gui/editserverdialog.h
+++ b/src/gui/editserverdialog.h
@@ -44,7 +44,8 @@ class TypeListModel;
class TypeListModel : public gcn::ListModel
{
public:
- TypeListModel() {}
+ TypeListModel()
+ { }
/**
* Used to get number of line in the list
diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp
index 275bf19bb..89063c3dc 100644
--- a/src/gui/equipmentwindow.cpp
+++ b/src/gui/equipmentwindow.cpp
@@ -407,8 +407,11 @@ void EquipmentWindow::loadSlot(XmlNodePtr slotNode, ImageSet *imageset)
const int imageIndex = XML::getProperty(slotNode, "image", -1);
Image *image = nullptr;
- if (imageset && imageIndex >= 0 && imageIndex < (signed)imageset->size())
+ if (imageset && imageIndex >= 0 && imageIndex
+ < static_cast<signed>(imageset->size()))
+ {
image = imageset->get(imageIndex);
+ }
if (mBoxes[slot])
{
@@ -510,8 +513,11 @@ void EquipmentWindow::addBox(int idx, int x, int y, int imageIndex)
{
Image *image = nullptr;
- if (mImageSet && imageIndex >= 0 && imageIndex < (signed)mImageSet->size())
+ if (mImageSet && imageIndex >= 0 && imageIndex
+ < static_cast<signed>(mImageSet->size()))
+ {
image = mImageSet->get(imageIndex);
+ }
mBoxes[idx] = new EquipmentBox(x + getPadding(), y + getTitleBarHeight(),
image);
diff --git a/src/gui/itempopup.cpp b/src/gui/itempopup.cpp
index d96aa564f..f33f77e83 100644
--- a/src/gui/itempopup.cpp
+++ b/src/gui/itempopup.cpp
@@ -123,7 +123,7 @@ void ItemPopup::setItem(const Item *item, bool showImage)
}
mItemName->adjustSize();
unsigned minWidth = mItemName->getWidth() + 8;
- if ((unsigned)getWidth() < minWidth)
+ if (static_cast<unsigned>(getWidth()) < minWidth)
setWidth(minWidth);
}
}
diff --git a/src/gui/minimap.cpp b/src/gui/minimap.cpp
index 74da37341..b76e71069 100644
--- a/src/gui/minimap.cpp
+++ b/src/gui/minimap.cpp
@@ -60,7 +60,7 @@ Minimap::Minimap():
setDefaultSize(5, 25, 100, 100);
// set this to false as the minimap window size is changed
//depending on the map size
- setResizable(false);
+ setResizable(true);
setupWindow->registerWindowForReset(this);
setDefaultVisible(true);
@@ -229,13 +229,11 @@ void Minimap::draw(gcn::Graphics *graphics)
mMapImage->mBounds.h > a.height)
{
const Vector &p = player_node->getPosition();
- mMapOriginX = ((a.width) / 2) - static_cast<int>((p.x
- + viewport->getCameraRelativeX()) * static_cast<int>(
- mWidthProportion)) / 32;
+ mMapOriginX = ((a.width) / 2) - (static_cast<float>(p.x
+ + viewport->getCameraRelativeX()) * mWidthProportion) / 32;
- mMapOriginY = ((a.height) / 2) - static_cast<int>((p.y
- + viewport->getCameraRelativeX()) * static_cast<int>(
- mHeightProportion)) / 32;
+ mMapOriginY = ((a.height) / 2) - (static_cast<float>(p.y
+ + viewport->getCameraRelativeX()) * mHeightProportion) / 32;
const int minOriginX = a.width - mMapImage->mBounds.w;
const int minOriginY = a.height - mMapImage->mBounds.h;
@@ -314,9 +312,9 @@ void Minimap::draw(gcn::Graphics *graphics)
const Vector &pos = being->getPosition();
graphics->fillRectangle(gcn::Rectangle(
- static_cast<int>(pos.x * mWidthProportion) / 32
+ static_cast<float>(pos.x * mWidthProportion) / 32
+ mMapOriginX - offsetWidth,
- static_cast<int>(pos.y * mHeightProportion) / 32
+ static_cast<float>(pos.y * mHeightProportion) / 32
+ mMapOriginY - offsetHeight,
dotSize, dotSize));
}
@@ -367,10 +365,10 @@ void Minimap::draw(gcn::Graphics *graphics)
const Vector &pos = player_node->getPosition();
// logger->log("width:" + toString(graph->getWidth()));
- int x = static_cast<int>((pos.x - (graph->getWidth() / 2)
+ int x = static_cast<float>((pos.x - (graph->getWidth() / 2)
+ viewport->getCameraRelativeX())
* mWidthProportion) / 32 + mMapOriginX;
- int y = static_cast<int>((pos.y - (graph->getHeight() / 2)
+ int y = static_cast<float>((pos.y - (graph->getHeight() / 2)
+ viewport->getCameraRelativeY())
* mHeightProportion) / 32 + mMapOriginY;
@@ -403,17 +401,29 @@ void Minimap::mouseReleased(gcn::MouseEvent &event)
{
gcn::Window::mouseReleased(event);
- if (!player_node)
+ if (!player_node || !viewport)
return;
if (event.getButton() == gcn::MouseEvent::LEFT)
{
- const gcn::Rectangle a = getChildrenArea();
- const int x = event.getX() - a.x;
- const int y = event.getY() - a.y;
+ int x = event.getX();
+ int y = event.getY();
+ screenToMap(x, y);
- player_node->navigateTo((x - mMapOriginX + mWidthProportion)
- / mWidthProportion, (y - mMapOriginY + mHeightProportion)
- / mHeightProportion);
+ player_node->navigateTo(x, y);
}
+ else if (event.getButton() == gcn::MouseEvent::RIGHT)
+ {
+ int x = event.getX();
+ int y = event.getY();
+ screenToMap(x, y);
+ viewport->showMapPopup(x, y);
+ }
+}
+
+void Minimap::screenToMap(int &x, int &y)
+{
+ const gcn::Rectangle a = getChildrenArea();
+ x = (x - a.x - mMapOriginX + mWidthProportion) / mWidthProportion;
+ y = (y - a.y - mMapOriginY + mHeightProportion) / mHeightProportion;
}
diff --git a/src/gui/minimap.h b/src/gui/minimap.h
index 8b7da5849..12835edd5 100644
--- a/src/gui/minimap.h
+++ b/src/gui/minimap.h
@@ -60,6 +60,8 @@ class Minimap : public Window
void mouseReleased(gcn::MouseEvent &event);
+ void screenToMap(int &x, int &y);
+
private:
Image *mMapImage;
float mWidthProportion;
diff --git a/src/gui/npcdialog.cpp b/src/gui/npcdialog.cpp
index 3e5b30a9c..12b3e1244 100644
--- a/src/gui/npcdialog.cpp
+++ b/src/gui/npcdialog.cpp
@@ -78,7 +78,7 @@ NpcDialog::NpcDialog(int npcId) :
setMinWidth(200);
setMinHeight(150);
- setDefaultSize(260, 200, ImageRect::CENTER);
+ setDefaultSize(400, 400, ImageRect::CENTER);
mItemLinkHandler = new ItemLinkHandler;
// Setup output text box
@@ -342,9 +342,20 @@ void NpcDialog::parseListItems(const std::string &itemString)
mItems.push_back(tmp);
if (!mItems.empty())
+ {
mItemList->setSelected(0);
+ mItemList->requestFocus();
+ }
else
+ {
mItemList->setSelected(-1);
+ }
+}
+
+void NpcDialog::refocus()
+{
+ if (!mItems.empty())
+ mItemList->refocus();
}
void NpcDialog::textRequest(const std::string &defaultText)
@@ -363,7 +374,8 @@ bool NpcDialog::isTextInputFocused() const
bool NpcDialog::isInputFocused() const
{
- return mTextField->isFocused() || mIntField->isFocused();
+ return mTextField->isFocused() || mIntField->isFocused()
+ || mItemList->isFocused();
}
bool NpcDialog::isAnyInputFocused()
diff --git a/src/gui/npcdialog.h b/src/gui/npcdialog.h
index d4288d5c9..7bd2ee76d 100644
--- a/src/gui/npcdialog.h
+++ b/src/gui/npcdialog.h
@@ -177,6 +177,8 @@ class NpcDialog : public Window, public gcn::ActionListener,
void restoreCamera();
+ void refocus();
+
private:
typedef std::list<NpcDialog*> DialogList;
static DialogList instances;
diff --git a/src/gui/okdialog.cpp b/src/gui/okdialog.cpp
index 4a3bdf731..3259cb6d6 100644
--- a/src/gui/okdialog.cpp
+++ b/src/gui/okdialog.cpp
@@ -22,6 +22,8 @@
#include "gui/okdialog.h"
+#include "sound.h"
+
#include "gui/gui.h"
#include "gui/widgets/button.h"
@@ -34,7 +36,8 @@
#include "debug.h"
OkDialog::OkDialog(const std::string &title, const std::string &msg,
- bool modal, bool showCenter, Window *parent):
+ int soundEvent, bool modal, bool showCenter,
+ Window *parent):
Window(title, modal, parent, "ok.xml")
{
mTextBox = new TextBox;
@@ -71,6 +74,11 @@ OkDialog::OkDialog(const std::string &title, const std::string &msg,
centerHorisontally();
setVisible(true);
okButton->requestFocus();
+
+ if (soundEvent == DIALOG_OK)
+ sound.playGuiSound(SOUND_INFO);
+ else if (soundEvent == DIALOG_ERROR)
+ sound.playGuiSound(SOUND_ERROR);
}
void OkDialog::action(const gcn::ActionEvent &event)
diff --git a/src/gui/okdialog.h b/src/gui/okdialog.h
index 5705be568..b6f17480b 100644
--- a/src/gui/okdialog.h
+++ b/src/gui/okdialog.h
@@ -31,6 +31,13 @@
class TextBox;
+enum
+{
+ DIALOG_OK = 0,
+ DIALOG_ERROR,
+ DIALOG_SILENCE
+};
+
/**
* An 'Ok' button dialog.
*
@@ -45,8 +52,8 @@ class OkDialog : public Window, public gcn::ActionListener
* @see Window::Window
*/
OkDialog(const std::string &title, const std::string &msg,
- bool modal = true, bool showCenter = true,
- Window *parent = nullptr);
+ int soundEvent = DIALOG_OK, bool modal = true,
+ bool showCenter = true, Window *parent = nullptr);
/**
* Called when receiving actions from the widgets.
diff --git a/src/gui/outfitwindow.cpp b/src/gui/outfitwindow.cpp
index 73484f1d5..6eaa2ac4e 100644
--- a/src/gui/outfitwindow.cpp
+++ b/src/gui/outfitwindow.cpp
@@ -190,7 +190,7 @@ void OutfitWindow::save()
outfitStr += toString(res);
if (i < OUTFIT_ITEM_COUNT - 1)
outfitStr += " ";
- outfitColorsStr += toString((int)mItemColors[o][i]);
+ outfitColorsStr += toString(static_cast<int>(mItemColors[o][i]));
if (i < OUTFIT_ITEM_COUNT - 1)
outfitColorsStr += " ";
}
diff --git a/src/gui/popupmenu.cpp b/src/gui/popupmenu.cpp
index c987843d3..5e5f310dc 100644
--- a/src/gui/popupmenu.cpp
+++ b/src/gui/popupmenu.cpp
@@ -579,6 +579,25 @@ void PopupMenu::showPopup(int x, int y, MapItem *mapItem)
showPopup(x, y);
}
+void PopupMenu::showMapPopup(int x, int y, int x2, int y2)
+{
+ mX = x2;
+ mY = y2;
+
+ mBrowserBox->clearRows();
+
+ mBrowserBox->addRow(_("Map Item"));
+
+ if (player_node && player_node->isGM())
+ mBrowserBox->addRow("warp map", _("Warp"));
+ mBrowserBox->addRow("move", _("Move"));
+ mBrowserBox->addRow("movecamera", _("Move camera"));
+ mBrowserBox->addRow("##3---");
+ mBrowserBox->addRow("cancel", _("Cancel"));
+
+ showPopup(x, y);
+}
+
void PopupMenu::showOutfitsPopup(int x, int y)
{
mX = x;
@@ -1161,6 +1180,16 @@ void PopupMenu::handleLink(const std::string &link,
}
}
}
+ else if (link == "move" && (mX || mY))
+ {
+ if (player_node)
+ player_node->navigateTo(mX, mY);
+ }
+ else if (link == "movecamera" && (mX || mY))
+ {
+ if (viewport)
+ viewport->moveCameraToPosition(mX * 32, mY * 32);
+ }
else if (link == "split" && mItem)
{
ItemAmountWindow::showWindow(ItemAmountWindow::ItemSplit,
@@ -1304,6 +1333,14 @@ void PopupMenu::handleLink(const std::string &link,
mMapItem->getX(), mMapItem->getY());
}
}
+ else if (link == "warp map" && (mX || mY))
+ {
+ if (Game::instance())
+ {
+ Net::getAdminHandler()->warp(Game::instance()->getCurrentMapName(),
+ mX, mY);
+ }
+ }
else if (link == "remove map" && mMapItem)
{
if (viewport)
@@ -2205,7 +2242,7 @@ void PlayerListener::action(const gcn::ActionEvent &event)
{
std::string comment = mDialog->getText();
Being* being = actorSpriteManager->findBeingByName(
- mNick, (ActorSprite::Type)mType);
+ mNick, static_cast<ActorSprite::Type>(mType));
if (being)
being->setComment(comment);
Being::saveComment(mNick, comment, mType);
diff --git a/src/gui/popupmenu.h b/src/gui/popupmenu.h
index 8b9107300..f616e46ee 100644
--- a/src/gui/popupmenu.h
+++ b/src/gui/popupmenu.h
@@ -142,6 +142,8 @@ class PopupMenu : public Popup, public LinkHandler
void showUndressPopup(int x, int y, Being *being, Item *item);
+ void showMapPopup(int x, int y, int x2, int y2);
+
/**
* Shows the related popup menu when right click on the chat
* at the specified mouse coordinates.
diff --git a/src/gui/register.cpp b/src/gui/register.cpp
index 2122e0d6b..bf0cb299e 100644
--- a/src/gui/register.cpp
+++ b/src/gui/register.cpp
@@ -225,7 +225,7 @@ void RegisterDialog::action(const gcn::ActionEvent &event)
mWrongDataNoticeListener->setTarget(this->mPasswordField);
}
- OkDialog *dlg = new OkDialog(_("Error"), errorMsg);
+ OkDialog *dlg = new OkDialog(_("Error"), errorMsg, DIALOG_ERROR);
dlg->addActionListener(mWrongDataNoticeListener);
}
else
diff --git a/src/gui/sdlinput.h b/src/gui/sdlinput.h
index 17cb4ea8a..f68612793 100644
--- a/src/gui/sdlinput.h
+++ b/src/gui/sdlinput.h
@@ -147,7 +147,8 @@ public:
* only use SDL and plan sticking with SDL you can safely ignore this
* function as it in the SDL case does nothing.
*/
- virtual void _pollInput() { }
+ virtual void _pollInput()
+ { }
// Inherited from Input
diff --git a/src/gui/serverdialog.cpp b/src/gui/serverdialog.cpp
index da61e105b..ed9696892 100644
--- a/src/gui/serverdialog.cpp
+++ b/src/gui/serverdialog.cpp
@@ -125,7 +125,7 @@ std::string ServersListModel::getElementAt(int elementIndex)
void ServersListModel::setVersionString(int index, const std::string &version)
{
- if (index >= (int)mVersionStrings.size())
+ if (index >= static_cast<int>(mVersionStrings.size()))
return;
if (version.empty())
@@ -632,7 +632,7 @@ void ServerDialog::saveCustomServers(const ServerInfo &currentServer,
// Make sure the current server is mentioned first
if (currentServer.isValid())
{
- if (index >= 0 && (unsigned)index < mServers.size())
+ if (index >= 0 && static_cast<unsigned>(index) < mServers.size())
{
mServers[index] = currentServer;
}
diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp
index 3408fba33..c7908a6ac 100644
--- a/src/gui/setup.cpp
+++ b/src/gui/setup.cpp
@@ -38,6 +38,7 @@
#include "gui/setup_players.h"
#include "gui/setup_relations.h"
#include "gui/setup_video.h"
+#include "gui/setup_visual.h"
#include "gui/widgets/button.h"
#include "gui/widgets/label.h"
@@ -92,6 +93,7 @@ Setup::Setup():
mPanel->enableScrollButtons(true);
mTabs.push_back(new Setup_Video);
+ mTabs.push_back(new Setup_Visual);
mTabs.push_back(new Setup_Audio);
mTabs.push_back(new Setup_Perfomance);
mTabs.push_back(new Setup_Joystick);
diff --git a/src/gui/setup_audio.cpp b/src/gui/setup_audio.cpp
index bc058faf9..69ca4e759 100644
--- a/src/gui/setup_audio.cpp
+++ b/src/gui/setup_audio.cpp
@@ -23,179 +23,125 @@
#include "gui/setup_audio.h"
#include "configuration.h"
-#include "logger.h"
#include "sound.h"
-#include "gui/okdialog.h"
+#include "gui/theme.h"
#include "gui/viewport.h"
-#include "gui/widgets/checkbox.h"
-#include "gui/widgets/label.h"
#include "gui/widgets/layouthelper.h"
-#include "gui/widgets/slider.h"
+#include "gui/widgets/namesmodel.h"
+#include "gui/widgets/scrollarea.h"
+#include "gui/widgets/setupitem.h"
#include "utils/gettext.h"
#include "debug.h"
-Setup_Audio::Setup_Audio():
- mMusicVolume(config.getIntValue("musicVolume")),
- mSfxVolume(config.getIntValue("sfxVolume")),
- mAudioEnabled(config.getBoolValue("sound")),
- mGameSoundEnabled(config.getBoolValue("playBattleSound")),
- mGuiSoundEnabled(config.getBoolValue("playGuiSound")),
- mMusicEnabled(config.getBoolValue("playMusic")),
- mMumbleEnabled(config.getBoolValue("enableMumble")),
- mDownloadEnabled(config.getBoolValue("download-music")),
- mAudioCheckBox(new CheckBox(_("Enable Audio"), mAudioEnabled)),
- mGameSoundCheckBox(new CheckBox(_("Enable game sfx"), mGameSoundEnabled)),
- mGuiSoundCheckBox(new CheckBox(_("Enable gui sfx"), mGuiSoundEnabled)),
- mMusicCheckBox(new CheckBox(_("Enable music"), mMusicEnabled)),
- mMumbleCheckBox(new CheckBox(_("Enable mumble voice chat"),
- mMumbleEnabled)),
- mDownloadMusicCheckBox(new CheckBox(_("Download music"),
- mDownloadEnabled)),
- mSfxSlider(new Slider(0, sound.getMaxVolume())),
- mMusicSlider(new Slider(0, sound.getMaxVolume()))
+class SoundsModel : public NamesModel
+{
+public:
+ SoundsModel()
+ {
+ mNames.push_back(gettext("(no sound)"));
+ Theme::fillSoundsList(mNames);
+ }
+
+ virtual ~SoundsModel()
+ { }
+};
+
+Setup_Audio::Setup_Audio()
{
setName(_("Audio"));
- setDimension(gcn::Rectangle(0, 0, 250, 200));
- gcn::Label *sfxLabel = new Label(_("Sfx volume"));
- gcn::Label *musicLabel = new Label(_("Music volume"));
+ // Do the layout
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+ place(0, 0, mScroll, 10, 10);
+
+ mSoundModel = new SoundsModel();
- mSfxSlider->setActionEventId("sfx");
- mMusicSlider->setActionEventId("music");
+ new SetupItemLabel(_("Basic settings"), "", this);
- mSfxSlider->addActionListener(this);
- mMusicSlider->addActionListener(this);
+ new SetupItemCheckBox(_("Enable Audio"), "", "sound", this, "soundEvent");
- mAudioCheckBox->setPosition(10, 10);
+ new SetupItemCheckBox(_("Enable music"), "",
+ "playMusic", this, "playMusicEvent");
- mSfxSlider->setValue(mSfxVolume);
- mMusicSlider->setValue(mMusicVolume);
+ new SetupItemCheckBox(_("Enable game sfx"), "",
+ "playBattleSound", this, "playBattleSoundEvent");
- mSfxSlider->setWidth(90);
- mMusicSlider->setWidth(90);
+ new SetupItemCheckBox(_("Enable gui sfx"), "",
+ "playGuiSound", this, "playGuiSoundEvent");
- // Do the layout
- LayoutHelper h(this);
- ContainerPlacer place = h.getPlacer(0, 0);
+ new SetupItemSlider(_("Sfx volume"), "", "sfxVolume",
+ this, "sfxVolumeEvent", 0, sound.getMaxVolume(), 150, true);
+
+ new SetupItemSlider(_("Music volume"), "", "musicVolume",
+ this, "musicVolumeEvent", 0, sound.getMaxVolume(), 150, true);
+
+ new SetupItemLabel(_("Sound effects"), "", this);
+
+ new SetupItemSound(_("Information dialog sound"), "",
+ "soundinfo", this, "soundinfoEvent", mSoundModel);
+
+ new SetupItemSound(_("Request dialog sound"), "",
+ "soundrequest", this, "soundrequestEvent", mSoundModel);
+
+ new SetupItemSound(_("Whisper message sound"), "",
+ "soundwhisper", this, "soundwhisperEvent", mSoundModel);
+
+ new SetupItemSound(_("Guild / Party message sound"), "",
+ "soundguild", this, "soundguildEvent", mSoundModel);
+
+ new SetupItemSound(_("Highlight message sound"), "",
+ "soundhighlight", this, "soundhighlightEvent", mSoundModel);
+
+ new SetupItemSound(_("Global message sound"), "",
+ "soundglobal", this, "soundglobalEvent", mSoundModel);
+
+ new SetupItemSound(_("Error message sound"), "",
+ "sounderror", this, "sounderrorEvent", mSoundModel);
+
+ new SetupItemSound(_("Trade request sound"), "",
+ "soundtrade", this, "soundtradeEvent", mSoundModel);
+
+ new SetupItemLabel(_("Other"), "", this);
+
+ new SetupItemCheckBox(_("Enable mumble voice chat"), "",
+ "enableMumble", this, "enableMumbleEvent");
- place(0, 0, mAudioCheckBox);
- place(0, 1, mMusicCheckBox);
- place(0, 2, mGameSoundCheckBox);
- place(0, 3, mGuiSoundCheckBox);
- place(0, 4, mSfxSlider);
- place(1, 4, sfxLabel);
- place(0, 5, mMusicSlider);
- place(1, 5, musicLabel);
- place(0, 6, mMumbleCheckBox);
- place(0, 7, mDownloadMusicCheckBox);
-
- setDimension(gcn::Rectangle(0, 0, 365, 280));
+ new SetupItemCheckBox(_("Download music"), "",
+ "download-music", this, "download-musicEvent");
+
+ setDimension(gcn::Rectangle(0, 0, 550, 350));
}
-void Setup_Audio::apply()
+Setup_Audio::~Setup_Audio()
{
- mAudioEnabled = mAudioCheckBox->isSelected();
- mGameSoundEnabled = mGameSoundCheckBox->isSelected();
- mGuiSoundEnabled = mGuiSoundCheckBox->isSelected();
- mMusicEnabled = mMusicCheckBox->isSelected();
- mMumbleEnabled = mMumbleCheckBox->isSelected();
- mDownloadEnabled = mDownloadMusicCheckBox->isSelected();
- mSfxVolume = config.getIntValue("sfxVolume");
- mMusicVolume = config.getIntValue("musicVolume");
-
- config.setValue("sound", mAudioEnabled);
- config.setValue("playBattleSound", mGameSoundEnabled);
- config.setValue("playGuiSound", mGuiSoundEnabled);
-
- config.setValue("enableMumble", mMumbleEnabled);
-
- // Display a message if user has selected to download music,
- // And if downloadmusic is not already enabled
- if (mDownloadEnabled && !config.getBoolValue("download-music"))
- {
- new OkDialog(_("Notice"), _("You may have to restart your client "
- "if you want to download new music"));
- }
- config.setValue("download-music", mDownloadEnabled);
+ delete mSoundModel;
+ mSoundModel = nullptr;
+}
- if (mAudioEnabled)
+void Setup_Audio::apply()
+{
+ SetupTabScroll::apply();
+ if (config.getBoolValue("sound"))
{
- try
- {
- sound.init();
- }
- catch (const char *err)
+ sound.init();
+ if (viewport && config.getBoolValue("playMusic"))
{
- new OkDialog(_("Sound Engine"), err);
- logger->log("Warning: %s", err);
+ Map *map = viewport->getMap();
+ if (map)
+ sound.playMusic(map->getMusicFile());
}
- if (mMusicEnabled)
- {
- if (viewport && !config.getBoolValue("playMusic"))
- {
- Map *map = viewport->getMap();
- if (map)
- {
- config.setValue("playMusic", mMusicEnabled);
- sound.playMusic(map->getMusicFile());
- }
- }
- }
- else if (config.getBoolValue("playMusic"))
+ else
{
sound.stopMusic();
}
-
}
else
{
sound.close();
}
-
- config.setValue("playMusic", mMusicEnabled);
-}
-
-void Setup_Audio::cancel()
-{
- mAudioCheckBox->setSelected(mAudioEnabled);
- mGameSoundCheckBox->setSelected(mGameSoundEnabled);
- mGuiSoundCheckBox->setSelected(mGuiSoundEnabled);
- mMusicCheckBox->setSelected(mMusicEnabled);
- mMumbleCheckBox->setSelected(mMumbleEnabled);
- mDownloadMusicCheckBox->setSelected(mDownloadEnabled);
-
- sound.setSfxVolume(mSfxVolume);
- mSfxSlider->setValue(mSfxVolume);
-
- sound.setMusicVolume(mMusicVolume);
- mMusicSlider->setValue(mMusicVolume);
-
- config.setValue("sound", mAudioEnabled);
- config.setValue("playBattleSound", mGameSoundEnabled);
- config.setValue("playGuiSound", mGuiSoundEnabled);
- config.setValue("enableMumble", mMumbleEnabled);
- config.setValue("download-music", mDownloadEnabled);
- config.setValue("sfxVolume", mSfxVolume);
- config.setValue("musicVolume", mMusicVolume);
- config.setValue("playMusic", mMusicEnabled);
-}
-
-void Setup_Audio::action(const gcn::ActionEvent &event)
-{
- if (event.getId() == "sfx")
- {
- config.setValueInt("sfxVolume",
- static_cast<int>(mSfxSlider->getValue()));
- sound.setSfxVolume(static_cast<int>(mSfxSlider->getValue()));
- }
- else if (event.getId() == "music")
- {
- config.setValueInt("musicVolume",
- static_cast<int>(mMusicSlider->getValue()));
- sound.setMusicVolume(static_cast<int>(mMusicSlider->getValue()));
- }
}
diff --git a/src/gui/setup_audio.h b/src/gui/setup_audio.h
index 88869d730..21b661bcb 100644
--- a/src/gui/setup_audio.h
+++ b/src/gui/setup_audio.h
@@ -25,30 +25,21 @@
#include "guichanfwd.h"
-#include "gui/widgets/setuptab.h"
+#include "gui/widgets/setuptabscroll.h"
#include <guichan/actionlistener.hpp>
-class Setup_Audio : public SetupTab
+class Setup_Audio : public SetupTabScroll
{
public:
Setup_Audio();
- void apply();
- void cancel();
+ ~Setup_Audio();
- void action(const gcn::ActionEvent &event);
+ void apply();
private:
- int mMusicVolume, mSfxVolume;
- bool mAudioEnabled, mGameSoundEnabled, mGuiSoundEnabled;
- bool mMusicEnabled, mMumbleEnabled;
- bool mDownloadEnabled;
-
- gcn::CheckBox *mAudioCheckBox, *mGameSoundCheckBox, *mGuiSoundCheckBox;
- gcn::CheckBox *mMusicCheckBox, *mMumbleCheckBox;
- gcn::CheckBox *mDownloadMusicCheckBox;
- gcn::Slider *mSfxSlider, *mMusicSlider;
+ gcn::ListModel *mSoundModel;
};
#endif
diff --git a/src/gui/setup_joystick.cpp b/src/gui/setup_joystick.cpp
index a3240282a..cb3ff9341 100644
--- a/src/gui/setup_joystick.cpp
+++ b/src/gui/setup_joystick.cpp
@@ -31,6 +31,7 @@
#include "gui/widgets/dropdown.h"
#include "gui/widgets/label.h"
#include "gui/widgets/layouthelper.h"
+#include "gui/widgets/namesmodel.h"
#include "utils/gettext.h"
@@ -40,32 +41,6 @@
extern Joystick *joystick;
-class NamesModel : public gcn::ListModel
-{
- public:
- NamesModel()
- { }
-
- virtual ~NamesModel()
- { }
-
- virtual int getNumberOfElements()
- {
- return static_cast<int>(mNames.size());
- }
-
- virtual std::string getElementAt(int i)
- {
- if (i >= getNumberOfElements() || i < 0)
- return _("???");
-
- return mNames[i];
- }
-
- std::vector<std::string> mNames;
-};
-
-
Setup_Joystick::Setup_Joystick():
mCalibrateLabel(new Label(_("Press the button to start calibration"))),
mCalibrateButton(new Button(_("Calibrate"), "calibrate", this)),
@@ -77,7 +52,7 @@ Setup_Joystick::Setup_Joystick():
{
setName(_("Joystick"));
- Joystick::getNames(mNamesModel->mNames);
+ Joystick::getNames(mNamesModel->getNames());
mOriginalJoystickEnabled = config.getBoolValue("joystickEnabled");
mJoystickEnabled->setSelected(mOriginalJoystickEnabled);
@@ -95,7 +70,7 @@ Setup_Joystick::Setup_Joystick():
else
{
unsigned sel = config.getIntValue("selectedJoystick");
- if (sel >= mNamesModel->mNames.size())
+ if (sel >= mNamesModel->size())
sel = 0;
mNamesDropDown->setSelected(sel);
}
diff --git a/src/gui/setup_keyboard.cpp b/src/gui/setup_keyboard.cpp
index bdd7c2083..ef024c5d9 100644
--- a/src/gui/setup_keyboard.cpp
+++ b/src/gui/setup_keyboard.cpp
@@ -131,7 +131,7 @@ void Setup_Keyboard::apply()
if (keyboard.hasConflicts())
{
new OkDialog(_("Key Conflict(s) Detected."),
- keyboard.getBindError());
+ keyboard.getBindError(), DIALOG_ERROR);
}
keyboard.setEnabled(true);
keyboard.store();
diff --git a/src/gui/setup_other.cpp b/src/gui/setup_other.cpp
index 3ea5f4e4a..148037732 100644
--- a/src/gui/setup_other.cpp
+++ b/src/gui/setup_other.cpp
@@ -183,6 +183,11 @@ Setup_Other::Setup_Other()
new SetupItemCheckBox(_("Hide shield sprite"), "", "hideShield",
this, "hideShieldEvent");
+#if !defined(_WIN32)
+ new SetupItemCheckBox(_("Use FBO for screenshots (only for opengl)"),
+ "", "usefbo", this, "usefboEvent");
+#endif
+
new SetupItemCheckBox(_("Show background"), "", "showBackground",
this, "showBackgroundEvent");
diff --git a/src/gui/setup_relations.cpp b/src/gui/setup_relations.cpp
index 47d53620c..d9f7a362d 100644
--- a/src/gui/setup_relations.cpp
+++ b/src/gui/setup_relations.cpp
@@ -80,7 +80,8 @@ static const char *RELATION_NAMES[PlayerRelation::RELATIONS_NR] =
class PlayerRelationListModel : public gcn::ListModel
{
public:
- virtual ~PlayerRelationListModel() { }
+ virtual ~PlayerRelationListModel()
+ { }
virtual int getNumberOfElements()
{
@@ -194,7 +195,7 @@ public:
std::string getPlayerAt(int index) const
{
- if (index < 0 || index >= (signed)mPlayers->size())
+ if (index < 0 || index >= static_cast<signed>(mPlayers->size()))
return "";
return (*mPlayers)[index];
}
@@ -211,7 +212,8 @@ protected:
class IgnoreChoicesListModel : public gcn::ListModel
{
public:
- virtual ~IgnoreChoicesListModel() { }
+ virtual ~IgnoreChoicesListModel()
+ { }
virtual int getNumberOfElements()
{
diff --git a/src/gui/setup_theme.cpp b/src/gui/setup_theme.cpp
index d4a1d5652..7386f496a 100644
--- a/src/gui/setup_theme.cpp
+++ b/src/gui/setup_theme.cpp
@@ -29,10 +29,11 @@
#include "gui/widgets/button.h"
#include "gui/widgets/checkbox.h"
+#include "gui/widgets/dropdown.h"
#include "gui/widgets/label.h"
#include "gui/widgets/layouthelper.h"
+#include "gui/widgets/namesmodel.h"
#include "gui/widgets/textfield.h"
-#include "gui/widgets/dropdown.h"
#include "configuration.h"
#include "localplayer.h"
@@ -53,32 +54,6 @@ const char* ACTION_HELP_FONT = "help font";
const char* ACTION_SECURE_FONT = "secure font";
const char* ACTION_JAPAN_FONT = "japan font";
-class NamesModel : public gcn::ListModel
-{
-public:
- NamesModel()
- {
- }
-
- virtual ~NamesModel() { }
-
- virtual int getNumberOfElements()
- {
- return static_cast<int>(mNames.size());
- }
-
- virtual std::string getElementAt(int i)
- {
- if (i >= getNumberOfElements() || i < 0)
- return _("???");
-
- return mNames[i];
- }
-
-protected:
- std::vector<std::string> mNames;
-};
-
class ThemesModel : public NamesModel
{
public:
@@ -374,8 +349,8 @@ void Setup_Theme::apply()
if (config.getValue("theme",
config.getValue("selectedSkin", "")) != mTheme)
{
- new OkDialog(_("Theme Changed"),
- _("Restart your client for the change to take effect."));
+ new OkDialog(_("Theme Changed"), _("Restart your client for "
+ "the change to take effect."));
}
config.setValue("selectedSkin", "");
diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp
index cc3063a68..24d42c83d 100644
--- a/src/gui/setup_video.cpp
+++ b/src/gui/setup_video.cpp
@@ -28,7 +28,6 @@
#include "localplayer.h"
#include "logger.h"
#include "main.h"
-#include "particle.h"
#include "gui/gui.h"
#include "gui/okdialog.h"
@@ -40,6 +39,7 @@
#include "gui/widgets/listbox.h"
#include "gui/widgets/scrollarea.h"
#include "gui/widgets/slider.h"
+#include "gui/widgets/sliderlist.h"
#include "gui/widgets/textfield.h"
#include "gui/widgets/dropdown.h"
@@ -214,105 +214,26 @@ public:
}
};
-static const char *speechModeToString(Being::Speech mode)
-{
- switch (mode)
- {
- case Being::NO_SPEECH:
- default:
- return _("No text");
- case Being::TEXT_OVERHEAD:
- return _("Text");
- case Being::NO_NAME_IN_BUBBLE:
- return _("Bubbles, no names");
- case Being::NAME_IN_BUBBLE:
- return _("Bubbles with names");
- }
-}
-
-const char *Setup_Video::overlayDetailToString(int detail)
-{
- if (detail == -1)
- detail = config.getIntValue("OverlayDetail");
-
- switch (detail)
- {
- case 0:
- return _("off");
- case 1:
- return _("low");
- case 2:
- return _("high");
- default:
- return "";
- }
- return "";
-}
-
-const char *Setup_Video::particleDetailToString(int detail)
-{
- if (detail == -1)
- detail = 3 - config.getIntValue("particleEmitterSkip");
-
- switch (detail)
- {
- case 0:
- return _("low");
- case 1:
- return _("medium");
- case 2:
- return _("high");
- case 3:
- return _("max");
- default:
- return "";
- }
- return "";
-}
-
Setup_Video::Setup_Video():
mFullScreenEnabled(config.getBoolValue("screen")),
mOpenGLEnabled(config.getIntValue("opengl")),
mCustomCursorEnabled(config.getBoolValue("customcursor")),
- mParticleEffectsEnabled(config.getBoolValue("particleeffects")),
- mPickupChatEnabled(config.getBoolValue("showpickupchat")),
- mPickupParticleEnabled(config.getBoolValue("showpickupparticle")),
- mOpacity(config.getFloatValue("guialpha")),
mFps(config.getIntValue("fpslimit")),
mAltFps(config.getIntValue("altfpslimit")),
mEnableResize(config.getBoolValue("enableresize")),
mNoFrame(config.getBoolValue("noframe")),
- mSpeechMode(static_cast<Being::Speech>(
- config.getIntValue("speech"))),
mModeListModel(new ModeListModel),
mModeList(new ListBox(mModeListModel)),
mFsCheckBox(new CheckBox(_("Full screen"), mFullScreenEnabled)),
mCustomCursorCheckBox(new CheckBox(_("Custom cursor"),
mCustomCursorEnabled)),
- mParticleEffectsCheckBox(new CheckBox(_("Particle effects"),
- mParticleEffectsEnabled)),
- mPickupNotifyLabel(new Label(_("Show pickup notification"))),
- // TRANSLATORS: Refers to "Show own name"
- mPickupChatCheckBox(new CheckBox(_("in chat"), mPickupChatEnabled)),
- // TRANSLATORS: Refers to "Show own name"
- mPickupParticleCheckBox(new CheckBox(_("as particle"),
- mPickupParticleEnabled)),
mEnableResizeCheckBox(new CheckBox(_("Enable resize"), mEnableResize)),
mNoFrameCheckBox(new CheckBox(_("No frame"), mNoFrame)),
- mSpeechSlider(new Slider(0, 3)),
- mSpeechLabel(new Label("")),
- mAlphaSlider(new Slider(0.1, 1.0)),
mFpsCheckBox(new CheckBox(_("FPS limit:"))),
mFpsSlider(new Slider(2, 160)),
mFpsLabel(new Label),
mAltFpsSlider(new Slider(2, 160)),
mAltFpsLabel(new Label(_("Alt FPS limit: "))),
- mOverlayDetail(config.getIntValue("OverlayDetail")),
- mOverlayDetailSlider(new Slider(0, 2)),
- mOverlayDetailField(new Label),
- mParticleDetail(3 - config.getIntValue("particleEmitterSkip")),
- mParticleDetailSlider(new Slider(0, 3)),
- mParticleDetailField(new Label),
mDialog(nullptr)
{
setName(_("Video"));
@@ -321,11 +242,6 @@ Setup_Video::Setup_Video():
scrollArea->setWidth(150);
scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
- speechLabel = new Label(_("Overhead text"));
- alphaLabel = new Label(_("Gui opacity"));
- overlayDetailLabel = new Label(_("Ambient FX"));
- particleDetailLabel = new Label(_("Particle detail"));
-
mOpenGLListModel = new OpenGLListModel;
mOpenGLDropDown = new DropDown(mOpenGLListModel),
mOpenGLDropDown->setSelected(mOpenGLEnabled);
@@ -336,9 +252,6 @@ Setup_Video::Setup_Video():
mOpenGLDropDown->setSelected(0);
#endif
- mAlphaSlider->setValue(mOpacity);
- mAlphaSlider->setWidth(90);
-
mFpsLabel->setCaption(mFps > 0 ? toString(mFps) : _("None"));
mFpsLabel->setWidth(60);
mAltFpsLabel->setCaption(_("Alt FPS limit: ") + (mAltFps > 0
@@ -357,57 +270,28 @@ Setup_Video::Setup_Video():
mModeList->setActionEventId("videomode");
mCustomCursorCheckBox->setActionEventId("customcursor");
- mParticleEffectsCheckBox->setActionEventId("particleeffects");
- mPickupChatCheckBox->setActionEventId("pickupchat");
- mPickupParticleCheckBox->setActionEventId("pickupparticle");
- mAlphaSlider->setActionEventId("guialpha");
mFpsCheckBox->setActionEventId("fpslimitcheckbox");
- mSpeechSlider->setActionEventId("speech");
mFpsSlider->setActionEventId("fpslimitslider");
mAltFpsSlider->setActionEventId("altfpslimitslider");
- mOverlayDetailSlider->setActionEventId("overlaydetailslider");
- mOverlayDetailField->setActionEventId("overlaydetailfield");
- mParticleDetailSlider->setActionEventId("particledetailslider");
- mParticleDetailField->setActionEventId("particledetailfield");
mOpenGLDropDown->setActionEventId("opengl");
mEnableResizeCheckBox->setActionEventId("enableresize");
mNoFrameCheckBox->setActionEventId("noframe");
mModeList->addActionListener(this);
mCustomCursorCheckBox->addActionListener(this);
- mParticleEffectsCheckBox->addActionListener(this);
- mPickupChatCheckBox->addActionListener(this);
- mPickupParticleCheckBox->addActionListener(this);
- mAlphaSlider->addActionListener(this);
mFpsCheckBox->addActionListener(this);
- mSpeechSlider->addActionListener(this);
mFpsSlider->addActionListener(this);
mAltFpsSlider->addActionListener(this);
- mOverlayDetailSlider->addActionListener(this);
- mOverlayDetailField->addKeyListener(this);
- mParticleDetailSlider->addActionListener(this);
- mParticleDetailField->addKeyListener(this);
mOpenGLDropDown->addActionListener(this);
mEnableResizeCheckBox->addActionListener(this);
mNoFrameCheckBox->addActionListener(this);
- mSpeechLabel->setCaption(speechModeToString(mSpeechMode));
- mSpeechSlider->setValue(mSpeechMode);
-
- mOverlayDetailField->setCaption(overlayDetailToString(mOverlayDetail));
- mOverlayDetailSlider->setValue(mOverlayDetail);
-
- mParticleDetailField->setCaption(particleDetailToString(mParticleDetail));
- mParticleDetailSlider->setValue(mParticleDetail);
-
// Do the layout
LayoutHelper h(this);
ContainerPlacer place = h.getPlacer(0, 0);
- place(0, 0, scrollArea, 1, 6).setPadding(2);
- place(0, 6, mOpenGLDropDown, 1);
-
-// place(0, 6, mHwAccelCheckBox, 6);
+ place(0, 0, scrollArea, 1, 5).setPadding(2);
+ place(0, 5, mOpenGLDropDown, 1);
place(1, 0, mFsCheckBox, 2);
@@ -416,33 +300,34 @@ Setup_Video::Setup_Video():
place(1, 2, mEnableResizeCheckBox, 2);
place(1, 3, mNoFrameCheckBox, 2);
- place(1, 4, mParticleEffectsCheckBox, 2);
- place(1, 5, mPickupNotifyLabel, 4);
- place(1, 6, mPickupChatCheckBox, 1);
- place(2, 6, mPickupParticleCheckBox, 2);
+// place(1, 5, mPickupNotifyLabel, 4);
+// place(1, 6, mPickupChatCheckBox, 1);
+// place(2, 6, mPickupParticleCheckBox, 2);
- place(0, 7, mAlphaSlider);
- place(1, 7, alphaLabel, 3);
+// place(0, 7, mAlphaSlider);
+// place(1, 7, alphaLabel, 3);
- place(0, 9, mFpsSlider);
- place(1, 9, mFpsCheckBox).setPadding(3);
- place(2, 9, mFpsLabel).setPadding(1);
+ place(0, 6, mFpsSlider);
+ place(1, 6, mFpsCheckBox).setPadding(3);
+ place(2, 6, mFpsLabel).setPadding(1);
- place(0, 10, mAltFpsSlider);
- place(1, 10, mAltFpsLabel).setPadding(3);
+ place(0, 7, mAltFpsSlider);
+ place(1, 7, mAltFpsLabel).setPadding(3);
- place(0, 11, mSpeechSlider);
- place(1, 11, speechLabel);
- place(2, 11, mSpeechLabel, 3).setPadding(2);
+// place(0, 11, mSpeechSlider);
+// place(1, 11, speechLabel);
+// place(2, 11, mSpeechLabel, 3).setPadding(2);
- place(0, 12, mOverlayDetailSlider);
- place(1, 12, overlayDetailLabel);
- place(2, 12, mOverlayDetailField, 3).setPadding(2);
+// place(0, 12, mOverlayDetailSlider);
+// place(1, 12, overlayDetailLabel);
+// place(2, 12, mOverlayDetailField, 3).setPadding(2);
- place(0, 13, mParticleDetailSlider);
- place(1, 13, particleDetailLabel);
- place(2, 13, mParticleDetailField, 3).setPadding(2);
+// place(0, 13, mParticleEffectsCheckBox, 5);
+
+// place(0, 14, mParticleDetailSlider);
+// place(1, 14, particleDetailLabel);
+// place(2, 14, mParticleDetailField, 3).setPadding(2);
int width = 600;
@@ -500,7 +385,7 @@ void Setup_Video::apply()
" and restoration of old mode also "
"failed!") << std::endl;
}
- logger->error(errorMsg.str());
+ logger->safeError(errorMsg.str());
}
}
#if defined(WIN32) || defined(__APPLE__)
@@ -508,7 +393,7 @@ void Setup_Video::apply()
else
{
new OkDialog(_("Switching to Full Screen"),
- _("Restart needed for changes to take effect."));
+ _("Restart needed for changes to take effect."));
}
#endif
config.setValue("screen", fullscreen);
@@ -521,7 +406,7 @@ void Setup_Video::apply()
// OpenGL can currently only be changed by restarting, notify user.
new OkDialog(_("Changing to OpenGL"),
- _("Applying change to OpenGL requires restart."));
+ _("Applying change to OpenGL requires restart."));
}
mFps = mFpsCheckBox->isSelected() ?
@@ -540,15 +425,8 @@ void Setup_Video::apply()
// We sync old and new values at apply time
mFullScreenEnabled = config.getBoolValue("screen");
mCustomCursorEnabled = config.getBoolValue("customcursor");
- mParticleEffectsEnabled = config.getBoolValue("particleeffects");
- mSpeechMode = static_cast<Being::Speech>(
- config.getIntValue("speech"));
- mOpacity = config.getFloatValue("guialpha");
- mOverlayDetail = config.getIntValue("OverlayDetail");
mOpenGLEnabled = config.getIntValue("opengl");
- mPickupChatEnabled = config.getBoolValue("showpickupchat");
- mPickupParticleEnabled = config.getBoolValue("showpickupparticle");
mEnableResize = config.getBoolValue("enableresize");
mNoFrame = config.getBoolValue("noframe");
}
@@ -559,15 +437,10 @@ void Setup_Video::cancel()
mFsCheckBox->setSelected(mFullScreenEnabled);
mOpenGLDropDown->setSelected(mOpenGLEnabled);
mCustomCursorCheckBox->setSelected(mCustomCursorEnabled);
- mParticleEffectsCheckBox->setSelected(mParticleEffectsEnabled);
mFpsSlider->setValue(mFps);
mFpsSlider->setEnabled(mFps > 0);
mAltFpsSlider->setValue(mAltFps);
mAltFpsSlider->setEnabled(mAltFps > 0);
- mSpeechSlider->setValue(mSpeechMode);
- mAlphaSlider->setValue(mOpacity);
- mOverlayDetailSlider->setValue(mOverlayDetail);
- mParticleDetailSlider->setValue(mParticleDetail);
mFpsLabel->setCaption(mFpsCheckBox->isSelected()
? toString(mFps) : _("None"));
mAltFpsLabel->setCaption(_("Alt FPS limit: ") + toString(mAltFps));
@@ -584,13 +457,7 @@ void Setup_Video::cancel()
config.setValue("screenheight", mainGraphics->mHeight);
config.setValue("customcursor", mCustomCursorEnabled);
- config.setValue("particleeffects", mParticleEffectsEnabled);
- config.setValue("speech", static_cast<int>(mSpeechMode));
- config.setValue("guialpha", mOpacity);
- Image::setEnableAlpha(mOpacity != 1.0f);
config.setValue("opengl", mOpenGLEnabled);
- config.setValue("showpickupchat", mPickupChatEnabled);
- config.setValue("showpickupparticle", mPickupParticleEnabled);
config.setValue("enableresize", mEnableResize);
config.setValue("noframe", mNoFrame);
}
@@ -631,13 +498,17 @@ void Setup_Video::action(const gcn::ActionEvent &event)
{
#if defined(_WIN32)
if (width < mainGraphics->mWidth || height < mainGraphics->mHeight)
+ {
new OkDialog(_("Screen Resolution Changed"),
- _("Restart your client for the change to take effect.")
- + std::string("\n") +
- _("Some windows may be moved to fit the lowered resolution."));
+ _("Restart your client for the change to take effect.")
+ + std::string("\n") + _("Some windows may be moved to "
+ "fit the lowered resolution."));
+ }
else
+ {
new OkDialog(_("Screen Resolution Changed"),
- _("Restart your client for the change to take effect."));
+ _("Restart your client for the change to take effect."));
+ }
#else
Client::resize(width, height);
#endif
@@ -653,57 +524,10 @@ void Setup_Video::action(const gcn::ActionEvent &event)
{
mDialog = nullptr;
}
- else if (id == "guialpha")
- {
- config.setValue("guialpha", mAlphaSlider->getValue());
- Image::setEnableAlpha(config.getFloatValue("guialpha") != 1.0f);
- }
else if (id == "customcursor")
{
config.setValue("customcursor", mCustomCursorCheckBox->isSelected());
}
- else if (id == "particleeffects")
- {
- config.setValue("particleeffects",
- mParticleEffectsCheckBox->isSelected());
- Particle::enabled = mParticleEffectsCheckBox->isSelected();
-
- if (Game::instance())
- {
- new OkDialog(_("Particle Effect Settings Changed."),
- _("Changes will take effect on map change."));
- }
- }
- else if (id == "pickupchat")
- {
- config.setValue("showpickupchat", mPickupChatCheckBox->isSelected());
- }
- else if (id == "pickupparticle")
- {
- config.setValue("showpickupparticle",
- mPickupParticleCheckBox->isSelected());
- }
- else if (id == "speech")
- {
- Being::Speech val = static_cast<Being::Speech>(
- mSpeechSlider->getValue());
- mSpeechLabel->setCaption(speechModeToString(val));
- mSpeechSlider->setValue(val);
- config.setValue("speech", static_cast<int>(val));
- }
- else if (id == "overlaydetailslider")
- {
- int val = static_cast<int>(mOverlayDetailSlider->getValue());
- mOverlayDetailField->setCaption(overlayDetailToString(val));
- config.setValue("OverlayDetail", val);
- }
- else if (id == "particledetailslider")
- {
- int val = static_cast<int>(mParticleDetailSlider->getValue());
- mParticleDetailField->setCaption(particleDetailToString(val));
- config.setValue("particleEmitterSkip", 3 - val);
- Particle::emitterSkip = 4 - val;
- }
else if (id == "fpslimitcheckbox" || id == "fpslimitslider")
{
int tempFps = static_cast<int>(mFpsSlider->getValue());
diff --git a/src/gui/setup_video.h b/src/gui/setup_video.h
index 31d45d93d..0e7bc0f21 100644
--- a/src/gui/setup_video.h
+++ b/src/gui/setup_video.h
@@ -46,68 +46,38 @@ class Setup_Video : public SetupTab, public gcn::KeyListener
void action(const gcn::ActionEvent &event);
- static const char *overlayDetailToString(int detail = -1);
-
- static const char *particleDetailToString(int detail = -1);
-
virtual void externalUpdated();
private:
bool mFullScreenEnabled;
int mOpenGLEnabled;
bool mCustomCursorEnabled;
- bool mParticleEffectsEnabled;
- bool mPickupChatEnabled;
- bool mPickupParticleEnabled;
- float mOpacity;
int mFps;
int mAltFps;
bool mEnableResize;
bool mNoFrame;
- Being::Speech mSpeechMode;
ModeListModel *mModeListModel;
OpenGLListModel *mOpenGLListModel;
- gcn::Label *speechLabel;
- gcn::Label *alphaLabel;
gcn::Label *scrollRadiusLabel;
gcn::Label *scrollLazinessLabel;
- gcn::Label *overlayDetailLabel;
- gcn::Label *particleDetailLabel;
gcn::ListBox *mModeList;
gcn::CheckBox *mFsCheckBox;
gcn::DropDown *mOpenGLDropDown;
gcn::CheckBox *mCustomCursorCheckBox;
- gcn::CheckBox *mParticleEffectsCheckBox;
-
- gcn::Label *mPickupNotifyLabel;
- gcn::CheckBox *mPickupChatCheckBox;
- gcn::CheckBox *mPickupParticleCheckBox;
gcn::CheckBox *mEnableResizeCheckBox;
gcn::CheckBox *mNoFrameCheckBox;
- gcn::Slider *mSpeechSlider;
- gcn::Label *mSpeechLabel;
- gcn::Slider *mAlphaSlider;
gcn::CheckBox *mFpsCheckBox;
gcn::Slider *mFpsSlider;
gcn::Label *mFpsLabel;
-// gcn::CheckBox *mAltFpsCheckBox;
gcn::Slider *mAltFpsSlider;
gcn::Label *mAltFpsLabel;
- int mOverlayDetail;
- gcn::Slider *mOverlayDetailSlider;
- gcn::Label *mOverlayDetailField;
-
- int mParticleDetail;
- gcn::Slider *mParticleDetailSlider;
- gcn::Label *mParticleDetailField;
-
TextDialog *mDialog;
};
diff --git a/src/gui/setup_visual.cpp b/src/gui/setup_visual.cpp
new file mode 100644
index 000000000..68704956a
--- /dev/null
+++ b/src/gui/setup_visual.cpp
@@ -0,0 +1,118 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009-2010 Andrei Karas
+ * Copyright (C) 2011-2012 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "gui/setup_visual.h"
+
+#include "gui/widgets/layouthelper.h"
+#include "gui/widgets/scrollarea.h"
+
+#include "client.h"
+
+#include "utils/gettext.h"
+
+#include "debug.h"
+
+Setup_Visual::Setup_Visual()
+{
+ setName(_("Visual"));
+ // Do the layout
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+ place(0, 0, mScroll, 10, 10);
+
+ mPreferredFirstItemSize = 150;
+
+ new SetupItemLabel(_("Notifications"), "", this);
+
+ new SetupItemCheckBox(_("Show pickup notifications in chat"), "",
+ "showpickupchat", this, "showpickupchatEvent");
+
+ new SetupItemCheckBox(_("Show pickup notifications as particle effects"),
+ "", "showpickupparticle", this, "showpickupparticleEvent");
+
+ new SetupItemLabel(_("Effects"), "", this);
+
+ new SetupItemCheckBox(_("Grab mouse and keyboard input"),
+ "", "grabinput", this, "grabinputEvent");
+
+ new SetupItemSlider(_("Gui opacity"), "", "guialpha",
+ this, "guialphaEvent", 0.1, 1.0, 150, true);
+
+ mSpeachList = new SetupItemNames();
+ mSpeachList->push_back(_("No text"));
+ mSpeachList->push_back(_("Text"));
+ mSpeachList->push_back(_("Bubbles, no names"));
+ mSpeachList->push_back(_("Bubbles with names"));
+ new SetupItemSlider2(_("Overhead text"), "", "speech", this,
+ "speechEvent", 0, 3, mSpeachList);
+
+ mAmbientFxList = new SetupItemNames();
+ mAmbientFxList->push_back(_("off"));
+ mAmbientFxList->push_back(_("low"));
+ mAmbientFxList->push_back(_("high"));
+ new SetupItemSlider2(_("Ambient FX"), "", "OverlayDetail", this,
+ "OverlayDetailEvent", 0, 2, mAmbientFxList);
+
+ new SetupItemCheckBox(_("Particle effects"), "",
+ "particleeffects", this, "particleeffectsEvent");
+
+ mParticleList = new SetupItemNames();
+ mParticleList->push_back(_("low"));
+ mParticleList->push_back(_("medium"));
+ mParticleList->push_back(_("high"));
+ mParticleList->push_back(_("max"));
+ (new SetupItemSlider2(_("Particle detail"), "", "particleEmitterSkip",
+ this, "particleEmitterSkipEvent", 0, 3,
+ mParticleList, true))->setInvertValue(3);
+
+ new SetupItemLabel(_("Other"), "", this);
+
+ new SetupItemSlider(_("Gamma"), "", "gamma",
+ this, "gammeEvent", 1, 20, 350, true);
+
+ mVSyncList = new SetupItemNames();
+ mVSyncList->push_back(_("default"));
+ mVSyncList->push_back(_("off"));
+ mVSyncList->push_back(_("on"));
+ new SetupItemSlider2(_("Vsync"), "", "vsync", this,
+ "vsyncEvent", 0, 2, mVSyncList);
+
+ setDimension(gcn::Rectangle(0, 0, 550, 350));
+}
+
+Setup_Visual::~Setup_Visual()
+{
+ delete mSpeachList;
+ mSpeachList = nullptr;
+ delete mAmbientFxList;
+ mAmbientFxList = nullptr;
+ delete mParticleList;
+ mParticleList = nullptr;
+ delete mVSyncList;
+ mVSyncList = nullptr;
+}
+
+void Setup_Visual::apply()
+{
+ SetupTabScroll::apply();
+ Client::applyGrabMode();
+}
diff --git a/src/gui/setup_visual.h b/src/gui/setup_visual.h
new file mode 100644
index 000000000..028f366b8
--- /dev/null
+++ b/src/gui/setup_visual.h
@@ -0,0 +1,50 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009-2010 Andrei Karas
+ * Copyright (C) 2011-2012 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef GUI_SETUP_VISUAL_H
+#define GUI_SETUP_VISUAL_H
+
+#include "guichanfwd.h"
+
+#include "gui/widgets/setupitem.h"
+#include "gui/widgets/setuptabscroll.h"
+
+class Setup_Visual : public SetupTabScroll
+{
+ public:
+ Setup_Visual();
+
+ ~Setup_Visual();
+
+ void apply();
+
+ private:
+ SetupItemNames *mSpeachList;
+
+ SetupItemNames *mAmbientFxList;
+
+ SetupItemNames *mParticleList;
+
+ SetupItemNames *mVSyncList;
+};
+
+#endif
diff --git a/src/gui/shopwindow.cpp b/src/gui/shopwindow.cpp
index 1a27b8b0c..01b589ab6 100644
--- a/src/gui/shopwindow.cpp
+++ b/src/gui/shopwindow.cpp
@@ -753,7 +753,7 @@ void ShopWindow::processRequest(std::string nick, std::string data, int mode)
if (config.getBoolValue("autoShop"))
{
- sound.playGuiSfx("system/newmessage.ogg");
+ sound.playGuiSound(SOUND_TRADE);
startTrade();
}
else
diff --git a/src/gui/socialwindow.cpp b/src/gui/socialwindow.cpp
index 287089790..f0ac9e128 100644
--- a/src/gui/socialwindow.cpp
+++ b/src/gui/socialwindow.cpp
@@ -1630,13 +1630,13 @@ void SocialWindow::showPartyCreate()
if (player_node->getParty())
{
new OkDialog(_("Create Party"),
- _("Cannot create party. You are already in a party"),
- this);
+ _("Cannot create party. You are already in a party"),
+ DIALOG_ERROR, true, true, this);
return;
}
mPartyCreateDialog = new TextDialog(_("Party Name"),
- _("Choose your party's name."), this);
+ _("Choose your party's name."), this);
mPartyCreateDialog->setActionEventId("create party");
mPartyCreateDialog->addActionListener(this);
}
diff --git a/src/gui/textcommandeditor.cpp b/src/gui/textcommandeditor.cpp
index 7b9442318..3f98b4ea3 100644
--- a/src/gui/textcommandeditor.cpp
+++ b/src/gui/textcommandeditor.cpp
@@ -127,7 +127,8 @@ const char *MAGIC_SCHOOL_TEXT[6] =
class TargetTypeModel : public gcn::ListModel
{
public:
- virtual ~TargetTypeModel() { }
+ virtual ~TargetTypeModel()
+ { }
virtual int getNumberOfElements()
{
@@ -146,7 +147,8 @@ public:
class MagicSchoolModel : public gcn::ListModel
{
public:
- virtual ~MagicSchoolModel() { }
+ virtual ~MagicSchoolModel()
+ { }
virtual int getNumberOfElements()
{
diff --git a/src/gui/theme.cpp b/src/gui/theme.cpp
index 85fd215ac..3a09810d0 100644
--- a/src/gui/theme.cpp
+++ b/src/gui/theme.cpp
@@ -569,6 +569,25 @@ void Theme::fillFontsList(std::vector<std::string> &list)
PHYSFS_permitSymbolicLinks(0);
}
+void Theme::fillSoundsList(std::vector<std::string> &list)
+{
+ char **skins = PHYSFS_enumerateFiles(
+ branding.getStringValue("systemsounds").c_str());
+
+ for (char **i = skins; *i; i++)
+ {
+ if (!PHYSFS_isDirectory((
+ branding.getStringValue("systemsounds") + *i).c_str()))
+ {
+ std::string str = *i;
+ if (findCutLast(str, ".ogg"))
+ list.push_back(str);
+ }
+ }
+
+ PHYSFS_freeList(skins);
+}
+
void Theme::selectSkin()
{
prepareThemePath();
diff --git a/src/gui/theme.h b/src/gui/theme.h
index 9cb8f6180..c30044dc7 100644
--- a/src/gui/theme.h
+++ b/src/gui/theme.h
@@ -131,6 +131,8 @@ class Theme : public Palette, public ConfigListener
static void fillFontsList(std::vector<std::string> &list);
+ static void fillSoundsList(std::vector<std::string> &list);
+
/**
* Returns the patch to the given gui resource relative to the theme
* or, if it isn't in the theme, relative to 'graphics/gui'.
diff --git a/src/gui/unregisterdialog.cpp b/src/gui/unregisterdialog.cpp
index ca21263f1..9ba895ec8 100644
--- a/src/gui/unregisterdialog.cpp
+++ b/src/gui/unregisterdialog.cpp
@@ -134,7 +134,8 @@ void UnRegisterDialog::action(const gcn::ActionEvent &event)
{
mWrongDataNoticeListener->setTarget(this->mPasswordField);
- OkDialog *dlg = new OkDialog(_("Error"), errorMsg.str());
+ OkDialog *dlg = new OkDialog(_("Error"),
+ errorMsg.str(), DIALOG_ERROR);
dlg->addActionListener(mWrongDataNoticeListener);
}
else
diff --git a/src/gui/updaterwindow.cpp b/src/gui/updaterwindow.cpp
index 3aaf93557..9bac5e311 100644
--- a/src/gui/updaterwindow.cpp
+++ b/src/gui/updaterwindow.cpp
@@ -298,9 +298,26 @@ void UpdaterWindow::loadNews()
// Tokenize and add each line separately
char *line = strtok(mMemoryBuffer, "\n");
+ bool firstLine(true);
while (line)
{
- mBrowserBox->addRow(line);
+ if (firstLine)
+ {
+ firstLine = false;
+ std::string str = line;
+ unsigned i = str.find("##9 Latest client version: ##6");
+ if (!i)
+ {
+ line = strtok(nullptr, "\n");
+ continue;
+ }
+
+ mBrowserBox->addRow(str);
+ }
+ else
+ {
+ mBrowserBox->addRow(line);
+ }
line = strtok(nullptr, "\n");
}
@@ -332,6 +349,15 @@ void UpdaterWindow::loadPatch()
if (line)
{
version = line;
+ if (serverVersion < 1)
+ {
+ line = strtok(nullptr, "\n");
+ if (line)
+ {
+ mBrowserBox->addRow("##9 Latest client version: ##6ManaPlus "
+ + std::string(line), true);
+ }
+ }
if (version > CHECK_VERSION)
{
mBrowserBox->addRow("", true);
@@ -554,8 +580,8 @@ void UpdaterWindow::logic()
if (mUpdateFiles.size() && mUpdateIndex <= mUpdateFiles.size())
{
mProgressBar->setText(strprintf("%d/%d", mUpdateIndex
- + mUpdateIndexOffset + 1, (int)mUpdateFiles.size()
- + (int)mTempUpdateFiles.size() + 1));
+ + mUpdateIndexOffset + 1, static_cast<int>(mUpdateFiles.size())
+ + static_cast<int>(mTempUpdateFiles.size()) + 1));
}
else
{
diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp
index d4c188bfb..5c50836f6 100644
--- a/src/gui/viewport.cpp
+++ b/src/gui/viewport.cpp
@@ -98,11 +98,7 @@ Viewport::Viewport():
Viewport::~Viewport()
{
- config.removeListener("ScrollLaziness", this);
- config.removeListener("ScrollRadius", this);
- config.removeListener("showBeingPopup", this);
- config.removeListener("selfMouseHeal", this);
- config.removeListener("enableLazyScrolling", this);
+ config.removeListeners(this);
delete mPopupMenu;
mPopupMenu = nullptr;
@@ -199,7 +195,8 @@ void Viewport::draw(gcn::Graphics *gcnGraphics)
// if (debugChatTab)
// debugChatTab->chatLog("incorrect player position!");
logger->log("incorrect player position: %d, %d, %d, %d",
- player_x, player_y, (int)mPixelViewX, (int)mPixelViewY);
+ player_x, player_y, static_cast<int>(mPixelViewX),
+ static_cast<int>(mPixelViewY));
if (player_node)
{
logger->log("tile position: %d, %d",
@@ -412,7 +409,6 @@ void Viewport::mousePressed(gcn::MouseEvent &event)
return;
// Check if we are alive and kickin'
-// if (!mMap || !player_node || !player_node->isAlive())
if (!mMap || !player_node)
return;
@@ -421,7 +417,6 @@ void Viewport::mousePressed(gcn::MouseEvent &event)
if (Being::isTalking())
return;
-
const int pixelX = event.getX() + static_cast<int>(mPixelViewX);
const int pixelY = event.getY() + static_cast<int>(mPixelViewY);
@@ -460,6 +455,13 @@ void Viewport::mousePressed(gcn::MouseEvent &event)
mPopupMenu->showPopup(event.getX(), event.getY(), mHoverSign);
return;
}
+ else if (mCameraMode)
+ {
+ mPopupMenu->showMapPopup(event.getX(), event.getY(),
+ (getMouseX() + getCameraX()) / mMap->getTileWidth(),
+ (getMouseY() + getCameraY()) / mMap->getTileHeight());
+ return;
+ }
}
// If a popup is active, just remove it
@@ -705,6 +707,11 @@ void Viewport::showUndressPopup(int x, int y, Being *being, Item *item)
mPopupMenu->showUndressPopup(x, y, being, item);
}
+void Viewport::showMapPopup(int x, int y)
+{
+ mPopupMenu->showMapPopup(getMouseX(), getMouseY(), x, y);
+}
+
void Viewport::closePopupMenu()
{
if (mPopupMenu)
diff --git a/src/gui/viewport.h b/src/gui/viewport.h
index ccb8124ba..ae6ff3d49 100644
--- a/src/gui/viewport.h
+++ b/src/gui/viewport.h
@@ -173,6 +173,8 @@ class Viewport : public WindowContainer, public gcn::MouseListener,
void showUndressPopup(int x, int y, Being *being, Item *item);
+ void showMapPopup(int x, int y);
+
/**
* Closes the popup menu. Needed for when the player dies or switching
* maps.
diff --git a/src/gui/whoisonline.cpp b/src/gui/whoisonline.cpp
index 15c8a42c4..734daa7a6 100644
--- a/src/gui/whoisonline.cpp
+++ b/src/gui/whoisonline.cpp
@@ -131,8 +131,7 @@ WhoIsOnline::WhoIsOnline():
WhoIsOnline::~WhoIsOnline()
{
- config.removeListener("updateOnlineList", this);
- config.removeListener("groupFriends", this);
+ config.removeListeners(this);
if (mThread && SDL_GetThreadID(mThread))
SDL_WaitThread(mThread, nullptr);
@@ -738,7 +737,12 @@ void OnlinePlayer::setText(std::string color)
Being *being = actorSpriteManager->findBeingByName(
mNick, Being::PLAYER);
if (being)
+ {
being->setState(mStatus);
+ // for now highlight versions > 3
+ if (mVersion > 3)
+ being->setAdvanced(true);
+ }
}
if (mLevel > 0)
diff --git a/src/gui/widgets/avatarlistbox.cpp b/src/gui/widgets/avatarlistbox.cpp
index 822e71805..749837f7d 100644
--- a/src/gui/widgets/avatarlistbox.cpp
+++ b/src/gui/widgets/avatarlistbox.cpp
@@ -74,8 +74,7 @@ AvatarListBox::AvatarListBox(AvatarListModel *model):
AvatarListBox::~AvatarListBox()
{
- config.removeListener("showgender", this);
- config.removeListener("showlevel", this);
+ config.removeListeners(this);
instances--;
diff --git a/src/gui/widgets/browserbox.cpp b/src/gui/widgets/browserbox.cpp
index 5856a91b1..47c5616b6 100644
--- a/src/gui/widgets/browserbox.cpp
+++ b/src/gui/widgets/browserbox.cpp
@@ -232,15 +232,17 @@ void BrowserBox::addRow(const std::string &row, bool atTop)
tempRow.substr(nextChar,
(nextSpacePos - nextChar)));
- if ((x + nextWordWidth + 10) > (unsigned)getWidth())
+ if ((x + nextWordWidth + 10)
+ > static_cast<unsigned>(getWidth()))
{
x = 15; // Ident in new line
y += 1;
- j++;
+ j ++;
}
}
// Wrapping looong lines (brutal force)
- else if ((x + 2 * hyphenWidth) > (unsigned)getWidth())
+ else if ((x + 2 * hyphenWidth)
+ > static_cast<unsigned>(getWidth()))
{
x = 15; // Ident in new line
y += 1;
@@ -249,7 +251,7 @@ void BrowserBox::addRow(const std::string &row, bool atTop)
}
setHeight(font->getHeight() * (static_cast<int>(
- mTextRows.size()) + y));
+ mTextRows.size()) + y));
}
else
{
@@ -423,7 +425,7 @@ int BrowserBox::calcHeight()
if (row.find("---", 0) == 0)
{
const int dashWidth = fontWidthMinus;
- for (x = 0; x < (unsigned)getWidth(); x++)
+ for (x = 0; x < static_cast<unsigned>(getWidth()); x ++)
{
mLineParts.push_back(LinePart(x, y, selColor, "-", false));
x += dashWidth - 2;
@@ -557,9 +559,8 @@ int BrowserBox::calcHeight()
width = font->getWidth(part);
// Auto wrap mode
- if (mMode == AUTO_WRAP && getWidth() > 0
- && width > 0
- && (x + width + 10) > (unsigned)getWidth())
+ if (mMode == AUTO_WRAP && getWidth() > 0 && width > 0
+ && (x + width + 10) > static_cast<unsigned>(getWidth()))
{
bool forced = false;
@@ -592,9 +593,8 @@ int BrowserBox::calcHeight()
else
width = font->getWidth(part);
}
- while (end > start && width > 0
- && (x + width + 10)
- > (unsigned)getWidth());
+ while (end > start && width > 0 && (x + width + 10)
+ > static_cast<unsigned>(getWidth()));
if (forced)
{
diff --git a/src/gui/widgets/browserbox.h b/src/gui/widgets/browserbox.h
index d82ebd758..b1582e077 100644
--- a/src/gui/widgets/browserbox.h
+++ b/src/gui/widgets/browserbox.h
@@ -104,7 +104,8 @@ class BrowserBox : public gcn::Widget,
/**
* Sets the maximum numbers of rows in the browser box. 0 = no limit.
*/
- void setMaxRow(unsigned max) {mMaxRows = max; };
+ void setMaxRow(unsigned max)
+ { mMaxRows = max; };
/**
* Disable links & user defined colors to be used in chat input.
diff --git a/src/gui/widgets/button.cpp b/src/gui/widgets/button.cpp
index 2867e3d39..c99f46149 100644
--- a/src/gui/widgets/button.cpp
+++ b/src/gui/widgets/button.cpp
@@ -32,6 +32,7 @@
#include "gui/theme.h"
#include "resources/image.h"
+#include "resources/imageset.h"
#include "utils/dtor.h"
@@ -69,30 +70,92 @@ static ButtonData const data[BUTTON_COUNT] =
ImageRect Button::button[BUTTON_COUNT];
-Button::Button():
+Button::Button() :
mDescription(""), mClickCount(0),
mTag(0),
mVertexes(new GraphicsVertexes()),
mRedraw(true),
mMode(0),
mXOffset(0),
- mYOffset(0)
+ mYOffset(0),
+ mImages(nullptr),
+ mImageSet(nullptr)
{
init();
+ adjustSize();
}
Button::Button(const std::string &caption, const std::string &actionEventId,
- gcn::ActionListener *listener):
+ gcn::ActionListener *listener) :
gcn::Button(caption),
- mDescription(""), mClickCount(0),
+ mDescription(""),
+ mClickCount(0),
+ mTag(0),
+ mVertexes(new GraphicsVertexes()),
+ mRedraw(true),
+ mMode(0),
+ mXOffset(0),
+ mYOffset(0),
+ mImages(nullptr),
+ mImageSet(nullptr),
+ mImageWidth(0),
+ mImageHeight(0)
+{
+ init();
+ adjustSize();
+ setActionEventId(actionEventId);
+
+ if (listener)
+ addActionListener(listener);
+}
+
+Button::Button(const std::string &caption, const std::string &imageName,
+ int imageWidth, int imageHeight,
+ const std::string &actionEventId,
+ gcn::ActionListener *listener) :
+ gcn::Button(caption),
+ mDescription(""),
+ mClickCount(0),
+ mTag(0),
+ mVertexes(new GraphicsVertexes()),
+ mRedraw(true),
+ mMode(0),
+ mXOffset(0),
+ mYOffset(0),
+ mImages(nullptr),
+ mImageSet(nullptr),
+ mImageWidth(imageWidth),
+ mImageHeight(imageHeight)
+{
+ init();
+ loadImage(imageName);
+ adjustSize();
+ setActionEventId(actionEventId);
+
+ if (listener)
+ addActionListener(listener);
+}
+
+Button::Button(const std::string &imageName, int imageWidth, int imageHeight,
+ const std::string &actionEventId,
+ gcn::ActionListener *listener) :
+ gcn::Button(""),
+ mDescription(""),
+ mClickCount(0),
mTag(0),
mVertexes(new GraphicsVertexes()),
mRedraw(true),
mMode(0),
mXOffset(0),
- mYOffset(0)
+ mYOffset(0),
+ mImages(nullptr),
+ mImageSet(nullptr),
+ mImageWidth(imageWidth),
+ mImageHeight(imageHeight)
{
init();
+ loadImage(imageName);
+ adjustSize();
setActionEventId(actionEventId);
if (listener)
@@ -158,6 +221,41 @@ Button::~Button()
}
}
}
+ if (mImageSet)
+ {
+ mImageSet->decRef();
+ mImageSet = nullptr;
+ }
+ if (mImages)
+ {
+ for (int f = 0; f < BUTTON_COUNT; f ++)
+ mImages[f] = nullptr;
+ delete [] mImages;
+ mImages = nullptr;
+ }
+}
+
+void Button::loadImage(const std::string &imageName)
+{
+ if (mImageSet)
+ {
+ mImageSet->decRef();
+ mImageSet = nullptr;
+ }
+ mImageSet = Theme::getImageSetFromTheme(imageName,
+ mImageWidth, mImageHeight);
+ if (!mImageSet)
+ return;
+ mImages = new Image*[BUTTON_COUNT];
+ mImages[0] = nullptr;
+ for (int f = 0; f < BUTTON_COUNT; f ++)
+ {
+ Image *img = mImageSet->get(f);
+ if (img)
+ mImages[f] = img;
+ else
+ mImages[f] = mImages[0];
+ }
}
void Button::updateAlpha()
@@ -197,6 +295,7 @@ void Button::draw(gcn::Graphics *graphics)
updateAlpha();
+ Graphics *g2 = static_cast<Graphics*>(graphics);
bool recalc = false;
if (mRedraw)
@@ -207,8 +306,7 @@ void Button::draw(gcn::Graphics *graphics)
{
// because we don't know where parent windows was moved,
// need recalc vertexes
- gcn::ClipRectangle &rect = static_cast<Graphics*>(
- graphics)->getTopClip();
+ gcn::ClipRectangle &rect = g2->getTopClip();
if (rect.xOffset != mXOffset || rect.yOffset != mYOffset)
{
recalc = true;
@@ -220,7 +318,7 @@ void Button::draw(gcn::Graphics *graphics)
recalc = true;
mMode = mode;
}
- else if (static_cast<Graphics*>(graphics)->getRedraw())
+ else if (g2->getRedraw())
{
recalc = true;
}
@@ -230,45 +328,73 @@ void Button::draw(gcn::Graphics *graphics)
{
mRedraw = false;
mMode = mode;
- static_cast<Graphics*>(graphics)->calcWindow(mVertexes, 0, 0,
- getWidth(), getHeight(), button[mode]);
+ g2->calcWindow(mVertexes, 0, 0, getWidth(), getHeight(), button[mode]);
}
- static_cast<Graphics*>(graphics)->drawImageRect2(
- mVertexes, button[mode]);
+ g2->drawImageRect2(mVertexes, button[mode]);
-// static_cast<Graphics*>(graphics)->
-// drawImageRect(0, 0, getWidth(), getHeight(), button[mode]);
+// g2->drawImageRect(0, 0, getWidth(), getHeight(), button[mode]);
if (mode == BUTTON_DISABLED)
graphics->setColor(mDisabledColor);
else
graphics->setColor(mEnabledColor);
- int textX;
+ int textX = 0;
int textY = getHeight() / 2 - getFont()->getHeight() / 2;
+ int imageX = 0;
+ int imageY = 0;
+ if (mImages)
+ imageY = getHeight() / 2 - mImageHeight / 2;
+
+// need move calculation from draw!!!
switch (getAlignment())
{
default:
case gcn::Graphics::LEFT:
- textX = 4;
+ if (mImages)
+ {
+ imageX = 4;
+ textX = 4 + mImageWidth + 2;
+ }
+ else
+ {
+ textX = 4;
+ }
break;
case gcn::Graphics::CENTER:
- textX = getWidth() / 2;
+ if (mImages)
+ {
+ int width = getFont()->getWidth(mCaption) + mImageWidth + 2;
+ imageX = getWidth() / 2 - width / 2;
+ textX = imageX + mImageWidth + 2;
+ }
+ else
+ {
+ textX = getWidth() / 2;
+ }
break;
case gcn::Graphics::RIGHT:
textX = getWidth() - 4;
+ imageX = textX - getFont()->getWidth(mCaption) - 2;
break;
-// throw GCN_EXCEPTION("Button::draw. Unknown alignment.");
}
graphics->setFont(getFont());
if (isPressed())
- graphics->drawText(getCaption(), textX + 1, textY + 1, getAlignment());
+ {
+ if (mImages)
+ g2->drawImage(mImages[mode], imageX + 1, imageY + 1);
+ g2->drawText(getCaption(), textX + 1, textY + 1, getAlignment());
+ }
else
- graphics->drawText(getCaption(), textX, textY, getAlignment());
+ {
+ if (mImages)
+ g2->drawImage(mImages[mode], imageX, imageY);
+ g2->drawText(getCaption(), textX, textY, getAlignment());
+ }
}
void Button::mouseReleased(gcn::MouseEvent& mouseEvent)
@@ -298,3 +424,27 @@ void Button::widgetMoved(const gcn::Event &event A_UNUSED)
{
mRedraw = true;
}
+
+void Button::adjustSize()
+{
+ if (mImages)
+ {
+ setWidth(getFont()->getWidth(mCaption)
+ + mImageWidth + 2 + 2 * mSpacing);
+ int height = getFont()->getHeight();
+ if (height < mImageHeight)
+ height = mImageHeight;
+ setHeight(height + 2 * mSpacing);
+ }
+ else
+ {
+ setWidth(getFont()->getWidth(mCaption) + 2 * mSpacing);
+ setHeight(getFont()->getHeight() + 2 * mSpacing);
+ }
+}
+
+void Button::setCaption(const std::string& caption)
+{
+ mCaption = caption;
+// adjustSize();
+}
diff --git a/src/gui/widgets/button.h b/src/gui/widgets/button.h
index 560e46377..6585d9850 100644
--- a/src/gui/widgets/button.h
+++ b/src/gui/widgets/button.h
@@ -28,8 +28,12 @@
#include <guichan/widgetlistener.hpp>
class GraphicsVertexes;
+class Image;
+class ImageSet;
class ImageRect;
+const std::string BUTTON_PLAY = "buttonplay.png";
+
/**
* Button widget. Same as the Guichan button but with custom look.
*
@@ -51,6 +55,23 @@ class Button : public gcn::Button, public gcn::WidgetListener
gcn::ActionListener *listener);
/**
+ * Constructor, sets the caption of the button to the given string and
+ * adds the given action listener.
+ */
+ Button(const std::string &caption, const std::string &imageName,
+ int imageWidth, int imageHeight,
+ const std::string &actionEventId,
+ gcn::ActionListener *listener);
+
+ /**
+ * Constructor, sets the caption of the button to the given string and
+ * adds the given action listener.
+ */
+ Button(const std::string &imageName, int imageWidth, int imageHeight,
+ const std::string &actionEventId,
+ gcn::ActionListener *listener);
+
+ /**
* Destructor.
*/
~Button();
@@ -86,6 +107,12 @@ class Button : public gcn::Button, public gcn::WidgetListener
void widgetMoved(const gcn::Event &event);
+ void loadImage(const std::string &imageName);
+
+ void adjustSize();
+
+ void setCaption(const std::string& caption);
+
private:
void init();
@@ -103,6 +130,10 @@ class Button : public gcn::Button, public gcn::WidgetListener
int mYOffset;
gcn::Color mEnabledColor;
gcn::Color mDisabledColor;
+ Image **mImages;
+ ImageSet *mImageSet;
+ int mImageWidth;
+ int mImageHeight;
};
#endif
diff --git a/src/gui/widgets/chattab.cpp b/src/gui/widgets/chattab.cpp
index 018e35030..be6a31164 100644
--- a/src/gui/widgets/chattab.cpp
+++ b/src/gui/widgets/chattab.cpp
@@ -289,9 +289,19 @@ void ChatTab::chatLog(std::string line, Own own,
if (getFlash() == 0)
{
if (chatWindow && chatWindow->findHighlight(tmp.text))
+ {
setFlash(2);
+ sound.playGuiSound(SOUND_HIGHLIGHT);
+ }
else
+ {
setFlash(1);
+ }
+ }
+ else if (getFlash() == 2)
+ {
+ if (chatWindow && chatWindow->findHighlight(tmp.text))
+ sound.playGuiSound(SOUND_HIGHLIGHT);
}
}
@@ -300,8 +310,10 @@ void ChatTab::chatLog(std::string line, Own own,
|| (Client::getIsMinimized() || (!Client::getMouseFocused()
&& !Client::getInputFocused()))))
{
- if (own != BY_SERVER)
- sound.playGuiSfx("system/newmessage.ogg");
+ if (own == BY_GM)
+ sound.playGuiSound(SOUND_GLOBAL);
+ else if (own != BY_SERVER)
+ playNewMessageSound();
}
}
}
@@ -468,3 +480,8 @@ void ChatTab::addNewRow(std::string &line)
}
mScrollArea->logic();
}
+
+void ChatTab::playNewMessageSound()
+{
+ sound.playGuiSound(SOUND_WHISPER);
+}
diff --git a/src/gui/widgets/chattab.h b/src/gui/widgets/chattab.h
index 912305a63..d67f56b54 100644
--- a/src/gui/widgets/chattab.h
+++ b/src/gui/widgets/chattab.h
@@ -162,6 +162,8 @@ class ChatTab : public Tab
void addNewRow(std::string &line);
+ virtual void playNewMessageSound();
+
protected:
friend class ChatWindow;
friend class WhisperWindow;
diff --git a/src/gui/widgets/flowcontainer.h b/src/gui/widgets/flowcontainer.h
index 677dd3661..e5eeebdcb 100644
--- a/src/gui/widgets/flowcontainer.h
+++ b/src/gui/widgets/flowcontainer.h
@@ -43,7 +43,8 @@ class FlowContainer : public Container,
/**
* Destructor.
*/
- ~FlowContainer() {}
+ ~FlowContainer()
+ { }
/**
* Invoked when a widget changes its size. This is used to determine
diff --git a/src/gui/widgets/guildchattab.cpp b/src/gui/widgets/guildchattab.cpp
index a95fca3cf..bad34cfb3 100644
--- a/src/gui/widgets/guildchattab.cpp
+++ b/src/gui/widgets/guildchattab.cpp
@@ -27,6 +27,7 @@
#include "guild.h"
#include "guildmanager.h"
#include "localplayer.h"
+#include "sound.h"
#include "gui/theme.h"
@@ -126,3 +127,8 @@ void GuildChatTab::saveToLogFile(std::string &msg)
if (chatLogger)
chatLogger->log("#Guild", msg);
}
+
+void GuildChatTab::playNewMessageSound()
+{
+ sound.playGuiSound(SOUND_GUILD);
+}
diff --git a/src/gui/widgets/guildchattab.h b/src/gui/widgets/guildchattab.h
index be6f4d034..e729844f4 100644
--- a/src/gui/widgets/guildchattab.h
+++ b/src/gui/widgets/guildchattab.h
@@ -44,6 +44,8 @@ class GuildChatTab : public ChatTab
int getType() const
{ return ChatTab::TAB_GUILD; }
+ void playNewMessageSound();
+
protected:
void handleInput(const std::string &msg);
diff --git a/src/gui/widgets/guitable.cpp b/src/gui/widgets/guitable.cpp
index d620cbb8d..6434f5453 100644
--- a/src/gui/widgets/guitable.cpp
+++ b/src/gui/widgets/guitable.cpp
@@ -348,14 +348,15 @@ void GuiTable::draw(gcn::Graphics* graphics)
if (mSelectedRow > 0)
{
- if (mLinewiseMode && r == (unsigned)mSelectedRow && c == 0)
+ if (mLinewiseMode && r == static_cast<unsigned>(
+ mSelectedRow) && c == 0)
{
graphics->fillRectangle(gcn::Rectangle(0, y_offset,
- getWidth(), height));
+ getWidth(), height));
}
else if (!mLinewiseMode && mSelectedColumn > 0
- && c == (unsigned)mSelectedColumn
- && r == (unsigned)mSelectedRow)
+ && c == static_cast<unsigned>(mSelectedColumn)
+ && r == static_cast<unsigned>(mSelectedRow))
{
graphics->fillRectangle(gcn::Rectangle(
x_offset, y_offset, width, height));
diff --git a/src/gui/widgets/horizontcontainer.cpp b/src/gui/widgets/horizontcontainer.cpp
index c128ea550..5bf81c5d8 100644
--- a/src/gui/widgets/horizontcontainer.cpp
+++ b/src/gui/widgets/horizontcontainer.cpp
@@ -34,11 +34,16 @@ HorizontContainer::HorizontContainer(int height, int spacing):
void HorizontContainer::add(gcn::Widget *widget)
{
+ add(widget, mSpacing);
+}
+
+void HorizontContainer::add(gcn::Widget *widget, int spacing)
+{
if (!widget)
return;
Container::add(widget);
- widget->setPosition(mLastX, mSpacing);
+ widget->setPosition(mLastX, spacing);
mCount++;
mLastX += widget->getWidth() + 2 * mSpacing;
}
diff --git a/src/gui/widgets/horizontcontainer.h b/src/gui/widgets/horizontcontainer.h
index 7439672dc..8e1d082ac 100644
--- a/src/gui/widgets/horizontcontainer.h
+++ b/src/gui/widgets/horizontcontainer.h
@@ -38,6 +38,8 @@ class HorizontContainer : public Container, public gcn::WidgetListener
virtual void add(gcn::Widget *widget);
+ virtual void add(gcn::Widget *widget, int spacing);
+
virtual void clear();
void widgetResized(const gcn::Event &event);
diff --git a/src/gui/widgets/linkhandler.h b/src/gui/widgets/linkhandler.h
index 366899ffc..703f593f2 100644
--- a/src/gui/widgets/linkhandler.h
+++ b/src/gui/widgets/linkhandler.h
@@ -34,7 +34,8 @@
class LinkHandler
{
public:
- virtual ~LinkHandler() { }
+ virtual ~LinkHandler()
+ { }
virtual void handleLink(const std::string &link,
gcn::MouseEvent *event) = 0;
diff --git a/src/gui/widgets/listbox.cpp b/src/gui/widgets/listbox.cpp
index 28fe9daa1..2944c5be6 100644
--- a/src/gui/widgets/listbox.cpp
+++ b/src/gui/widgets/listbox.cpp
@@ -29,6 +29,7 @@
#include "gui/sdlinput.h"
#include "gui/theme.h"
+#include <guichan/focushandler.hpp>
#include <guichan/font.hpp>
#include <guichan/graphics.hpp>
#include <guichan/key.hpp>
@@ -149,3 +150,12 @@ void ListBox::mouseDragged(gcn::MouseEvent &event)
if (getRowHeight())
setSelected(y / getRowHeight());
}
+
+void ListBox::refocus()
+{
+ if (!mFocusHandler)
+ return;
+
+ if (isFocusable())
+ mFocusHandler->requestFocus(this);
+}
diff --git a/src/gui/widgets/listbox.h b/src/gui/widgets/listbox.h
index e4b6dd54e..1df07f19d 100644
--- a/src/gui/widgets/listbox.h
+++ b/src/gui/widgets/listbox.h
@@ -66,6 +66,8 @@ class ListBox : public gcn::ListBox
void mouseDragged(gcn::MouseEvent &event);
+ void refocus();
+
protected:
gcn::Color mHighlightColor;
static float mAlpha;
diff --git a/src/gui/widgets/namesmodel.cpp b/src/gui/widgets/namesmodel.cpp
new file mode 100644
index 000000000..abfcd6def
--- /dev/null
+++ b/src/gui/widgets/namesmodel.cpp
@@ -0,0 +1,51 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2012 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/namesmodel.h"
+
+#include "logger.h"
+
+#include "utils/gettext.h"
+
+#include <guichan/exception.hpp>
+#include <guichan/font.hpp>
+
+#include "debug.h"
+
+NamesModel::NamesModel()
+{
+}
+
+NamesModel::~NamesModel()
+{
+}
+
+int NamesModel::getNumberOfElements()
+{
+ return static_cast<int>(mNames.size());
+}
+
+std::string NamesModel::getElementAt(int i)
+{
+ if (i >= getNumberOfElements() || i < 0)
+ return _("???");
+
+ return mNames[i];
+}
diff --git a/src/gui/widgets/namesmodel.h b/src/gui/widgets/namesmodel.h
new file mode 100644
index 000000000..dc694fc46
--- /dev/null
+++ b/src/gui/widgets/namesmodel.h
@@ -0,0 +1,51 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2012 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_WIDGETS_NAMESMODEL_H
+#define GUI_WIDGETS_NAMESMODEL_H
+
+//#include "guichanfwd.h"
+
+#include <guichan/listmodel.hpp>
+
+#include <vector>
+
+class NamesModel : public gcn::ListModel
+{
+ public:
+ NamesModel();
+
+ virtual ~NamesModel();
+
+ virtual int getNumberOfElements();
+
+ virtual std::string getElementAt(int i);
+
+ std::vector<std::string> &getNames()
+ { return mNames; }
+
+ size_t size()
+ { return mNames.size(); }
+
+ protected:
+ std::vector<std::string> mNames;
+};
+
+#endif
diff --git a/src/gui/widgets/setupitem.cpp b/src/gui/widgets/setupitem.cpp
index 56ce0a25a..93854e823 100644
--- a/src/gui/widgets/setupitem.cpp
+++ b/src/gui/widgets/setupitem.cpp
@@ -23,8 +23,10 @@
#include "configuration.h"
#include "main.h"
#include "logger.h"
+#include "sound.h"
#include "gui/editdialog.h"
+#include "gui/gui.h"
#include "gui/widgets/button.h"
#include "gui/widgets/checkbox.h"
@@ -33,13 +35,19 @@
#include "gui/widgets/inttextfield.h"
#include "gui/widgets/label.h"
#include "gui/widgets/layouthelper.h"
+#include "gui/widgets/slider.h"
+#include "gui/widgets/sliderlist.h"
#include "gui/widgets/tabbedarea.h"
#include "gui/widgets/textfield.h"
#include "gui/widgets/vertcontainer.h"
#include "utils/dtor.h"
#include "utils/gettext.h"
+#include "utils/mathutils.h"
+#include <guichan/font.hpp>
+
+#include "debug.h"
SetupItem::SetupItem(std::string text, std::string description,
std::string keyName, SetupTabScroll *parent,
@@ -163,6 +171,12 @@ void SetupItem::externalUpdated(std::string eventName A_UNUSED)
toWidget();
}
+void SetupItem::fixFirstItemSize(gcn::Widget *widget)
+{
+ if (widget->getWidth() < mParent->getPreferredFirstItemSize())
+ widget->setWidth(mParent->getPreferredFirstItemSize());
+}
+
SetupItemCheckBox::SetupItemCheckBox(std::string text, std::string description,
std::string keyName,
SetupTabScroll *parent,
@@ -271,6 +285,7 @@ void SetupItemTextField::createControls()
mButton = new Button(_("Edit"), mEventName + "_EDIT", mParent);
mWidget = mTextField;
mTextField->setWidth(200);
+ fixFirstItemSize(mLabel);
mHorizont->add(mLabel);
mHorizont->add(mTextField);
mHorizont->add(mButton);
@@ -394,6 +409,7 @@ void SetupItemIntTextField::createControls()
mButton = new Button(_("Edit"), mEventName + "_EDIT", mParent);
mWidget = mTextField;
mTextField->setWidth(50);
+ fixFirstItemSize(mLabel);
mHorizont->add(mLabel);
mHorizont->add(mTextField);
mHorizont->add(mButton);
@@ -564,6 +580,7 @@ void SetupItemDropDown::createControls()
mWidget = mDropDown;
// mTextField->setWidth(50);
+ fixFirstItemSize(mLabel);
mHorizont->add(mLabel);
mHorizont->add(mDropDown);
@@ -588,3 +605,402 @@ void SetupItemDropDown::toWidget()
mDropDown->setSelectedString(mValue);
}
+
+
+SetupItemSlider::SetupItemSlider(std::string text, std::string description,
+ std::string keyName, SetupTabScroll *parent,
+ std::string eventName, double min, double max,
+ int width, bool onTheFly, bool mainConfig) :
+ SetupItem(text, description, keyName, parent, eventName, mainConfig),
+ mHorizont(nullptr),
+ mLabel(nullptr),
+ mSlider(nullptr),
+ mMin(min),
+ mMax(max),
+ mWidth(width),
+ mOnTheFly(onTheFly)
+{
+ mValueType = VSTR;
+ createControls();
+}
+
+SetupItemSlider::SetupItemSlider(std::string text, std::string description,
+ std::string keyName, SetupTabScroll *parent,
+ std::string eventName, double min, double max,
+ std::string def, int width, bool onTheFly,
+ bool mainConfig) :
+ SetupItem(text, description, keyName, parent, eventName, def, mainConfig),
+ mHorizont(nullptr),
+ mLabel(nullptr),
+ mSlider(nullptr),
+ mMin(min),
+ mMax(max),
+ mWidth(width),
+ mOnTheFly(onTheFly)
+{
+ mValueType = VSTR;
+ createControls();
+}
+
+SetupItemSlider::~SetupItemSlider()
+{
+ mHorizont = nullptr;
+ mWidget = nullptr;
+ mSlider = nullptr;
+ mLabel = nullptr;
+}
+
+void SetupItemSlider::createControls()
+{
+ load();
+ mHorizont = new HorizontContainer(32, 2);
+
+ mLabel = new Label(mText);
+ mSlider = new Slider(mMin, mMax);
+ mSlider->setActionEventId(mEventName);
+ mSlider->addActionListener(mParent);
+ mSlider->setValue(atof(mValue.c_str()));
+ mSlider->setHeight(30);
+
+ mWidget = mSlider;
+ mSlider->setWidth(mWidth);
+ mSlider->setHeight(40);
+ fixFirstItemSize(mLabel);
+ mHorizont->add(mLabel);
+ mHorizont->add(mSlider, -10);
+
+ mParent->getContainer()->add2(mHorizont, true, 4);
+ mParent->addControl(this);
+ mParent->addActionListener(this);
+ mWidget->addActionListener(this);
+}
+
+void SetupItemSlider::fromWidget()
+{
+ if (!mSlider)
+ return;
+
+ mValue = toString(mSlider->getValue());
+}
+
+void SetupItemSlider::toWidget()
+{
+ if (!mSlider)
+ return;
+
+ mSlider->setValue(atof(mValue.c_str()));
+}
+
+void SetupItemSlider::action(const gcn::ActionEvent &event A_UNUSED)
+{
+ fromWidget();
+ if (mOnTheFly)
+ save();
+}
+
+void SetupItemSlider::apply(std::string eventName)
+{
+ if (eventName != mEventName)
+ return;
+
+ fromWidget();
+ save();
+}
+
+
+SetupItemSlider2::SetupItemSlider2(std::string text, std::string description,
+ std::string keyName, SetupTabScroll *parent,
+ std::string eventName, int min, int max,
+ SetupItemNames *values, bool onTheFly,
+ bool mainConfig) :
+ SetupItem(text, description, keyName, parent, eventName, mainConfig),
+ mHorizont(nullptr),
+ mLabel(nullptr),
+ mLabel2(nullptr),
+ mSlider(nullptr),
+ mValues(values),
+ mMin(min),
+ mMax(max),
+ mInvert(false),
+ mInvertValue(0),
+ mOnTheFly(onTheFly)
+{
+ mValueType = VSTR;
+ createControls();
+}
+
+SetupItemSlider2::SetupItemSlider2(std::string text, std::string description,
+ std::string keyName, SetupTabScroll *parent,
+ std::string eventName, int min, int max,
+ SetupItemNames *values, std::string def,
+ bool onTheFly, bool mainConfig) :
+ SetupItem(text, description, keyName, parent, eventName, def, mainConfig),
+ mHorizont(nullptr),
+ mLabel(nullptr),
+ mLabel2(nullptr),
+ mSlider(nullptr),
+ mValues(values),
+ mMin(min),
+ mMax(max),
+ mInvert(false),
+ mInvertValue(0),
+ mOnTheFly(onTheFly)
+{
+ mValueType = VSTR;
+ createControls();
+}
+
+SetupItemSlider2::~SetupItemSlider2()
+{
+ mHorizont = nullptr;
+ mWidget = nullptr;
+ mSlider = nullptr;
+ mLabel = nullptr;
+}
+
+void SetupItemSlider2::createControls()
+{
+ load();
+ mHorizont = new HorizontContainer(32, 2);
+
+ int width = getMaxWidth();
+
+ mLabel = new Label(mText);
+ mLabel2 = new Label("");
+ mLabel2->setWidth(width);
+ mSlider = new Slider(mMin, mMax);
+ mSlider->setActionEventId(mEventName);
+ mSlider->addActionListener(mParent);
+ mSlider->setValue(atof(mValue.c_str()));
+ mSlider->setHeight(30);
+
+ mWidget = mSlider;
+ mSlider->setWidth(150);
+ mSlider->setHeight(40);
+ fixFirstItemSize(mLabel);
+ mHorizont->add(mLabel);
+ mHorizont->add(mSlider, -10);
+ mHorizont->add(mLabel2);
+
+ mParent->getContainer()->add2(mHorizont, true, 4);
+ mParent->addControl(this);
+ mParent->addActionListener(this);
+ mWidget->addActionListener(this);
+ updateLabel();
+}
+
+int SetupItemSlider2::getMaxWidth()
+{
+ if (!mValues || !gui)
+ return 1;
+
+ int maxWidth = 0;
+ SetupItemNamesConstIter it = mValues->begin();
+ SetupItemNamesConstIter it_end = mValues->end();
+ gcn::Font *font = gui->getFont();
+
+ while (it != it_end)
+ {
+ int w = font->getWidth(*it);
+ if (w > maxWidth)
+ maxWidth = w;
+
+ ++ it;
+ }
+ return maxWidth;
+}
+
+void SetupItemSlider2::fromWidget()
+{
+ if (!mSlider)
+ return;
+
+ int val = roundDouble(mSlider->getValue());
+ if (mInvert)
+ val = mInvertValue - val;
+ mValue = toString(val);
+}
+
+void SetupItemSlider2::toWidget()
+{
+ if (!mSlider)
+ return;
+
+ int val = roundDouble(atof(mValue.c_str()));
+ if (mInvert)
+ val = mInvertValue - val;
+ mSlider->setValue(val);
+ updateLabel();
+}
+
+void SetupItemSlider2::action(const gcn::ActionEvent &event A_UNUSED)
+{
+ fromWidget();
+ updateLabel();
+ if (mOnTheFly)
+ save();
+}
+
+void SetupItemSlider2::updateLabel()
+{
+ int val = mSlider->getValue() - mMin;
+ if (val < 0)
+ val = 0;
+ else if (val >= static_cast<signed>(mValues->size()))
+ val = static_cast<signed>(mValues->size()) - 1;
+ std::string str = mValues->at(val);
+ mLabel2->setCaption(str);
+}
+
+void SetupItemSlider2::apply(std::string eventName)
+{
+ if (eventName != mEventName)
+ return;
+
+ fromWidget();
+ save();
+}
+
+void SetupItemSlider2::setInvertValue(int v)
+{
+ mInvert = true;
+ mInvertValue = v;
+ toWidget();
+}
+
+
+SetupItemSliderList::SetupItemSliderList(std::string text,
+ std::string description,
+ std::string keyName,
+ SetupTabScroll *parent,
+ std::string eventName,
+ gcn::ListModel *model,
+ int width, bool onTheFly,
+ bool mainConfig) :
+ SetupItem(text, description, keyName, parent, eventName, mainConfig),
+ mHorizont(nullptr),
+ mLabel(nullptr),
+ mSlider(nullptr),
+ mModel(model),
+ mWidth(width),
+ mOnTheFly(onTheFly)
+{
+ mValueType = VSTR;
+// createControls();
+}
+
+SetupItemSliderList::SetupItemSliderList(std::string text,
+ std::string description,
+ std::string keyName,
+ SetupTabScroll *parent,
+ std::string eventName,
+ gcn::ListModel *model,
+ std::string def, int width,
+ bool onTheFly, bool mainConfig) :
+ SetupItem(text, description, keyName, parent, eventName, def, mainConfig),
+ mHorizont(nullptr),
+ mLabel(nullptr),
+ mSlider(nullptr),
+ mModel(model),
+ mWidth(width),
+ mOnTheFly(onTheFly)
+{
+ mValueType = VSTR;
+// createControls();
+}
+
+SetupItemSliderList::~SetupItemSliderList()
+{
+ mHorizont = nullptr;
+ mWidget = nullptr;
+ mSlider = nullptr;
+ mLabel = nullptr;
+}
+
+void SetupItemSliderList::createControls()
+{
+ load();
+ mHorizont = new HorizontContainer(32, 2);
+
+ mLabel = new Label(mText);
+ mSlider = new SliderList(mModel, mParent, mEventName);
+ mSlider->setSelectedString(mValue);
+ mSlider->adjustSize();
+
+ mWidget = mSlider;
+ fixFirstItemSize(mLabel);
+ mHorizont->add(mLabel, 5);
+ mHorizont->add(mSlider);
+
+ addMoreControls();
+
+ mParent->getContainer()->add2(mHorizont, true, 4);
+ mParent->addControl(this);
+ mParent->addActionListener(this);
+ mWidget->addActionListener(this);
+}
+
+void SetupItemSliderList::fromWidget()
+{
+ if (!mSlider)
+ return;
+
+ mValue = mSlider->getSelectedString();
+}
+
+void SetupItemSliderList::toWidget()
+{
+ if (!mSlider)
+ return;
+
+ mSlider->setSelectedString(mValue);
+}
+
+void SetupItemSliderList::action(const gcn::ActionEvent &event A_UNUSED)
+{
+ fromWidget();
+ if (mOnTheFly)
+ save();
+}
+
+void SetupItemSliderList::apply(std::string eventName)
+{
+ if (eventName != mEventName)
+ return;
+
+ fromWidget();
+ save();
+}
+
+SetupItemSound::SetupItemSound(std::string text, std::string description,
+ std::string keyName, SetupTabScroll *parent,
+ std::string eventName, gcn::ListModel *model,
+ int width, bool onTheFly, bool mainConfig) :
+ SetupItemSliderList(text, description, keyName, parent, eventName,
+ model, width, onTheFly, mainConfig),
+ mButton(nullptr)
+{
+ createControls();
+}
+
+void SetupItemSound::addMoreControls()
+{
+ mButton = new Button(BUTTON_PLAY, 16, 16, mEventName + "_PLAY", this);
+ mHorizont->add(mButton);
+}
+
+void SetupItemSound::action(const gcn::ActionEvent &event)
+{
+ if (event.getId() == mEventName + "_PLAY")
+ {
+ if (mSlider->getSelected())
+ {
+ sound.playGuiSfx(branding.getStringValue("systemsounds")
+ + mSlider->getSelectedString() + ".ogg");
+ }
+ }
+ else
+ {
+ SetupItemSliderList::action(event);
+ }
+}
diff --git a/src/gui/widgets/setupitem.h b/src/gui/widgets/setupitem.h
index 71856d6e2..86fdf95f9 100644
--- a/src/gui/widgets/setupitem.h
+++ b/src/gui/widgets/setupitem.h
@@ -41,6 +41,8 @@ class EditDialog;
class HorizontContainer;
class IntTextField;
class Label;
+class Slider;
+class SliderList;
class TextField;
class SetupItem : public gcn::ActionListener
@@ -91,11 +93,12 @@ class SetupItem : public gcn::ActionListener
virtual void cancel(std::string eventName);
virtual void externalUpdated(std::string eventName);
-// virtual int add(ContainerPlacer &place, int x, int y, int width);
bool isMainConfig() const
{ return mMainConfig; }
+ void fixFirstItemSize(gcn::Widget *widget);
+
protected:
std::string mText;
@@ -264,4 +267,148 @@ class SetupItemDropDown : public SetupItem
DropDown *mDropDown;
};
+class SetupItemSlider : public SetupItem
+{
+ public:
+ SetupItemSlider(std::string text, std::string description,
+ std::string keyName, SetupTabScroll *parent,
+ std::string eventName, double min, double max,
+ int width = 150, bool onTheFly = false,
+ bool mainConfig = true);
+
+ SetupItemSlider(std::string text, std::string description,
+ std::string keyName, SetupTabScroll *parent,
+ std::string eventName, double min, double max,
+ std::string def, int width = 150,
+ bool onTheFly = false, bool mainConfig = true);
+
+ ~SetupItemSlider();
+
+ void createControls();
+
+ void fromWidget();
+
+ void toWidget();
+
+ void action(const gcn::ActionEvent &event);
+
+ void apply(std::string eventName);
+
+ void updateLabel();
+
+ protected:
+ HorizontContainer *mHorizont;
+ Label *mLabel;
+ Slider *mSlider;
+ double mMin;
+ double mMax;
+ int mWidth;
+ bool mOnTheFly;
+};
+
+typedef std::vector<std::string> SetupItemNames;
+typedef SetupItemNames::iterator SetupItemNamesIter;
+typedef SetupItemNames::const_iterator SetupItemNamesConstIter;
+
+class SetupItemSlider2 : public SetupItem
+{
+ public:
+ SetupItemSlider2(std::string text, std::string description,
+ std::string keyName, SetupTabScroll *parent,
+ std::string eventName, int min, int max,
+ SetupItemNames *values, bool onTheFly = false,
+ bool mainConfig = true);
+
+ SetupItemSlider2(std::string text, std::string description,
+ std::string keyName, SetupTabScroll *parent,
+ std::string eventName, int min, int max,
+ SetupItemNames *values, std::string def,
+ bool onTheFly = false, bool mainConfig = true);
+
+ ~SetupItemSlider2();
+
+ void createControls();
+
+ void fromWidget();
+
+ void toWidget();
+
+ void action(const gcn::ActionEvent &event);
+
+ void apply(std::string eventName);
+
+ void setInvertValue(int v);
+
+ protected:
+ void updateLabel();
+
+ int getMaxWidth();
+
+ HorizontContainer *mHorizont;
+ Label *mLabel;
+ Label *mLabel2;
+ Slider *mSlider;
+ SetupItemNames *mValues;
+ int mMin;
+ int mMax;
+ bool mInvert;
+ int mInvertValue;
+ bool mOnTheFly;
+};
+
+class SetupItemSliderList : public SetupItem
+{
+ public:
+ SetupItemSliderList(std::string text, std::string description,
+ std::string keyName, SetupTabScroll *parent,
+ std::string eventName, gcn::ListModel *model,
+ int width = 150, bool onTheFly = false,
+ bool mainConfig = true);
+
+ SetupItemSliderList(std::string text, std::string description,
+ std::string keyName, SetupTabScroll *parent,
+ std::string eventName, gcn::ListModel *model,
+ std::string def, int width = 150,
+ bool onTheFly = false, bool mainConfig = true);
+
+ ~SetupItemSliderList();
+
+ void createControls();
+
+ void fromWidget();
+
+ void toWidget();
+
+ virtual void action(const gcn::ActionEvent &event);
+
+ void apply(std::string eventName);
+
+ virtual void addMoreControls() = 0;
+
+ protected:
+ HorizontContainer *mHorizont;
+ Label *mLabel;
+ SliderList *mSlider;
+ gcn::ListModel *mModel;
+ int mWidth;
+ bool mOnTheFly;
+};
+
+class SetupItemSound : public SetupItemSliderList
+{
+ public:
+ SetupItemSound(std::string text, std::string description,
+ std::string keyName, SetupTabScroll *parent,
+ std::string eventName, gcn::ListModel *model,
+ int width = 150, bool onTheFly = false,
+ bool mainConfig = true);
+
+ void action(const gcn::ActionEvent &event);
+
+ void addMoreControls();
+
+ protected:
+ Button *mButton;
+};
+
#endif
diff --git a/src/gui/widgets/setuptabscroll.cpp b/src/gui/widgets/setuptabscroll.cpp
index ab8f61a40..f3f8b1526 100644
--- a/src/gui/widgets/setuptabscroll.cpp
+++ b/src/gui/widgets/setuptabscroll.cpp
@@ -28,17 +28,14 @@
#include "debug.h"
SetupTabScroll::SetupTabScroll() :
- SetupTab()
+ SetupTab(),
+ mPreferredFirstItemSize(200)
{
- mContainer = new VertContainer(32, false, 8);
+ mContainer = new VertContainer(25, false, 8);
mScroll = new ScrollArea(mContainer);
mScroll->setOpaque(false);
mScroll->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
mScroll->setVerticalScrollPolicy(ScrollArea::SHOW_AUTO);
-
-// LayoutHelper h(this);
-// ContainerPlacer place = h.getPlacer(0, 0);
-// place(0, 0, mScroll, 10, 10);
}
SetupTabScroll::~SetupTabScroll()
diff --git a/src/gui/widgets/setuptabscroll.h b/src/gui/widgets/setuptabscroll.h
index d471ecfbc..e7151769e 100644
--- a/src/gui/widgets/setuptabscroll.h
+++ b/src/gui/widgets/setuptabscroll.h
@@ -55,11 +55,15 @@ class SetupTabScroll : public SetupTab
virtual void action(const gcn::ActionEvent &event A_UNUSED)
{ }
+ int getPreferredFirstItemSize()
+ { return mPreferredFirstItemSize; }
+
protected:
VertContainer *mContainer;
ScrollArea *mScroll;
std::map<std::string, SetupItem*> mItems;
std::set<SetupItem*> mAllItems;
+ int mPreferredFirstItemSize;
};
#endif
diff --git a/src/gui/widgets/sliderlist.cpp b/src/gui/widgets/sliderlist.cpp
new file mode 100644
index 000000000..bc30bbe38
--- /dev/null
+++ b/src/gui/widgets/sliderlist.cpp
@@ -0,0 +1,216 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2012 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/sliderlist.h"
+
+#include "client.h"
+#include "logger.h"
+
+#include "gui/gui.h"
+
+#include "gui/widgets/button.h"
+#include "gui/widgets/label.h"
+
+#include "utils/dtor.h"
+
+#include <guichan/font.hpp>
+
+#include "debug.h"
+
+static const int buttonWidth = 27;
+static const int buttonSpace = 30;
+static const int sliderHeight = 30;
+
+SliderList::SliderList(gcn::ListModel *listModel,
+ gcn::ActionListener* listener,
+ std::string eventId) :
+ mListModel(listModel),
+ mOldWidth(0),
+ mSelectedIndex(0)
+{
+ mPrevEventId = eventId + "_prev";
+ mNextEventId = eventId + "_next";
+
+ setHeight(sliderHeight);
+
+ mButtons[0] = new Button("<", mPrevEventId, this);
+ mButtons[1] = new Button(">", mNextEventId, this);
+ mLabel = new Label("");
+ add(mButtons[0]);
+ add(mLabel);
+ add(mButtons[1]);
+
+ if (!eventId.empty())
+ setActionEventId(eventId);
+
+ if (listener)
+ addActionListener(listener);
+
+ updateLabel();
+ addMouseListener(this);
+}
+
+SliderList::~SliderList()
+{
+}
+
+void SliderList::updateAlpha()
+{
+ mButtons[0]->updateAlpha();
+ mButtons[1]->updateAlpha();
+}
+
+void SliderList::mouseWheelMovedUp(gcn::MouseEvent& mouseEvent)
+{
+ logger->log("SliderList::mouseWheelMovedUp");
+ setSelected(mSelectedIndex - 1);
+ mouseEvent.consume();
+}
+
+void SliderList::mouseWheelMovedDown(gcn::MouseEvent& mouseEvent)
+{
+ setSelected(mSelectedIndex + 1);
+ mouseEvent.consume();
+}
+
+void SliderList::resize()
+{
+ const int width = getWidth();
+
+ mButtons[0]->setWidth(buttonWidth);
+// mLabel->setPosition(buttonSpace, 0);
+ mLabel->setWidth(width - buttonSpace * 2);
+ mButtons[1]->setPosition(width - buttonSpace + 3, 0);
+ mButtons[1]->setWidth(buttonWidth);
+ updateLabel();
+}
+
+void SliderList::draw(gcn::Graphics *graphics)
+{
+ if (mOldWidth != getWidth())
+ {
+ resize();
+ mOldWidth = getWidth();
+ }
+ Container::draw(graphics);
+}
+
+void SliderList::updateLabel()
+{
+ if (!mListModel || mSelectedIndex < 0
+ || mSelectedIndex >= mListModel->getNumberOfElements())
+ {
+ return;
+ }
+
+ mLabel->setCaption(mListModel->getElementAt(mSelectedIndex));
+ mLabel->adjustSize();
+ const int space = getWidth() - buttonSpace * 2;
+ const int labelWidth = mLabel->getWidth();
+ int labelY = (getHeight() - mLabel->getHeight()) / 2;
+ if (labelY < 0)
+ labelY = 0;
+
+ if (space < 0 || space < labelWidth)
+ mLabel->setPosition(buttonSpace, labelY);
+ else
+ mLabel->setPosition(buttonSpace + (space - labelWidth) / 2, labelY);
+}
+
+void SliderList::action(const gcn::ActionEvent &event)
+{
+ if (!mListModel)
+ return;
+
+ if (event.getId() == mPrevEventId)
+ {
+ mSelectedIndex --;
+ if (mSelectedIndex < 0)
+ mSelectedIndex = mListModel->getNumberOfElements() - 1;
+ }
+ else if (event.getId() == mNextEventId)
+ {
+ mSelectedIndex ++;
+ if (mSelectedIndex >= mListModel->getNumberOfElements())
+ mSelectedIndex = 0;
+ }
+ updateLabel();
+ distributeActionEvent();
+}
+
+void SliderList::setSelectedString(std::string str)
+{
+ if (!mListModel)
+ return;
+
+ for (int f = 0; f < mListModel->getNumberOfElements(); f ++)
+ {
+ if (mListModel->getElementAt(f) == str)
+ {
+ setSelected(f);
+ break;
+ }
+ }
+}
+
+std::string SliderList::getSelectedString() const
+{
+ if (!mListModel)
+ return "";
+
+ return mListModel->getElementAt(mSelectedIndex);
+}
+
+void SliderList::setSelected(int idx)
+{
+ if (!mListModel)
+ return;
+
+ mSelectedIndex = idx;
+ if (mSelectedIndex >= mListModel->getNumberOfElements())
+ mSelectedIndex = 0;
+ if (mSelectedIndex < 0)
+ mSelectedIndex = mListModel->getNumberOfElements() - 1;
+ updateLabel();
+}
+
+void SliderList::adjustSize()
+{
+ setWidth(getMaxLabelWidth() + 60);
+ updateLabel();
+}
+
+int SliderList::getMaxLabelWidth()
+{
+ if (!mListModel || !gui)
+ return 1;
+
+ int maxWidth = 0;
+ gcn::Font *font = gui->getFont();
+
+ for (int f = 0; f < mListModel->getNumberOfElements(); f ++)
+ {
+ int w = font->getWidth(mListModel->getElementAt(f));
+ if (w > maxWidth)
+ maxWidth = w;
+ }
+
+ return maxWidth;
+}
diff --git a/src/gui/widgets/sliderlist.h b/src/gui/widgets/sliderlist.h
new file mode 100644
index 000000000..b2239834d
--- /dev/null
+++ b/src/gui/widgets/sliderlist.h
@@ -0,0 +1,83 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2012 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_WIDGETS_SLIDERLIST_H
+#define GUI_WIDGETS_SLIDERLIST_H
+
+#include <guichan/actionlistener.hpp>
+#include <guichan/listmodel.hpp>
+#include <guichan/mouselistener.hpp>
+
+#include "gui/widgets/container.h"
+
+#include "localconsts.h"
+
+class Button;
+class Label;
+
+class SliderList : public Container,
+ public gcn::ActionListener,
+ public gcn::MouseListener
+{
+ public:
+ SliderList(gcn::ListModel *listModel = nullptr,
+ gcn::ActionListener* listener = nullptr,
+ std::string eventId = "");
+
+ ~SliderList();
+
+ void updateAlpha();
+
+ void mouseWheelMovedUp(gcn::MouseEvent& mouseEvent);
+
+ void mouseWheelMovedDown(gcn::MouseEvent& mouseEvent);
+
+ void resize();
+
+ void draw(gcn::Graphics *graphics);
+
+ void action(const gcn::ActionEvent &event);
+
+ void setSelectedString(std::string str);
+
+ std::string getSelectedString() const;
+
+ void setSelected(int idx);
+
+ void adjustSize();
+
+ int getSelected()
+ { return mSelectedIndex; }
+
+ protected:
+ void updateLabel();
+
+ int getMaxLabelWidth();
+
+ Button *mButtons[2];
+ Label *mLabel;
+ gcn::ListModel *mListModel;
+ std::string mPrevEventId;
+ std::string mNextEventId;
+ int mOldWidth;
+ int mSelectedIndex;
+};
+
+#endif // end GUI_WIDGETS_SLIDERLIST_H
diff --git a/src/gui/widgets/tablemodel.h b/src/gui/widgets/tablemodel.h
index 40a350163..e931888e4 100644
--- a/src/gui/widgets/tablemodel.h
+++ b/src/gui/widgets/tablemodel.h
@@ -42,7 +42,8 @@ public:
*/
virtual void modelUpdated(bool completed) = 0;
- virtual ~TableModelListener() {}
+ virtual ~TableModelListener()
+ { }
};
/**
diff --git a/src/gui/widgets/textfield.cpp b/src/gui/widgets/textfield.cpp
index e207b0613..a90712340 100644
--- a/src/gui/widgets/textfield.cpp
+++ b/src/gui/widgets/textfield.cpp
@@ -183,7 +183,7 @@ int TextField::getValue() const
if (value < mMinimum)
return mMinimum;
- if (value > (signed)mMaximum)
+ if (value > static_cast<signed>(mMaximum))
return mMaximum;
return value;
diff --git a/src/gui/worldselectdialog.cpp b/src/gui/worldselectdialog.cpp
index 917605281..19e6b81f7 100644
--- a/src/gui/worldselectdialog.cpp
+++ b/src/gui/worldselectdialog.cpp
@@ -54,7 +54,8 @@ class WorldListModel : public gcn::ListModel
{
}
- virtual ~WorldListModel() {}
+ virtual ~WorldListModel()
+ { }
int getNumberOfElements()
{
diff --git a/src/guildmanager.cpp b/src/guildmanager.cpp
index 9dc9d7b73..08af3b2c7 100644
--- a/src/guildmanager.cpp
+++ b/src/guildmanager.cpp
@@ -274,7 +274,7 @@ bool GuildManager::process(std::string msg)
return false;
// logger->log("welcome message: %s", msg.c_str());
int pos = msg.find("! (");
- if (pos == (int)std::string::npos)
+ if (pos == static_cast<int>(std::string::npos))
return false;
msg = msg.substr(0, pos);
guild->setName(msg);
@@ -299,7 +299,7 @@ bool GuildManager::process(std::string msg)
return false;
pos = msg.find(", Guild:");
- if (pos == (int)std::string::npos)
+ if (pos == static_cast<int>(std::string::npos))
return false;
int level = atoi(msg.substr(0, pos).c_str());
@@ -310,7 +310,7 @@ bool GuildManager::process(std::string msg)
msg = msg.substr(pos + strlen(", Guild:"));
pos = msg.find(", No. Of Online Players: ");
- if (pos == (int)std::string::npos)
+ if (pos == static_cast<int>(std::string::npos))
return false;
msg = msg.substr(0, pos);
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index 55df24532..1acc6a938 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -205,17 +205,8 @@ LocalPlayer::~LocalPlayer()
{
logger->log1("LocalPlayer::~LocalPlayer");
- config.removeListener("showownname", this);
- config.removeListener("targetDeadPlayers", this);
+ config.removeListeners(this);
serverConfig.removeListener("enableBuggyServers", this);
- config.removeListener("syncPlayerMove", this);
- config.removeListener("drawPath", this);
- config.removeListener("serverAttack", this);
- config.removeListener("attackMoving", this);
- config.removeListener("showJobExp", this);
- config.removeListener("enableAdvert", this);
- config.removeListener("tradebot", this);
- config.removeListener("targetOnlyReachable", this);
delete mAwayDialog;
mAwayDialog = nullptr;
@@ -1677,7 +1668,7 @@ void LocalPlayer::processEvent(Channels channel,
- event.getInt("oldValue");
if (change != 0)
- addMessageToQueue(toString(change) + " xp");
+ addMessageToQueue(strprintf("%d %s", change, _("xp")));
break;
}
case LEVEL:
@@ -1711,7 +1702,8 @@ void LocalPlayer::processEvent(Channels channel,
MessagePair pair = mMessages.back();
// TRANSLATORS: this is normal experience
if (pair.first.find(strprintf(" %s",
- _("xp"))) == pair.first.size() - 3)
+ _("xp"))) == pair.first.size()
+ - strlen(_("xp")) - 1)
{
mMessages.pop_back();
// TRANSLATORS: this is job experience
@@ -2063,7 +2055,7 @@ std::string LocalPlayer::getQuickDropCounterString()
void LocalPlayer::setQuickDropCounter(int n)
{
- if (n < 1 || n >= (signed)quickDropCounterSize)
+ if (n < 1 || n >= static_cast<signed>(quickDropCounterSize))
return;
mQuickDropCounter = n;
config.setValue("quickDropCounter", mQuickDropCounter);
@@ -2203,7 +2195,8 @@ void LocalPlayer::changeAwayMode()
if (outfitWindow)
outfitWindow->wearAwayOutfit();
mAwayDialog = new OkDialog(_("Away"),
- config.getStringValue("afkMessage"), true, false);
+ config.getStringValue("afkMessage"),
+ DIALOG_SILENCE, true, false);
mAwayDialog->addActionListener(mAwayListener);
sound.volumeOff();
}
@@ -4146,7 +4139,7 @@ void LocalPlayer::checkNewName(Being *being)
if (!mWaitFor.empty() && mWaitFor == nick)
{
debugMsg(_("You see ") + mWaitFor);
- sound.playGuiSfx("system/newmessage.ogg");
+ sound.playGuiSound(SOUND_INFO);
mWaitFor = "";
}
}
diff --git a/src/logger.cpp b/src/logger.cpp
index 8eba8fdb9..90d0d4106 100644
--- a/src/logger.cpp
+++ b/src/logger.cpp
@@ -189,7 +189,8 @@ void Logger::log(const char *log_text, ...)
delete [] buf;
}
-void Logger::error(const std::string &error_text)
+// here string must be safe for any usage
+void Logger::safeError(const std::string &error_text)
{
log("Error: %s", error_text.c_str());
#ifdef WIN32
@@ -214,3 +215,31 @@ void Logger::error(const std::string &error_text)
#endif
exit(1);
}
+
+// here string can be unsafe strings
+void Logger::error(const std::string &error_text)
+{
+ log("Error: %s", error_text.c_str());
+#ifdef WIN32
+ MessageBox(nullptr, error_text.c_str(), "Error", MB_ICONERROR | MB_OK);
+#elif defined __APPLE__
+// Str255 msg;
+// CFStringRef error;
+// error = CFStringCreateWithCString(nullptr,
+// error_text.c_str(),
+// kCFStringEncodingMacRoman);
+// CFStringGetPascalString(error, msg, 255, kCFStringEncodingMacRoman);
+// StandardAlert(kAlertStopAlert,
+// (const unsigned char*)"\pError",
+// (ConstStr255Param) msg, nullptr, nullptr);
+#elif defined __linux__ || __linux
+ std::cerr << "Error: " << error_text << std::endl;
+ std::string msg = "xmessage \"Error happend. "
+ "Please see log file for more information.\"";
+ if (system(msg.c_str()) == -1)
+ std::cerr << "Error: " << error_text << std::endl;
+#else
+ std::cerr << "Error: " << error_text << std::endl;
+#endif
+ exit(1);
+}
diff --git a/src/logger.h b/src/logger.h
index db618b275..54b44cc0e 100644
--- a/src/logger.h
+++ b/src/logger.h
@@ -58,12 +58,14 @@ class Logger
/**
* Sets whether the log should be written to standard output.
*/
- void setLogToStandardOut(bool value) { mLogToStandardOut = value; }
+ void setLogToStandardOut(bool value)
+ { mLogToStandardOut = value; }
/**
* Enables logging to chat window
*/
- void setChatWindow(ChatWindow *window) { mChatWindow = window; }
+ void setChatWindow(ChatWindow *window)
+ { mChatWindow = window; }
/**
* Enters a message in the log. The message will be timestamped.
@@ -98,6 +100,13 @@ class Logger
*/
void error(const std::string &error_text) __attribute__ ((noreturn));
+ /**
+ * Log an error and quit. The error will pop-up on Windows and Mac, and
+ * will be printed to standard error everywhere else.
+ */
+ void safeError(const std::string &error_text)
+ __attribute__ ((noreturn));
+
private:
std::ofstream mLogFile;
bool mLogToStandardOut;
diff --git a/src/main.h b/src/main.h
index abc152ed3..d8bae89c3 100644
--- a/src/main.h
+++ b/src/main.h
@@ -45,8 +45,8 @@
* different interfaces, which have different implementations for each server.
*/
-#define SMALL_VERSION "1.2.2.19"
-#define CHECK_VERSION "01.02.02.19"
+#define SMALL_VERSION "1.2.3.4"
+#define CHECK_VERSION "01.02.03.04"
#ifdef HAVE_CONFIG_H
#include "../config.h"
diff --git a/src/map.cpp b/src/map.cpp
index b8767e5e4..d983508b1 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -177,9 +177,7 @@ Map::Map(int width, int height, int tileWidth, int tileHeight):
Map::~Map()
{
- config.removeListener("OverlayDetail", this);
- config.removeListener("guialpha", this);
- config.removeListener("beingopacity", this);
+ config.removeListeners(this);
// delete metadata, layers, tilesets and overlays
delete [] mMetaTiles;
diff --git a/src/net/ea/charserverhandler.cpp b/src/net/ea/charserverhandler.cpp
index 2dc51acf3..67894b0d9 100644
--- a/src/net/ea/charserverhandler.cpp
+++ b/src/net/ea/charserverhandler.cpp
@@ -167,7 +167,7 @@ void CharServerHandler::processCharCreateFailed(Net::MessageIn &msg)
errorMessage = _("Incorrect race.");
break;
}
- new OkDialog(_("Error"), errorMessage);
+ new OkDialog(_("Error"), errorMessage, DIALOG_ERROR);
if (mCharCreateDialog)
mCharCreateDialog->unlock();
}
@@ -185,7 +185,7 @@ void CharServerHandler::processCharDelete(Net::MessageIn &msg A_UNUSED)
void CharServerHandler::processCharDeleteFailed(Net::MessageIn &msg A_UNUSED)
{
unlockCharSelectDialog();
- new OkDialog(_("Error"), _("Failed to delete character."));
+ new OkDialog(_("Error"), _("Failed to delete character."), DIALOG_ERROR);
}
void CharServerHandler::clear()
diff --git a/src/net/ea/gamehandler.cpp b/src/net/ea/gamehandler.cpp
index 6d021d6a9..c8c870dbd 100644
--- a/src/net/ea/gamehandler.cpp
+++ b/src/net/ea/gamehandler.cpp
@@ -101,7 +101,7 @@ void GameHandler::processCharSwitchResponse(Net::MessageIn &msg)
void GameHandler::processMapQuitResponse(Net::MessageIn &msg)
{
if (msg.readInt8())
- new OkDialog(_("Game"), _("Request to quit denied!"), nullptr);
+ new OkDialog(_("Game"), _("Request to quit denied!"), DIALOG_ERROR);
}
} // namespace Ea
diff --git a/src/net/ea/gui/guildtab.cpp b/src/net/ea/gui/guildtab.cpp
index 87fc34d94..bd1521b21 100644
--- a/src/net/ea/gui/guildtab.cpp
+++ b/src/net/ea/gui/guildtab.cpp
@@ -26,6 +26,7 @@
#include "commandhandler.h"
#include "guild.h"
#include "localplayer.h"
+#include "sound.h"
#include "gui/theme.h"
@@ -151,4 +152,9 @@ void GuildTab::saveToLogFile(std::string &msg)
chatLogger->log("#Guild", msg);
}
+void GuildTab::playNewMessageSound()
+{
+ sound.playGuiSound(SOUND_GUILD);
+}
+
} // namespace Ea
diff --git a/src/net/ea/gui/guildtab.h b/src/net/ea/gui/guildtab.h
index 81d971161..22a41ce80 100644
--- a/src/net/ea/gui/guildtab.h
+++ b/src/net/ea/gui/guildtab.h
@@ -47,6 +47,8 @@ class GuildTab : public ChatTab
int getType() const
{ return ChatTab::TAB_GUILD; }
+ void playNewMessageSound();
+
protected:
void handleInput(const std::string &msg);
diff --git a/src/net/ea/gui/partytab.cpp b/src/net/ea/gui/partytab.cpp
index d5e344ac2..e69207842 100644
--- a/src/net/ea/gui/partytab.cpp
+++ b/src/net/ea/gui/partytab.cpp
@@ -26,6 +26,7 @@
#include "commandhandler.h"
#include "localplayer.h"
#include "party.h"
+#include "sound.h"
#include "gui/theme.h"
@@ -241,4 +242,8 @@ void PartyTab::saveToLogFile(std::string &msg)
chatLogger->log("#Party", msg);
}
+void PartyTab::playNewMessageSound()
+{
+ sound.playGuiSound(SOUND_GUILD);
+}
} // namespace Ea
diff --git a/src/net/ea/gui/partytab.h b/src/net/ea/gui/partytab.h
index 029d71ac7..931b283dd 100644
--- a/src/net/ea/gui/partytab.h
+++ b/src/net/ea/gui/partytab.h
@@ -47,6 +47,8 @@ class PartyTab : public ChatTab
void saveToLogFile(std::string &msg);
+ void playNewMessageSound();
+
protected:
void handleInput(const std::string &msg);
diff --git a/src/net/ea/playerhandler.cpp b/src/net/ea/playerhandler.cpp
index 27aa4da80..bfbef0798 100644
--- a/src/net/ea/playerhandler.cpp
+++ b/src/net/ea/playerhandler.cpp
@@ -28,6 +28,7 @@
#include "playerinfo.h"
#include "units.h"
+#include "gui/ministatuswindow.h"
#include "gui/okdialog.h"
#include "gui/skilldialog.h"
#include "gui/statuswindow.h"
@@ -257,7 +258,12 @@ void PlayerHandler::processPlayerWarp(Net::MessageIn &msg)
static_cast<int>(scrollOffsetY));
if (viewport)
+ {
+ viewport->returnCamera();
+ if (miniStatusWindow)
+ miniStatusWindow->updateStatus();
viewport->scrollBy(scrollOffsetX, scrollOffsetY);
+ }
}
void PlayerHandler::processPlayerStatUpdate1(Net::MessageIn &msg)
@@ -336,7 +342,7 @@ void PlayerHandler::processPlayerStatUpdate1(Net::MessageIn &msg)
weightNotice = new OkDialog(_("Message"),
_("You are carrying more than "
"half your weight. You are "
- "unable to regain health."), false);
+ "unable to regain health."), DIALOG_OK, false);
weightNotice->addActionListener(
&weightListener);
}
@@ -346,7 +352,7 @@ void PlayerHandler::processPlayerStatUpdate1(Net::MessageIn &msg)
weightNotice = new OkDialog(_("Message"),
_("You are carrying less than "
"half your weight. You "
- "can regain health."), false);
+ "can regain health."), DIALOG_OK, false);
weightNotice->addActionListener(
&weightListener);
}
@@ -426,8 +432,7 @@ void PlayerHandler::processPlayerStatUpdate1(Net::MessageIn &msg)
if (PlayerInfo::getAttribute(HP) == 0 && !deathNotice)
{
deathNotice = new OkDialog(_("Message"),
- randomDeathMessage(),
- false);
+ randomDeathMessage(), DIALOG_OK, false);
deathNotice->addActionListener(&deathListener);
player_node->setAction(Being::DEAD);
}
diff --git a/src/net/manaserv/attributes.cpp b/src/net/manaserv/attributes.cpp
new file mode 100644
index 000000000..662032e29
--- /dev/null
+++ b/src/net/manaserv/attributes.cpp
@@ -0,0 +1,412 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2010 The Mana Developers
+ * Copyright (C) 2011-2012 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "net/manaserv/attributes.h"
+
+#include "logger.h"
+#include "playerinfo.h"
+
+#include "gui/statuswindow.h"
+
+#include "resources/itemdb.h"
+
+#include "utils/gettext.h"
+#include "utils/stringutils.h"
+#include "utils/xml.h"
+
+#include <list>
+#include <map>
+
+#define DEFAULT_ATTRIBUTESDB_FILE "attributes.xml"
+#define DEFAULT_POINTS 60
+#define DEFAULT_MIN_PTS 1
+#define DEFAULT_MAX_PTS 20
+
+namespace ManaServ
+{
+namespace Attributes
+{
+ typedef struct
+ {
+ unsigned int id;
+ std::string name;
+ std::string description;
+ /** Whether the attribute value can be modified by the player */
+ bool modifiable;
+ /**< Attribute scope. */
+ std::string scope;
+ /** The playerInfo core Id the attribute is linked with or -1 if not */
+ int playerInfoId;
+ } Attribute;
+
+ /** Map for attributes. */
+ typedef std::map<unsigned int, Attribute> AttributeMap;
+ static AttributeMap attributes;
+
+ /** tags = effects on attributes. */
+ typedef std::map< std::string, std::string > TagMap;
+ static TagMap tags;
+
+ /** List of modifiable attribute names used at character's creation. */
+ static std::vector<std::string> attributeLabels;
+
+ /** Characters creation points. */
+ static unsigned int creationPoints = 0;
+ static unsigned int attributeMinimum = 0;
+ static unsigned int attributeMaximum = 0;
+
+ unsigned int getCreationPoints()
+ { return creationPoints; }
+
+ unsigned int getAttributeMinimum()
+ { return attributeMinimum; }
+
+ unsigned int getAttributeMaximum()
+ { return attributeMaximum; }
+
+ std::vector<std::string>& getLabels()
+ { return attributeLabels; }
+
+ /**
+ * Fills the list of base attribute labels.
+ */
+ static void fillLabels()
+ {
+ // Fill up the modifiable attribute label list.
+ attributeLabels.clear();
+ AttributeMap::const_iterator it, it_end;
+ for (it = attributes.begin(), it_end = attributes.end();
+ it != it_end; ++it)
+ {
+ if (it->second.modifiable && (it->second.scope == "character"
+ || it->second.scope == "being"))
+ {
+ attributeLabels.push_back(it->second.name + ":");
+ }
+ }
+ }
+
+ /**
+ * Fills the list of base attribute labels.
+ */
+ static int getPlayerInfoIdFromAttrType(std::string attrType)
+ {
+ toLower(attrType);
+ if (attrType == "level")
+ return ::LEVEL;
+ else if (attrType == "hp")
+ return ::HP;
+ else if (attrType == "max-hp")
+ return ::MAX_HP;
+ else if (attrType == "mp")
+ return ::MP;
+ else if (attrType == "max-mp")
+ return ::MAX_MP;
+ else if (attrType == "exp")
+ return ::EXP;
+ else if (attrType == "exp-needed")
+ return ::EXP_NEEDED;
+ else if (attrType == "money")
+ return ::MONEY;
+ else if (attrType == "total-weight")
+ return ::TOTAL_WEIGHT;
+ else if (attrType == "max-weight")
+ return ::MAX_WEIGHT;
+ else if (attrType == "skill-points")
+ return ::SKILL_POINTS;
+ else if (attrType == "char-points")
+ return ::CHAR_POINTS;
+ else if (attrType == "corr-points")
+ return ::CORR_POINTS;
+ else if (attrType == "none")
+ return -2; // Used to hide the attribute display.
+
+ return -1; // Not linked to a playerinfo stat.
+ }
+
+ int getPlayerInfoIdFromAttrId(int attrId)
+ {
+ AttributeMap::const_iterator it = attributes.find(attrId);
+
+ if (it != attributes.end())
+ return it->second.playerInfoId;
+
+ return -1;
+ }
+
+ static void loadBuiltins()
+ {
+ {
+ Attribute a;
+ a.id = 16;
+ a.name = _("Strength");
+ a.description = "";
+ a.modifiable = true;
+ a.scope = "character";
+ a.playerInfoId = -1;
+
+ attributes[a.id] = a;
+ tags.insert(std::make_pair("str", _("Strength %+.1f")));
+ }
+
+ {
+ Attribute a;
+ a.id = 17;
+ a.name = _("Agility");
+ a.description = "";
+ a.modifiable = true;
+ a.scope = "character";
+ a.playerInfoId = -1;
+
+ attributes[a.id] = a;
+ tags.insert(std::make_pair("agi", _("Agility %+.1f")));
+ }
+
+ {
+ Attribute a;
+ a.id = 18;
+ a.name = _("Dexterity");
+ a.description = "";
+ a.modifiable = true;
+ a.scope = "character";
+ a.playerInfoId = -1;
+
+ attributes[a.id] = a;
+ tags.insert(std::make_pair("dex", _("Dexterity %+.1f")));
+ }
+
+ {
+ Attribute a;
+ a.id = 19;
+ a.name = _("Vitality");
+ a.description = "";
+ a.modifiable = true;
+ a.scope = "character";
+ a.playerInfoId = -1;
+
+ attributes[a.id] = a;
+ tags.insert(std::make_pair("vit", _("Vitality %+.1f")));
+ }
+
+ {
+ Attribute a;
+ a.id = 20;
+ a.name = _("Intelligence");
+ a.description = "";
+ a.modifiable = true;
+ a.scope = "character";
+ a.playerInfoId = -1;
+
+ attributes[a.id] = a;
+ tags.insert(std::make_pair("int", _("Intelligence %+.1f")));
+ }
+
+ {
+ Attribute a;
+ a.id = 21;
+ a.name = _("Willpower");
+ a.description = "";
+ a.modifiable = true;
+ a.scope = "character";
+ a.playerInfoId = -1;
+
+ attributes[a.id] = a;
+ tags.insert(std::make_pair("wil", _("Willpower %+.1f")));
+ }
+ }
+
+ void load()
+ {
+ logger->log("Initializing attributes database...");
+
+ XML::Document doc(DEFAULT_ATTRIBUTESDB_FILE);
+ XmlNodePtr rootNode = doc.rootNode();
+
+ if (!rootNode || !xmlNameEqual(rootNode, "attributes"))
+ {
+ logger->log("Attributes: Error while loading "
+ DEFAULT_ATTRIBUTESDB_FILE ". Using Built-ins.");
+ loadBuiltins();
+ fillLabels();
+ return;
+ }
+
+ for_each_xml_child_node(node, rootNode)
+ {
+ if (xmlNameEqual(node, "attribute"))
+ {
+ int id = XML::getProperty(node, "id", 0);
+
+ if (!id)
+ {
+ logger->log("Attributes: Invalid or missing stat ID in "
+ DEFAULT_ATTRIBUTESDB_FILE "!");
+ continue;
+ }
+ else if (attributes.find(id) != attributes.end())
+ {
+ logger->log("Attributes: Redefinition of stat ID %d", id);
+ }
+
+ std::string name = XML::getProperty(node, "name", "");
+
+ if (name.empty())
+ {
+ logger->log("Attributes: Invalid or missing stat name in "
+ DEFAULT_ATTRIBUTESDB_FILE "!");
+ continue;
+ }
+
+ // Create the attribute.
+ Attribute a;
+ a.id = id;
+ a.name = name;
+ a.description = XML::getProperty(node, "desc", "");
+ a.modifiable = XML::getBoolProperty(node, "modifiable", false);
+ a.scope = XML::getProperty(node, "scope", "none");
+ a.playerInfoId = getPlayerInfoIdFromAttrType(
+ XML::getProperty(node, "player-info", ""));
+
+ attributes[id] = a;
+
+ unsigned int count = 0;
+ for_each_xml_child_node(effectNode, node)
+ {
+ if (!xmlNameEqual(effectNode, "modifier"))
+ continue;
+ ++count;
+ std::string tag = XML::getProperty(effectNode, "tag", "");
+ if (tag.empty())
+ {
+ if (name.empty())
+ {
+ logger->log("Attribute modifier in attribute"
+ " %u:%s: Empty name definition "
+ "on empty tag definition, skipping.",
+ a.id, a.name.c_str());
+ --count;
+ continue;
+ }
+ tag = name.substr(0, name.size() > 3
+ ? 3 : name.size());
+ tag = toLower(tag) + toString(count);
+ }
+
+ std::string effect = XML::getProperty(
+ effectNode, "effect", "");
+
+ if (effect.empty())
+ {
+ if (name.empty())
+ {
+ logger->log("Attribute modifier in attribute"
+ " %u:%s: Empty name definition "
+ "on empty effect definition, skipping.",
+ a.id, a.name.c_str());
+ --count;
+ continue;
+ }
+ else
+ {
+ effect = name + " %+f";
+ }
+ }
+ tags.insert(std::make_pair(tag, effect));
+ }
+ logger->log("Found %d tags for attribute %d.", count, id);
+
+ }// End attribute
+ else if (xmlNameEqual(node, "points"))
+ {
+ creationPoints = XML::getProperty(
+ node, "start", DEFAULT_POINTS);
+ attributeMinimum = XML::getProperty(
+ node, "minimum", DEFAULT_MIN_PTS);
+ attributeMaximum = XML::getProperty(
+ node, "maximum", DEFAULT_MAX_PTS);
+ logger->log("Loaded points: start: %i, min: %i, max: %i.",
+ creationPoints, attributeMinimum, attributeMaximum);
+ }
+ else
+ {
+ continue;
+ }
+ }
+ logger->log("Found %d tags for %d attributes.", int(tags.size()),
+ int(attributes.size()));
+
+ fillLabels();
+
+ // Sanity checks on starting points
+ float modifiableAttributeCount = (float) attributeLabels.size();
+ float averageValue = 1;
+ if (modifiableAttributeCount)
+ averageValue = ((float) creationPoints) / modifiableAttributeCount;
+
+ if (averageValue > attributeMaximum || averageValue < attributeMinimum
+ || creationPoints < 1)
+ {
+ logger->log("Attributes: Character's point values make "
+ "the character's creation impossible. "
+ "Switch back to defaults.");
+ creationPoints = DEFAULT_POINTS;
+ attributeMinimum = DEFAULT_MIN_PTS;
+ attributeMaximum = DEFAULT_MAX_PTS;
+ }
+ }
+
+ void unload()
+ {
+ attributes.clear();
+ }
+
+ void informItemDB()
+ {
+ std::vector<ItemDB::Stat> dbStats;
+
+ TagMap::const_iterator it, it_end;
+ for (it = tags.begin(), it_end = tags.end(); it != it_end; ++it)
+ dbStats.push_back(ItemDB::Stat(it->first, it->second));
+
+ ItemDB::setStatsList(dbStats);
+ }
+
+ void informStatusWindow()
+ {
+ if (!statusWindow)
+ return;
+
+ AttributeMap::const_iterator it, it_end;
+ for (it = attributes.begin(), it_end = attributes.end();
+ it != it_end; ++it)
+ {
+ if (it->second.playerInfoId == -1
+ && (it->second.scope == "character"
+ || it->second.scope == "being"))
+ {
+ statusWindow->addAttribute(it->second.id, it->second.name,
+ it->second.modifiable, it->second.description);
+ }
+ }
+ }
+
+} // namespace Attributes
+} // namespace ManaServ
diff --git a/src/net/manaserv/beinghandler.cpp b/src/net/manaserv/beinghandler.cpp
new file mode 100644
index 000000000..9468baaa1
--- /dev/null
+++ b/src/net/manaserv/beinghandler.cpp
@@ -0,0 +1,388 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2012 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "net/manaserv/beinghandler.h"
+
+#include "actorspritemanager.h"
+#include "being.h"
+#include "client.h"
+#include "game.h"
+#include "localplayer.h"
+#include "logger.h"
+#include "particle.h"
+
+#include "gui/okdialog.h"
+
+#include "net/messagein.h"
+#include "net/net.h"
+
+#include "net/manaserv/playerhandler.h"
+#include "net/manaserv/protocol.h"
+
+#include "resources/colordb.h"
+
+#include "utils/gettext.h"
+
+extern Net::BeingHandler *beingHandler;
+
+namespace ManaServ
+{
+
+BeingHandler::BeingHandler()
+{
+ static const Uint16 _messages[] =
+ {
+ GPMSG_BEING_ATTACK,
+ GPMSG_BEING_ENTER,
+ GPMSG_BEING_LEAVE,
+ GPMSG_BEINGS_MOVE,
+ GPMSG_BEINGS_DAMAGE,
+ GPMSG_BEING_ACTION_CHANGE,
+ GPMSG_BEING_LOOKS_CHANGE,
+ GPMSG_BEING_DIR_CHANGE,
+ 0
+ };
+ handledMessages = _messages;
+ beingHandler = this;
+}
+
+void BeingHandler::handleMessage(Net::MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case GPMSG_BEING_ENTER:
+ handleBeingEnterMessage(msg);
+ break;
+ case GPMSG_BEING_LEAVE:
+ handleBeingLeaveMessage(msg);
+ break;
+ case GPMSG_BEINGS_MOVE:
+ handleBeingsMoveMessage(msg);
+ break;
+ case GPMSG_BEING_ATTACK:
+ handleBeingAttackMessage(msg);
+ break;
+ case GPMSG_BEINGS_DAMAGE:
+ handleBeingsDamageMessage(msg);
+ break;
+ case GPMSG_BEING_ACTION_CHANGE:
+ handleBeingActionChangeMessage(msg);
+ break;
+ case GPMSG_BEING_LOOKS_CHANGE:
+ handleBeingLooksChangeMessage(msg);
+ break;
+ case GPMSG_BEING_DIR_CHANGE:
+ handleBeingDirChangeMessage(msg);
+ break;
+ default:
+ break;
+ }
+}
+
+Vector BeingHandler::giveSpeedInPixelsPerTicks(float speedInTilesPerSeconds)
+{
+ Vector speedInTicks;
+ Game *game = Game::instance();
+ Map *map = 0;
+ if (game)
+ {
+ map = game->getCurrentMap();
+ if (map)
+ {
+ speedInTicks.x = speedInTilesPerSeconds
+ * (float)map->getTileWidth()
+ / 1000 * (float) MILLISECONDS_IN_A_TICK;
+ speedInTicks.y = speedInTilesPerSeconds
+ * (float)map->getTileHeight()
+ / 1000 * (float) MILLISECONDS_IN_A_TICK;
+ }
+ }
+
+ if (!game || !map)
+ {
+ speedInTicks.x = speedInTicks.y = 0;
+ logger->log1("Manaserv::BeingHandler: Speed wasn't given back"
+ " because game/Map not initialized.");
+ }
+ // We don't use z for now.
+ speedInTicks.z = 0;
+
+ return speedInTicks;
+}
+
+static void handleLooks(Being *being, Net::MessageIn &msg)
+{
+ // Order of sent slots. Has to be in sync with the server code.
+ static int const nb_slots = 4;
+ static int const slots[nb_slots] =
+ {
+ SPRITE_WEAPON,
+ SPRITE_HAT,
+ SPRITE_TOPCLOTHES,
+ SPRITE_BOTTOMCLOTHES
+ };
+
+ int mask = msg.readInt8();
+
+ if (mask & (1 << 7))
+ {
+ // The equipment has to be cleared first.
+ for (int i = 0; i < nb_slots; ++i)
+ being->setSprite(slots[i], 0);
+ }
+
+ // Fill slots enumerated by the bitmask.
+ for (int i = 0; i < nb_slots; ++i)
+ {
+ if (!(mask & (1 << i))) continue;
+ int id = msg.readInt16();
+ being->setSprite(slots[i], id, "", 1, (slots[i] == SPRITE_WEAPON));
+ }
+}
+
+void BeingHandler::handleBeingEnterMessage(Net::MessageIn &msg)
+{
+ int type = msg.readInt8();
+ int id = msg.readInt16();
+ Being::Action action = (Being::Action)msg.readInt8();
+ int px = msg.readInt16();
+ int py = msg.readInt16();
+ Being *being;
+
+ switch (type)
+ {
+ case OBJECT_CHARACTER:
+ {
+ std::string name = msg.readString();
+ if (player_node->getName() == name)
+ {
+ being = player_node;
+ being->setId(id);
+ }
+ else
+ {
+ being = actorSpriteManager->createBeing(id,
+ ActorSprite::PLAYER, 0);
+ being->setName(name);
+ }
+ int hs = msg.readInt8(), hc = msg.readInt8();
+ being->setSprite(SPRITE_HAIR, hs * -1, ColorDB::getHairColor(hc));
+ being->setGender(msg.readInt8() == GENDER_MALE ?
+ GENDER_MALE : GENDER_FEMALE);
+ handleLooks(being, msg);
+ } break;
+
+ case OBJECT_MONSTER:
+ case OBJECT_NPC:
+ {
+ int subtype = msg.readInt16();
+ being = actorSpriteManager->createBeing(id, type == OBJECT_MONSTER
+ ? ActorSprite::MONSTER : ActorSprite::NPC, subtype);
+ std::string name = msg.readString();
+ if (name.length() > 0) being->setName(name);
+ } break;
+
+ default:
+ return;
+ }
+
+ being->setPosition(px, py);
+ being->setDestination(px, py);
+ being->setAction(action);
+}
+
+void BeingHandler::handleBeingLeaveMessage(Net::MessageIn &msg)
+{
+ Being *being = actorSpriteManager->findBeing(msg.readInt16());
+ if (!being)
+ return;
+
+ actorSpriteManager->destroy(being);
+}
+
+void BeingHandler::handleBeingsMoveMessage(Net::MessageIn &msg)
+{
+ while (msg.getUnreadLength())
+ {
+ int id = msg.readInt16();
+ int flags = msg.readInt8();
+ Being *being = actorSpriteManager->findBeing(id);
+ int sx = 0;
+ int sy = 0;
+ int speed = 0;
+
+ if (flags & MOVING_POSITION)
+ {
+ sx = msg.readInt16();
+ sy = msg.readInt16();
+ speed = msg.readInt8();
+ }
+ if (!being || !(flags & (MOVING_POSITION | MOVING_DESTINATION)))
+ {
+ continue;
+ }
+ if (speed)
+ {
+ /*
+ * The being's speed is transfered in tiles per second * 10
+ * to keep it transferable in a Byte.
+ * We set it back to tiles per second and in a float.
+ * Then, we translate it in pixels per ticks, to correspond
+ * with the Being::logic() function calls
+ * @see MILLISECONDS_IN_A_TICK
+ */
+ being->setWalkSpeed(
+ giveSpeedInPixelsPerTicks((float) speed / 10));
+ }
+
+ // Ignore messages from the server for the local player
+ if (being == player_node)
+ continue;
+
+ if (flags & MOVING_POSITION)
+ {
+ being->setDestination(sx, sy);
+ }
+ }
+}
+
+void BeingHandler::handleBeingAttackMessage(Net::MessageIn &msg)
+{
+ Being *being = actorSpriteManager->findBeing(msg.readInt16());
+ const int direction = msg.readInt8();
+ const int attackType = msg.readInt8();
+
+ if (!being)
+ return;
+
+ switch (direction)
+ {
+ case DIRECTION_UP: being->setDirection(Being::UP); break;
+ case DIRECTION_DOWN: being->setDirection(Being::DOWN); break;
+ case DIRECTION_LEFT: being->setDirection(Being::LEFT); break;
+ case DIRECTION_RIGHT: being->setDirection(Being::RIGHT); break;
+ default: break;
+ }
+
+ being->setAction(Being::ATTACK, attackType);
+}
+
+void BeingHandler::handleBeingsDamageMessage(Net::MessageIn &msg)
+{
+ while (msg.getUnreadLength())
+ {
+ Being *being = actorSpriteManager->findBeing(msg.readInt16());
+ int damage = msg.readInt16();
+ if (being)
+ {
+ being->takeDamage(0, damage, Being::HIT);
+ }
+ }
+}
+
+void BeingHandler::handleBeingActionChangeMessage(Net::MessageIn &msg)
+{
+ Being *being = actorSpriteManager->findBeing(msg.readInt16());
+ Being::Action action = (Being::Action) msg.readInt8();
+ if (!being)
+ return;
+
+ being->setAction(action);
+
+ if (action == Being::DEAD && being == player_node)
+ {
+ static char const *const deadMsg[] =
+ {
+ _("You are dead."),
+ _("We regret to inform you that your character was killed in "
+ "battle."),
+ _("You are not that alive anymore."),
+ _("The cold hands of the grim reaper are grabbing for your soul."),
+ _("Game Over!"),
+ _("No, kids. Your character did not really die. It... err... "
+ "went to a better place."),
+ _("Your plan of breaking your enemies weapon by bashing it with "
+ "your throat failed."),
+ _("I guess this did not run too well."),
+ _("Do you want your possessions identified?"), // Nethack reference
+ _("Sadly, no trace of you was ever found..."), // Secret of Mana
+ // reference
+ _("Annihilated."), // Final Fantasy VI reference
+ _("Looks like you got your head handed to you."), // Earthbound
+ // reference
+ _("You screwed up again, dump your body down the tubes and get "
+ "you another one.") // Leisure Suit Larry 1 Reference
+
+ };
+ std::string message(deadMsg[rand() % 13]);
+ message.append(std::string(" ") + _("Press OK to respawn."));
+ OkDialog *dlg = new OkDialog(_("You Died"),
+ message, DIALOG_OK, false);
+ dlg->addActionListener(&(ManaServ::respawnListener));
+ }
+}
+
+void BeingHandler::handleBeingLooksChangeMessage(Net::MessageIn &msg)
+{
+ Being *being = actorSpriteManager->findBeing(msg.readInt16());
+ if (!being || being->getType() != ActorSprite::PLAYER)
+ return;
+ handleLooks(being, msg);
+ if (msg.getUnreadLength())
+ {
+ int style = msg.readInt16();
+ int color = msg.readInt16();
+ being->setSprite(SPRITE_HAIR, style * -1,
+ ColorDB::getHairColor(color));
+ }
+}
+
+void BeingHandler::handleBeingDirChangeMessage(Net::MessageIn &msg)
+{
+ Being *being = actorSpriteManager->findBeing(msg.readInt16());
+ if (!being)
+ return;
+ int data = msg.readInt8();
+
+ // The direction for the player's character is handled on client side.
+ if (being != player_node)
+ {
+ switch (data)
+ {
+ case DIRECTION_UP: being->setDirection(Being::UP); break;
+ case DIRECTION_DOWN: being->setDirection(Being::DOWN); break;
+ case DIRECTION_LEFT: being->setDirection(Being::LEFT); break;
+ case DIRECTION_RIGHT: being->setDirection(Being::RIGHT); break;
+ default: break;
+ }
+ }
+}
+
+void BeingHandler::requestNameById(int id A_UNUSED)
+{
+}
+
+void BeingHandler::undress(Being *being A_UNUSED)
+{
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/charhandler.cpp b/src/net/manaserv/charhandler.cpp
new file mode 100644
index 000000000..7977df909
--- /dev/null
+++ b/src/net/manaserv/charhandler.cpp
@@ -0,0 +1,407 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2012 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "net/manaserv/charhandler.h"
+
+#include "client.h"
+#include "localplayer.h"
+#include "logger.h"
+
+#include "gui/charcreatedialog.h"
+#include "gui/okdialog.h"
+
+#include "net/logindata.h"
+#include "net/loginhandler.h"
+#include "net/net.h"
+
+#include "net/manaserv/connection.h"
+#include "net/manaserv/gamehandler.h"
+#include "net/manaserv/messagein.h"
+#include "net/manaserv/messageout.h"
+#include "net/manaserv/protocol.h"
+#include "net/manaserv/attributes.h"
+
+#include "resources/colordb.h"
+
+#include "utils/dtor.h"
+#include "utils/gettext.h"
+
+extern Net::CharHandler *charHandler;
+extern ManaServ::GameHandler *gameHandler;
+
+namespace ManaServ
+{
+
+extern Connection *accountServerConnection;
+extern Connection *gameServerConnection;
+extern Connection *chatServerConnection;
+extern std::string netToken;
+extern ServerInfo gameServer;
+extern ServerInfo chatServer;
+
+CharHandler::CharHandler()
+{
+ static const Uint16 _messages[] =
+ {
+ APMSG_CHAR_CREATE_RESPONSE,
+ APMSG_CHAR_DELETE_RESPONSE,
+ APMSG_CHAR_INFO,
+ APMSG_CHAR_SELECT_RESPONSE,
+ 0
+ };
+ handledMessages = _messages;
+ charHandler = this;
+}
+
+CharHandler::~CharHandler()
+{
+ clear();
+}
+
+void CharHandler::handleMessage(Net::MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case APMSG_CHAR_CREATE_RESPONSE:
+ handleCharacterCreateResponse(msg);
+ break;
+
+ case APMSG_CHAR_DELETE_RESPONSE:
+ handleCharacterDeleteResponse(msg);
+ break;
+
+ case APMSG_CHAR_INFO:
+ handleCharacterInfo(msg);
+ break;
+
+ case APMSG_CHAR_SELECT_RESPONSE:
+ handleCharacterSelectResponse(msg);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void CharHandler::handleCharacterInfo(Net::MessageIn &msg)
+{
+ CachedCharacterInfo info;
+ info.slot = msg.readInt8();
+ info.name = msg.readString();
+ info.gender = msg.readInt8() == GENDER_MALE ? GENDER_MALE :
+ GENDER_FEMALE;
+ info.hairStyle = msg.readInt8();
+ info.hairColor = msg.readInt8();
+ info.level = msg.readInt16();
+ info.characterPoints = msg.readInt16();
+ info.correctionPoints = msg.readInt16();
+
+
+ while (msg.getUnreadLength() > 0)
+ {
+ int id = msg.readInt32();
+ CachedAttrbiute attr;
+ attr.base = msg.readInt32() / 256.0;
+ attr.mod = msg.readInt32() / 256.0;
+
+ info.attribute[id] = attr;
+ }
+
+ mCachedCharacterInfos.push_back(info);
+
+ updateCharacters();
+}
+
+void CharHandler::handleCharacterCreateResponse(Net::MessageIn &msg)
+{
+ const int errMsg = msg.readInt8();
+
+ if (errMsg != ERRMSG_OK)
+ {
+ // Character creation failed
+ std::string errorMessage("");
+ switch (errMsg)
+ {
+ case ERRMSG_NO_LOGIN:
+ errorMessage = _("Not logged in.");
+ break;
+ case CREATE_TOO_MUCH_CHARACTERS:
+ errorMessage = _("No empty slot.");
+ break;
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage = _("Invalid name.");
+ break;
+ case CREATE_EXISTS_NAME:
+ errorMessage = _("Character's name already exists.");
+ break;
+ case CREATE_INVALID_HAIRSTYLE:
+ errorMessage = _("Invalid hairstyle.");
+ break;
+ case CREATE_INVALID_HAIRCOLOR:
+ errorMessage = _("Invalid hair color.");
+ break;
+ case CREATE_INVALID_GENDER:
+ errorMessage = _("Invalid gender.");
+ break;
+ case CREATE_ATTRIBUTES_TOO_HIGH:
+ errorMessage = _("Character's stats are too high.");
+ break;
+ case CREATE_ATTRIBUTES_TOO_LOW:
+ errorMessage = _("Character's stats are too low.");
+ break;
+ case CREATE_ATTRIBUTES_OUT_OF_RANGE:
+ errorMessage = strprintf( _("At least one stat "
+ "is out of the permitted range: (%u - %u)."),
+ Attributes::getAttributeMinimum(),
+ Attributes::getAttributeMaximum());
+ break;
+ case CREATE_INVALID_SLOT:
+ errorMessage = _("Invalid slot number.");
+ break;
+ default:
+ errorMessage = _("Unknown error.");
+ break;
+ }
+ new OkDialog(_("Error"), errorMessage, DIALOG_ERROR);
+
+ if (mCharCreateDialog)
+ mCharCreateDialog->unlock();
+ }
+ else
+ {
+ // Close the character create dialog
+ if (mCharCreateDialog)
+ {
+ mCharCreateDialog->scheduleDelete();
+ mCharCreateDialog = 0;
+ }
+ }
+}
+
+void CharHandler::handleCharacterDeleteResponse(Net::MessageIn &msg)
+{
+ int errMsg = msg.readInt8();
+ if (errMsg == ERRMSG_OK)
+ {
+ // Character deletion successful
+ delete mSelectedCharacter;
+ mCharacters.remove(mSelectedCharacter);
+// mSelectedCharacter = 0;
+ updateCharSelectDialog();
+ new OkDialog(_("Info"), _("Player deleted."));
+ }
+ else
+ {
+ // Character deletion failed
+ std::string errorMessage("");
+ switch (errMsg)
+ {
+ case ERRMSG_NO_LOGIN:
+ errorMessage = _("Not logged in.");
+ break;
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage = _("Selection out of range.");
+ break;
+ default:
+ errorMessage = strprintf(_("Unknown error (%d)."), errMsg);
+ }
+ new OkDialog(_("Error"), errorMessage, DIALOG_ERROR);
+ }
+ mSelectedCharacter = 0;
+ unlockCharSelectDialog();
+}
+
+void CharHandler::handleCharacterSelectResponse(Net::MessageIn &msg)
+{
+ int errMsg = msg.readInt8();
+
+ if (errMsg == ERRMSG_OK)
+ {
+ netToken = msg.readString(32);
+
+ gameServer.hostname.assign(msg.readString());
+ gameServer.port = msg.readInt16();
+
+ chatServer.hostname.assign(msg.readString());
+ chatServer.port = msg.readInt16();
+
+ logger->log("Game server: %s:%d", gameServer.hostname.c_str(),
+ gameServer.port);
+ logger->log("Chat server: %s:%d", chatServer.hostname.c_str(),
+ chatServer.port);
+
+ // Prevent the selected local player from being deleted
+ player_node = mSelectedCharacter->dummy;
+ PlayerInfo::setBackend(mSelectedCharacter->data);
+ mSelectedCharacter->dummy = 0;
+
+ Client::setState(STATE_CONNECT_GAME);
+ }
+ else if (errMsg == ERRMSG_FAILURE)
+ {
+ errorMessage = _("No gameservers are available.");
+ delete_all(mCharacters);
+ mCharacters.clear();
+ Client::setState(STATE_ERROR);
+ }
+}
+
+void CharHandler::setCharSelectDialog(CharSelectDialog *window)
+{
+ mCharSelectDialog = window;
+ updateCharacters();
+}
+
+void CharHandler::setCharCreateDialog(CharCreateDialog *window)
+{
+ mCharCreateDialog = window;
+
+ if (!mCharCreateDialog)
+ return;
+
+ mCharCreateDialog->setAttributes(Attributes::getLabels(),
+ Attributes::getCreationPoints(),
+ Attributes::getAttributeMinimum(),
+ Attributes::getAttributeMaximum());
+}
+
+void CharHandler::requestCharacters()
+{
+ if (!accountServerConnection->isConnected())
+ {
+ Net::getLoginHandler()->connect();
+ }
+ else
+ {
+ // The characters are already there, continue to character selection
+ Client::setState(STATE_CHAR_SELECT);
+ }
+}
+
+void CharHandler::chooseCharacter(Net::Character *character)
+{
+ mSelectedCharacter = character;
+
+ MessageOut msg(PAMSG_CHAR_SELECT);
+ msg.writeInt8(mSelectedCharacter->slot);
+ accountServerConnection->send(msg);
+}
+
+void CharHandler::newCharacter(const std::string &name,
+ int slot,
+ bool gender,
+ int hairstyle,
+ int hairColor, unsigned char race,
+ const std::vector<int> &stats)
+{
+ MessageOut msg(PAMSG_CHAR_CREATE);
+
+ msg.writeString(name);
+ msg.writeInt8(hairstyle);
+ msg.writeInt8(hairColor);
+ msg.writeInt8(gender);
+ msg.writeInt8(slot);
+
+ std::vector<int>::const_iterator it, it_end;
+ for (it = stats.begin(), it_end = stats.end(); it != it_end; ++it)
+ msg.writeInt16((*it));
+
+ accountServerConnection->send(msg);
+}
+
+void CharHandler::deleteCharacter(Net::Character *character)
+{
+ mSelectedCharacter = character;
+
+ MessageOut msg(PAMSG_CHAR_DELETE);
+ msg.writeInt8(mSelectedCharacter->slot);
+ accountServerConnection->send(msg);
+}
+
+void CharHandler::switchCharacter()
+{
+ gameHandler->quit(true);
+}
+
+unsigned int CharHandler::baseSprite() const
+{
+ return SPRITE_BASE;
+}
+
+unsigned int CharHandler::hairSprite() const
+{
+ return SPRITE_HAIR;
+}
+
+unsigned int CharHandler::maxSprite() const
+{
+ return SPRITE_VECTOREND;
+}
+
+void CharHandler::updateCharacters()
+{
+ // Delete previous characters
+ delete_all(mCharacters);
+ mCharacters.clear();
+
+ if (!mCharSelectDialog)
+ return;
+
+ // Create new characters and initialize them from the cached infos
+ for (unsigned i = 0; i < mCachedCharacterInfos.size(); ++i)
+ {
+ const CachedCharacterInfo &info = mCachedCharacterInfos.at(i);
+
+ Net::Character *character = new Net::Character;
+ character->slot = info.slot;
+ LocalPlayer *player = character->dummy = new LocalPlayer;
+ player->setName(info.name);
+ player->setGender(info.gender);
+ player->setSprite(SPRITE_HAIR, info.hairStyle * -1,
+ ColorDB::getHairColor(info.hairColor));
+ character->data.mAttributes[LEVEL] = info.level;
+ character->data.mAttributes[CHAR_POINTS] = info.characterPoints;
+ character->data.mAttributes[CORR_POINTS] = info.correctionPoints;
+
+ for (CachedAttributes::const_iterator it = info.attribute.begin(),
+ it_end = info.attribute.end(); it != it_end; ++it)
+ {
+ character->data.mStats[i].base = it->second.base;
+ character->data.mStats[i].mod = it->second.mod;
+ }
+
+ mCharacters.push_back(character);
+ }
+
+ updateCharSelectDialog();
+}
+
+void CharHandler::clear()
+{
+ setCharCreateDialog(0);
+ setCharSelectDialog(0);
+
+ mCachedCharacterInfos.clear();
+ updateCharacters();
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/gamehandler.h b/src/net/manaserv/gamehandler.h
new file mode 100644
index 000000000..2019755ea
--- /dev/null
+++ b/src/net/manaserv/gamehandler.h
@@ -0,0 +1,72 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2012 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NET_MANASERV_MAPHANDLER_H
+#define NET_MANASERV_MAPHANDLER_H
+
+#include "net/gamehandler.h"
+#include "net/serverinfo.h"
+
+#include "net/manaserv/messagehandler.h"
+
+namespace ManaServ
+{
+
+class GameHandler : public MessageHandler, public Net::GameHandler
+{
+ public:
+ GameHandler();
+
+ void handleMessage(Net::MessageIn &msg);
+
+ void connect();
+
+ bool isConnected();
+
+ void disconnect();
+
+ void who();
+
+ void quit(bool reconnectAccount);
+
+ void quit()
+ { quit(false); }
+
+ void ping(int tick);
+
+ bool removeDeadBeings() const
+ { return false; }
+
+ void clear();
+
+ void gameLoading();
+
+ /** The ManaServ protocol doesn't use the MP status bar. */
+ bool canUseMagicBar() const
+ { return false; }
+
+ void disconnect2();
+};
+
+} // namespace ManaServ
+
+#endif // NET_MANASERV_MAPHANDLER_H
diff --git a/src/net/manaserv/inventoryhandler.cpp b/src/net/manaserv/inventoryhandler.cpp
new file mode 100644
index 000000000..2c9c84c76
--- /dev/null
+++ b/src/net/manaserv/inventoryhandler.cpp
@@ -0,0 +1,220 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2012 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "net/manaserv/inventoryhandler.h"
+
+#include "equipment.h"
+#include "inventory.h"
+#include "item.h"
+#include "itemshortcut.h"
+#include "localplayer.h"
+#include "playerinfo.h"
+
+#include "gui/chatwindow.h"
+
+#include "net/manaserv/connection.h"
+#include "net/manaserv/messagein.h"
+#include "net/manaserv/messageout.h"
+#include "net/manaserv/protocol.h"
+
+#include "resources/iteminfo.h"
+
+#include "logger.h" // <<< REMOVE ME!
+
+extern Net::InventoryHandler *inventoryHandler;
+
+namespace ManaServ
+{
+
+extern Connection *gameServerConnection;
+
+InventoryHandler::InventoryHandler()
+{
+ static const Uint16 _messages[] =
+ {
+ GPMSG_INVENTORY_FULL,
+ GPMSG_INVENTORY,
+ GPMSG_EQUIP,
+ 0
+ };
+ handledMessages = _messages;
+ inventoryHandler = this;
+}
+
+void InventoryHandler::handleMessage(Net::MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case GPMSG_INVENTORY_FULL:
+ {
+ PlayerInfo::clearInventory();
+ PlayerInfo::getEquipment()->setBackend(&mEquips);
+ int count = msg.readInt16();
+ while (count--)
+ {
+ unsigned int slot = msg.readInt16();
+ int id = msg.readInt16();
+ unsigned int amount = msg.readInt16();
+ PlayerInfo::setInventoryItem(slot, id, amount, 0);
+ }
+ while (msg.getUnreadLength())
+ {
+ unsigned int slot = msg.readInt8();
+ unsigned int ref = msg.readInt16();
+
+ mEquips.addEquipment(slot, ref);
+ }
+ }
+ break;
+
+ case GPMSG_INVENTORY:
+ while (msg.getUnreadLength())
+ {
+ unsigned int slot = msg.readInt16();
+ int id = msg.readInt16();
+ unsigned int amount = id ? msg.readInt16() : 0;
+ PlayerInfo::setInventoryItem(slot, id, amount, 0);
+ }
+ break;
+
+ case GPMSG_EQUIP:
+ while (msg.getUnreadLength())
+ {
+ unsigned int ref = msg.readInt16();
+ int count = msg.readInt8();
+ while (count--)
+ {
+ unsigned int slot = msg.readInt8();
+ unsigned int used = msg.readInt8();
+
+ mEquips.setEquipment(slot, used, ref);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void InventoryHandler::equipItem(const Item *item)
+{
+ MessageOut msg(PGMSG_EQUIP);
+ msg.writeInt8(item->getInvIndex());
+ gameServerConnection->send(msg);
+}
+
+void InventoryHandler::unequipItem(const Item *item)
+{
+ MessageOut msg(PGMSG_UNEQUIP);
+ msg.writeInt8(item->getInvIndex());
+ gameServerConnection->send(msg);
+
+/*
+ // Tidy equipment directly to avoid weapon still shown bug, for instance
+ int equipSlot = item->getInvIndex();
+ logger->log("Unequipping %d", equipSlot);
+ mEquips.setEquipment(equipSlot, 0);
+*/
+}
+
+void InventoryHandler::useItem(const Item *item)
+{
+ MessageOut msg(PGMSG_USE_ITEM);
+ msg.writeInt8(item->getInvIndex());
+ gameServerConnection->send(msg);
+}
+
+void InventoryHandler::dropItem(const Item *item, int amount)
+{
+ MessageOut msg(PGMSG_DROP);
+ msg.writeInt8(item->getInvIndex());
+ msg.writeInt8(amount);
+ gameServerConnection->send(msg);
+}
+
+bool InventoryHandler::canSplit(const Item *item) const
+{
+ return item && !item->isEquipment() && item->getQuantity() > 1;
+}
+
+void InventoryHandler::splitItem(const Item *item, int amount)
+{
+ int newIndex = PlayerInfo::getInventory()->getFreeSlot();
+ if (newIndex > Inventory::NO_SLOT_INDEX)
+ {
+ MessageOut msg(PGMSG_MOVE_ITEM);
+ msg.writeInt8(item->getInvIndex());
+ msg.writeInt8(newIndex);
+ msg.writeInt8(amount);
+ gameServerConnection->send(msg);
+ }
+}
+
+void InventoryHandler::moveItem(int oldIndex, int newIndex)
+{
+ if (oldIndex == newIndex)
+ return;
+
+ MessageOut msg(PGMSG_MOVE_ITEM);
+ msg.writeInt8(oldIndex);
+ msg.writeInt8(newIndex);
+ msg.writeInt8(PlayerInfo::getInventory()->getItem(oldIndex)
+ ->getQuantity());
+ gameServerConnection->send(msg);
+}
+
+void InventoryHandler::openStorage(int type A_UNUSED)
+{
+ // TODO
+}
+
+void InventoryHandler::closeStorage(int type A_UNUSED)
+{
+ // TODO
+}
+
+void InventoryHandler::moveItem2(int source A_UNUSED, int slot A_UNUSED,
+ int amount A_UNUSED, int destination A_UNUSED)
+{
+ // TODO
+}
+
+size_t InventoryHandler::getSize(int type) const
+{
+ switch (type)
+ {
+ case Inventory::INVENTORY:
+ case Inventory::TRADE:
+ return 50;
+ case Inventory::STORAGE:
+ return 300;
+ default:
+ return 0;
+ }
+}
+
+int InventoryHandler::convertFromServerSlot(int eAthenaSlot) const
+{
+ return eAthenaSlot;
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/inventoryhandler.h b/src/net/manaserv/inventoryhandler.h
new file mode 100644
index 000000000..af340399e
--- /dev/null
+++ b/src/net/manaserv/inventoryhandler.h
@@ -0,0 +1,104 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2012 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NET_MANASERV_INVENTORYHANDLER_H
+#define NET_MANASERV_INVENTORYHANDLER_H
+
+#include "equipment.h"
+
+#include "net/inventoryhandler.h"
+
+#include "net/manaserv/messagehandler.h"
+
+namespace ManaServ
+{
+
+class EquipBackend : public Equipment::Backend
+{
+ public:
+ EquipBackend()
+ { memset(mEquipment, 0, sizeof(mEquipment)); }
+
+ Item *getEquipment(int index) const
+ { return mEquipment[index]; }
+
+ void clear()
+ {
+ for (int i = 0; i < EQUIPMENT_SIZE; ++i)
+ delete mEquipment[i];
+
+ std::fill_n(mEquipment, EQUIPMENT_SIZE, (Item*) 0);
+ }
+
+ void setEquipment(unsigned int slot, unsigned int used, int reference)
+ {
+ printf("Equip: %d at %dx%d\n", reference, slot, used);
+ }
+
+ void addEquipment(unsigned int slot, int reference)
+ {
+ printf("Equip: %d at %d\n", reference, slot);
+ }
+
+ private:
+ Item *mEquipment[EQUIPMENT_SIZE];
+};
+
+class InventoryHandler : public MessageHandler, Net::InventoryHandler
+{
+ public:
+ InventoryHandler();
+
+ void handleMessage(Net::MessageIn &msg);
+
+ void equipItem(const Item *item);
+
+ void unequipItem(const Item *item);
+
+ void useItem(const Item *item);
+
+ void dropItem(const Item *item, int amount);
+
+ bool canSplit(const Item *item) const;
+
+ void splitItem(const Item *item, int amount);
+
+ void moveItem(int oldIndex, int newIndex);
+
+ void openStorage(int type);
+
+ void closeStorage(int type);
+
+ void moveItem2(int source, int slot, int amount,
+ int destination);
+
+ size_t getSize(int type) const;
+
+ int convertFromServerSlot(int eAthenaSlot) const;
+
+ private:
+ EquipBackend mEquips;
+};
+
+} // namespace ManaServ
+
+#endif // NET_MANASERV_INVENTORYHANDLER_H
diff --git a/src/net/manaserv/itemhandler.cpp b/src/net/manaserv/itemhandler.cpp
new file mode 100644
index 000000000..8ebe965ec
--- /dev/null
+++ b/src/net/manaserv/itemhandler.cpp
@@ -0,0 +1,91 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2012 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "net/manaserv/itemhandler.h"
+
+#include "actorspritemanager.h"
+
+#include "net/manaserv/protocol.h"
+#include "net/manaserv/messagein.h"
+
+#include "game.h"
+#include "map.h"
+#include "logger.h"
+
+namespace ManaServ
+{
+
+ItemHandler::ItemHandler()
+{
+ static const Uint16 _messages[] =
+ {
+ GPMSG_ITEMS,
+ GPMSG_ITEM_APPEAR,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void ItemHandler::handleMessage(Net::MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case GPMSG_ITEM_APPEAR:
+ case GPMSG_ITEMS:
+ {
+ while (msg.getUnreadLength())
+ {
+ int itemId = msg.readInt16();
+ int x = msg.readInt16();
+ int y = msg.readInt16();
+ int id = (x << 16) | y; // dummy id
+
+ if (itemId)
+ {
+ if (Game *game = Game::instance())
+ {
+ if (Map *map = game->getCurrentMap())
+ {
+ actorSpriteManager->createItem(id, itemId,
+ x / map->getTileWidth(),
+ y / map->getTileHeight(),
+ 0, 1, 0, 0);
+ }
+ else
+ {
+ logger->log(
+ "ItemHandler: An item wasn't created "
+ "because of Game/Map not initialized...");
+ }
+ }
+ }
+ else if (FloorItem *item = actorSpriteManager->findItem(id))
+ {
+ actorSpriteManager->destroy(item);
+ }
+ }
+ } break;
+ default: break;
+ }
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/loginhandler.cpp b/src/net/manaserv/loginhandler.cpp
new file mode 100644
index 000000000..f93d8e44c
--- /dev/null
+++ b/src/net/manaserv/loginhandler.cpp
@@ -0,0 +1,499 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2012 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "net/manaserv/loginhandler.h"
+
+#include "client.h"
+#include "logger.h"
+
+#include "net/logindata.h"
+
+#include "net/manaserv/connection.h"
+#include "net/manaserv/messagein.h"
+#include "net/manaserv/messageout.h"
+#include "net/manaserv/protocol.h"
+
+#include "utils/gettext.h"
+#include "utils/paths.h"
+#include "utils/sha256.h"
+
+extern Net::LoginHandler *loginHandler;
+
+namespace ManaServ
+{
+
+extern Connection *accountServerConnection;
+extern std::string netToken;
+
+LoginHandler::LoginHandler()
+{
+ static const Uint16 _messages[] =
+ {
+ APMSG_LOGIN_RESPONSE,
+ APMSG_REGISTER_RESPONSE,
+ APMSG_RECONNECT_RESPONSE,
+ APMSG_PASSWORD_CHANGE_RESPONSE,
+ APMSG_EMAIL_CHANGE_RESPONSE,
+ APMSG_LOGOUT_RESPONSE,
+ APMSG_UNREGISTER_RESPONSE,
+ APMSG_REGISTER_INFO_RESPONSE,
+ 0
+ };
+ handledMessages = _messages;
+ loginHandler = this;
+ mMinUserNameLength = 4;
+ mMaxUserNameLength = 10;
+ mLoginData = 0;
+}
+
+void LoginHandler::handleMessage(Net::MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case APMSG_LOGIN_RESPONSE:
+ handleLoginResponse(msg);
+ break;
+
+ case APMSG_REGISTER_RESPONSE:
+ handleRegisterResponse(msg);
+ break;
+
+ case APMSG_RECONNECT_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+ // Successful login
+ if (errMsg == ERRMSG_OK)
+ {
+ Client::setState(STATE_CHAR_SELECT);
+ }
+ // Login failed
+ else
+ {
+ switch (errMsg)
+ {
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage = _("Wrong magic_token.");
+ break;
+ case ERRMSG_FAILURE:
+ errorMessage = _("Already logged in.");
+ break;
+ case LOGIN_BANNED:
+ errorMessage = _("Account banned.");
+ break;
+ default:
+ errorMessage = _("Unknown error.");
+ break;
+ }
+ Client::setState(STATE_ERROR);
+ }
+ }
+ break;
+
+ case APMSG_PASSWORD_CHANGE_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+ // Successful pass change
+ if (errMsg == ERRMSG_OK)
+ {
+ Client::setState(STATE_CHANGEPASSWORD_SUCCESS);
+ }
+ // pass change failed
+ else
+ {
+ switch (errMsg)
+ {
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage = _("New password incorrect.");
+ break;
+ case ERRMSG_FAILURE:
+ errorMessage = _("Old password incorrect.");
+ break;
+ case ERRMSG_NO_LOGIN:
+ errorMessage =
+ _("Account not connected. Please login first.");
+ break;
+ default:
+ errorMessage = _("Unknown error.");
+ break;
+ }
+ Client::setState(STATE_ACCOUNTCHANGE_ERROR);
+ }
+ }
+ break;
+
+ case APMSG_EMAIL_CHANGE_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+ // Successful pass change
+ if (errMsg == ERRMSG_OK)
+ {
+ Client::setState(STATE_CHANGEEMAIL_SUCCESS);
+ }
+ // pass change failed
+ else
+ {
+ switch (errMsg)
+ {
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage = _("New email address incorrect.");
+ break;
+ case ERRMSG_FAILURE:
+ errorMessage = _("Old email address incorrect.");
+ break;
+ case ERRMSG_NO_LOGIN:
+ errorMessage =
+ _("Account not connected. Please login first.");
+ break;
+ case ERRMSG_EMAIL_ALREADY_EXISTS:
+ errorMessage =
+ _("The new email address already exists.");
+ break;
+ default:
+ errorMessage = _("Unknown error.");
+ break;
+ }
+ Client::setState(STATE_ACCOUNTCHANGE_ERROR);
+ }
+ }
+ break;
+ case APMSG_LOGOUT_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+
+ // Successful logout
+ if (errMsg == ERRMSG_OK)
+ {
+ // TODO: handle logout
+ }
+ // Logout failed
+ else
+ {
+ switch (errMsg)
+ {
+ case ERRMSG_NO_LOGIN:
+ errorMessage = "Accountserver: Not logged in";
+ break;
+ default:
+ errorMessage = "Accountserver: Unknown error";
+ break;
+ }
+ Client::setState(STATE_ERROR);
+ }
+ }
+ break;
+ case APMSG_UNREGISTER_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+ // Successful unregistration
+ if (errMsg == ERRMSG_OK)
+ {
+ Client::setState(STATE_UNREGISTER);
+ }
+ // Unregistration failed
+ else
+ {
+ switch (errMsg)
+ {
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage =
+ "Accountserver: Wrong username or password";
+ break;
+ default:
+ errorMessage = "Accountserver: Unknown error";
+ break;
+ }
+ Client::setState(STATE_ACCOUNTCHANGE_ERROR);
+ }
+ }
+ break;
+
+ case APMSG_REGISTER_INFO_RESPONSE:
+ {
+ int allowed = msg.readInt8();
+
+ if (allowed)
+ {
+ mMinUserNameLength = msg.readInt8();
+ mMaxUserNameLength = msg.readInt8();
+ std::string captchaURL = msg.readString();
+ std::string captchaInstructions = msg.readString();
+
+ printf("%s: %s\n", captchaURL.c_str(),
+ captchaInstructions.c_str());
+
+ Client::setState(STATE_REGISTER);
+ }
+ else
+ {
+ errorMessage = msg.readString();
+
+ if (errorMessage.empty())
+ errorMessage = _("Client registration is not allowed. "
+ "Please contact server administration.");
+ Client::setState(STATE_LOGIN_ERROR);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void LoginHandler::handleLoginResponse(Net::MessageIn &msg)
+{
+ const int errMsg = msg.readInt8();
+
+ if (errMsg == ERRMSG_OK)
+ {
+ readServerInfo(msg);
+ // No worlds atm, but future use :-D
+ Client::setState(STATE_WORLD_SELECT);
+ }
+ else
+ {
+ switch (errMsg)
+ {
+ case LOGIN_INVALID_VERSION:
+ errorMessage = _("Client version is too old.");
+ break;
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage = _("Wrong username or password.");
+ break;
+ case ERRMSG_FAILURE:
+ errorMessage = _("Already logged in.");
+ break;
+ case LOGIN_BANNED:
+ errorMessage = _("Account banned");
+ break;
+ case LOGIN_INVALID_TIME:
+ errorMessage = _("Login attempt too soon after previous "
+ "attempt.");
+ break;
+ default:
+ errorMessage = _("Unknown error.");
+ break;
+ }
+ Client::setState(STATE_LOGIN_ERROR);
+ }
+}
+
+void LoginHandler::handleRegisterResponse(Net::MessageIn &msg)
+{
+ const int errMsg = msg.readInt8();
+
+ if (errMsg == ERRMSG_OK)
+ {
+ readServerInfo(msg);
+ Client::setState(STATE_WORLD_SELECT);
+ }
+ else
+ {
+ switch (errMsg)
+ {
+ case REGISTER_INVALID_VERSION:
+ errorMessage = _("Client version is too old.");
+ break;
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage = _("Wrong username, password or email address.");
+ break;
+ case REGISTER_EXISTS_USERNAME:
+ errorMessage = _("Username already exists.");
+ break;
+ case REGISTER_EXISTS_EMAIL:
+ errorMessage = _("Email address already exists.");
+ break;
+ case REGISTER_CAPTCHA_WRONG:
+ errorMessage = _("You took too long with the captcha or your "
+ "response was incorrect.");
+ break;
+ default:
+ errorMessage = _("Unknown error.");
+ break;
+ }
+ Client::setState(STATE_LOGIN_ERROR);
+ }
+}
+
+void LoginHandler::readServerInfo(Net::MessageIn &msg)
+{
+ // Safety check for outdated manaserv versions (remove me later)
+ if (msg.getUnreadLength() == 0)
+ return;
+
+ // Set the update host when included in the message
+ std::string updateHost = msg.readString();
+ if (!updateHost.empty())
+ {
+ if (!checkPath(updateHost))
+ {
+ logger->log1("Warning: incorrect update server name");
+ updateHost = "";
+ }
+ mLoginData->updateHost = updateHost;
+ }
+ else
+ {
+ logger->log1("Warning: server does not have an update host set!");
+ }
+
+ // Read the client data folder for dynamic data loading.
+ // This is only used by the QT client.
+ msg.readString();
+
+ // Read the number of character slots
+ mLoginData->characterSlots = msg.readInt8();
+}
+
+void LoginHandler::connect()
+{
+ accountServerConnection->connect(mServer.hostname, mServer.port);
+}
+
+bool LoginHandler::isConnected()
+{
+ return accountServerConnection->isConnected();
+}
+
+void LoginHandler::disconnect()
+{
+ accountServerConnection->disconnect();
+
+ if (Client::getState() == STATE_CONNECT_GAME)
+ {
+ Client::setState(STATE_GAME);
+ }
+}
+
+bool LoginHandler::isRegistrationEnabled()
+{
+ return true;
+}
+
+void LoginHandler::getRegistrationDetails()
+{
+ MessageOut msg(PAMSG_REQUEST_REGISTER_INFO);
+ accountServerConnection->send(msg);
+}
+
+unsigned int LoginHandler::getMinUserNameLength() const
+{
+ return mMinUserNameLength;
+}
+
+unsigned int LoginHandler::getMaxUserNameLength() const
+{
+ return mMaxUserNameLength;
+}
+
+void LoginHandler::loginAccount(LoginData *loginData)
+{
+ mLoginData = loginData;
+
+ MessageOut msg(PAMSG_LOGIN);
+
+ msg.writeInt32(0); // client version
+ msg.writeString(loginData->username);
+ msg.writeString(sha256(loginData->username + loginData->password));
+
+ accountServerConnection->send(msg);
+}
+
+void LoginHandler::logout()
+{
+ MessageOut msg(PAMSG_LOGOUT);
+ accountServerConnection->send(msg);
+}
+
+void LoginHandler::changeEmail(const std::string &email)
+{
+ MessageOut msg(PAMSG_EMAIL_CHANGE);
+
+ // Email is sent clearly so the server can validate the data.
+ // Encryption is assumed server-side.
+ msg.writeString(email);
+
+ accountServerConnection->send(msg);
+}
+
+void LoginHandler::changePassword(const std::string &username,
+ const std::string &oldPassword,
+ const std::string &newPassword)
+{
+ MessageOut msg(PAMSG_PASSWORD_CHANGE);
+
+ // Change password using SHA2 encryption
+ msg.writeString(sha256(username + oldPassword));
+ msg.writeString(sha256(username + newPassword));
+
+ accountServerConnection->send(msg);
+}
+
+void LoginHandler::chooseServer(unsigned int server A_UNUSED)
+{
+ // TODO
+}
+
+void LoginHandler::registerAccount(LoginData *loginData)
+{
+ mLoginData = loginData;
+
+ MessageOut msg(PAMSG_REGISTER);
+
+ msg.writeInt32(0); // client version
+ msg.writeString(loginData->username);
+ // Use a hashed password for privacy reasons
+ msg.writeString(sha256(loginData->username + loginData->password));
+ msg.writeString(loginData->email);
+ msg.writeString(loginData->captchaResponse);
+
+ accountServerConnection->send(msg);
+}
+
+void LoginHandler::unregisterAccount(const std::string &username,
+ const std::string &password)
+{
+ MessageOut msg(PAMSG_UNREGISTER);
+
+ msg.writeString(username);
+ msg.writeString(sha256(username + password));
+
+ accountServerConnection->send(msg);
+}
+
+Worlds LoginHandler::getWorlds() const
+{
+ return Worlds();
+}
+
+void LoginHandler::reconnect()
+{
+ MessageOut msg(PAMSG_RECONNECT);
+ msg.writeString(netToken, 32);
+ accountServerConnection->send(msg);
+}
+
+void LoginHandler::clearWorlds()
+{
+
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/network.cpp b/src/net/manaserv/network.cpp
new file mode 100644
index 000000000..05041c56a
--- /dev/null
+++ b/src/net/manaserv/network.cpp
@@ -0,0 +1,177 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2012 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "net/manaserv/network.h"
+
+#include "logger.h"
+
+#include "net/manaserv/connection.h"
+#include "net/manaserv/internal.h"
+#include "net/manaserv/messagehandler.h"
+#include "net/manaserv/messagein.h"
+
+#include "enet/enet.h"
+
+#include <map>
+
+#include "debug.h"
+
+/**
+ * The local host which is shared for all outgoing connections.
+ */
+namespace
+{
+ ENetHost *client;
+}
+
+namespace ManaServ
+{
+
+typedef std::map<unsigned short, MessageHandler*> MessageHandlers;
+typedef MessageHandlers::const_iterator MessageHandlerIterator;
+static MessageHandlers mMessageHandlers;
+
+void initialize()
+{
+ if (enet_initialize())
+ {
+ logger->safeError("Failed to initialize ENet.");
+ }
+
+#if defined(ENET_VERSION) && ENET_VERSION >= ENET_CUTOFF
+ client = enet_host_create(nullptr, 3, 0, 0, 0);
+#else
+ client = enet_host_create(nullptr, 3, 0, 0);
+#endif
+
+ if (!client)
+ {
+ logger->safeError("Failed to create the local host.");
+ }
+}
+
+void finalize()
+{
+ if (!client)
+ return; // Wasn't initialized at all
+
+ if (connections)
+ {
+ logger->safeError("Tried to shutdown the network subsystem "
+ "while there are network connections left!");
+ }
+
+ clearNetworkHandlers();
+ enet_deinitialize();
+}
+
+Connection *getConnection()
+{
+ if (!client)
+ {
+ logger->safeError("Tried to instantiate a network object before "
+ "initializing the network subsystem!");
+ }
+
+ return new Connection(client);
+}
+
+void registerHandler(MessageHandler *handler)
+{
+ for (const Uint16 *i = handler->handledMessages; *i; i++)
+ mMessageHandlers[*i] = handler;
+}
+
+void unregisterHandler(MessageHandler *handler)
+{
+ for (const Uint16 *i = handler->handledMessages; *i; i++)
+ mMessageHandlers.erase(*i);
+}
+
+void clearNetworkHandlers()
+{
+ mMessageHandlers.clear();
+}
+
+
+/**
+ * Dispatches a message to the appropriate message handler and
+ * destroys it afterwards.
+ */
+namespace
+{
+ void dispatchMessage(ENetPacket *packet)
+ {
+ MessageIn msg((const char *)packet->data, packet->dataLength);
+
+ MessageHandlerIterator iter = mMessageHandlers.find(msg.getId());
+
+ if (iter != mMessageHandlers.end())
+ {
+ //logger->log("Received packet %x (%i B)",
+ // msg.getId(), msg.getLength());
+ iter->second->handleMessage(msg);
+ }
+ else
+ {
+ logger->log("Unhandled packet %x (%i B)",
+ msg.getId(), msg.getLength());
+ }
+
+ // Clean up the packet now that we're done using it.
+ enet_packet_destroy(packet);
+ }
+}
+
+void flush()
+{
+ ENetEvent event;
+
+ // Check if there are any new events
+ while (enet_host_service(client, &event, 0) > 0)
+ {
+ switch (event.type)
+ {
+ case ENET_EVENT_TYPE_CONNECT:
+ logger->log("Connected to port %d.", event.peer->address.port);
+ // Store any relevant server information here.
+ event.peer->data = 0;
+ break;
+
+ case ENET_EVENT_TYPE_RECEIVE:
+ dispatchMessage(event.packet);
+ break;
+
+ case ENET_EVENT_TYPE_DISCONNECT:
+ logger->log1("Disconnected.");
+ // Reset the server information.
+ event.peer->data = 0;
+ break;
+
+ case ENET_EVENT_TYPE_NONE:
+ default:
+ break;
+ }
+ }
+}
+
+}
diff --git a/src/net/messagein.cpp b/src/net/messagein.cpp
index 0547ed337..5d15d26ac 100644
--- a/src/net/messagein.cpp
+++ b/src/net/messagein.cpp
@@ -265,7 +265,7 @@ unsigned char *MessageIn::readBytes(int length)
#ifdef ENABLEDEBUGLOG
std::string str;
for (int f = 0; f < length; f ++)
- str += strprintf ("%02x", (unsigned)buf[f]);
+ str += strprintf ("%02x", static_cast<unsigned>(buf[f]));
str += " ";
for (int f = 0; f < length; f ++)
{
diff --git a/src/net/tmwa/network.cpp b/src/net/tmwa/network.cpp
index 6e9e367c0..5d5a84a64 100644
--- a/src/net/tmwa/network.cpp
+++ b/src/net/tmwa/network.cpp
@@ -236,7 +236,7 @@ void Network::dispatchMessages()
MessageHandlerIterator iter = mMessageHandlers.find(msg.getId());
if (msg.getLength() == 0)
- logger->error("Zero length packet received. Exiting.");
+ logger->safeError("Zero length packet received. Exiting.");
if (iter != mMessageHandlers.end())
{
@@ -429,7 +429,7 @@ void Network::receive()
}
else
{
- DEBUGLOG("Receive " + toString(ret) + " bytes");
+// DEBUGLOG("Receive " + toString(ret) + " bytes");
mInSize += ret;
if (mToSkip)
{
diff --git a/src/net/tmwa/playerhandler.cpp b/src/net/tmwa/playerhandler.cpp
index bfe9eea42..a63af770a 100644
--- a/src/net/tmwa/playerhandler.cpp
+++ b/src/net/tmwa/playerhandler.cpp
@@ -229,7 +229,7 @@ void PlayerHandler::processOnlineList(Net::MessageIn &msg)
return;
}
- char *start = (char*)msg.readBytes(size);
+ char *start = reinterpret_cast<char*>(msg.readBytes(size));
if (!start)
return;
@@ -265,7 +265,7 @@ void PlayerHandler::processOnlineList(Net::MessageIn &msg)
gender = GENDER_FEMALE;
}
}
- arr.push_back(new OnlinePlayer((char*)buf,
+ arr.push_back(new OnlinePlayer(static_cast<char*>(buf),
status, level, gender, ver));
buf += strlen(buf) + 1;
}
diff --git a/src/opengl1graphics.cpp b/src/opengl1graphics.cpp
index 34e9fcda3..b04deedac 100644
--- a/src/opengl1graphics.cpp
+++ b/src/opengl1graphics.cpp
@@ -25,6 +25,7 @@
#ifdef USE_OPENGL
#include "opengl1graphics.h"
+#include "configuration.h"
#include "graphicsvertexes.h"
#include "logger.h"
@@ -46,8 +47,8 @@
GLuint OpenGL1Graphics::mLastImage = 0;
OpenGL1Graphics::OpenGL1Graphics():
- mAlpha(false), mTexture(false), mColorAlpha(false),
- mSync(false)
+ mAlpha(false), mTexture(false), mColorAlpha(false), mSync(false),
+ mFboId(0), mTextureId(0), mRboId(0)
{
mOpenGL = 2;
}
@@ -393,8 +394,10 @@ void OpenGL1Graphics::drawRescaledImagePattern(Image *image, int x, int y,
// Draw a set of textured rectangles
glBegin(GL_QUADS);
- const float scaleFactorW = (float) scaledWidth / image->getWidth();
- const float scaleFactorH = (float) scaledHeight / image->getHeight();
+ const float scaleFactorW = static_cast<float>(scaledWidth)
+ / image->getWidth();
+ const float scaleFactorH = static_cast<float>(scaledHeight)
+ / image->getHeight();
for (int py = 0; py < h; py += ih)
{
@@ -491,10 +494,54 @@ void OpenGL1Graphics::_endDraw()
popClipArea();
}
+void OpenGL1Graphics::prepareScreenshot()
+{
+#if !defined(_WIN32)
+ if (config.getBoolValue("usefbo"))
+ {
+ int h = mTarget->h;
+ int w = mTarget->w;
+
+ // create a texture object
+ glGenTextures(1, &mTextureId);
+ glBindTexture(GL_TEXTURE_2D, mTextureId);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ // create a renderbuffer object to store depth info
+ glGenRenderbuffersEXT(1, &mRboId);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mRboId);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
+ GL_DEPTH_COMPONENT, w, h);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+
+ // create a framebuffer object
+ glGenFramebuffersEXT(1, &mFboId);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFboId);
+
+ // attach the texture to FBO color attachment point
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ GL_TEXTURE_2D, mTextureId, 0);
+
+ // attach the renderbuffer to depth attachment point
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
+ GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mRboId);
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFboId);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+#endif
+}
+
SDL_Surface* OpenGL1Graphics::getScreenshot()
{
- int h = mTarget->h;
- int w = mTarget->w;
+ const int h = mTarget->h;
+ const int w = mTarget->w - (mTarget->w % 4);
GLint pack = 1;
SDL_Surface *screenshot = SDL_CreateRGBSurface(
@@ -502,6 +549,9 @@ SDL_Surface* OpenGL1Graphics::getScreenshot()
w, h, 24,
0xff0000, 0x00ff00, 0x0000ff, 0x000000);
+ if (!screenshot)
+ return nullptr;
+
if (SDL_MUSTLOCK(screenshot))
SDL_LockSurface(screenshot);
@@ -528,6 +578,29 @@ SDL_Surface* OpenGL1Graphics::getScreenshot()
free(buf);
+#if !defined(_WIN32)
+ if (config.getBoolValue("usefbo"))
+ {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ if (mFboId)
+ {
+ glDeleteFramebuffersEXT(1, &mFboId);
+ mFboId = 0;
+ }
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+ if (mRboId)
+ {
+ glDeleteRenderbuffersEXT(1, &mRboId);
+ mRboId = 0;
+ }
+ if (mTextureId)
+ {
+ glDeleteTextures(1, &mTextureId);
+ mTextureId = 0;
+ }
+ }
+#endif
+
glPixelStorei(GL_PACK_ALIGNMENT, pack);
if (SDL_MUSTLOCK(screenshot))
diff --git a/src/opengl1graphics.h b/src/opengl1graphics.h
index 76dc3ef00..5a2d6c254 100644
--- a/src/opengl1graphics.h
+++ b/src/opengl1graphics.h
@@ -23,15 +23,16 @@
#ifndef OPENGL1GRAPHICS_H
#define OPENGL1GRAPHICS_H
+#ifdef USE_OPENGL
#include "main.h"
#include "graphics.h"
-#ifdef USE_OPENGL
-#define NO_SDL_GLEXT
+//#define NO_SDL_GLEXT
+#define GL_GLEXT_PROTOTYPES 1
#include <SDL_opengl.h>
-#endif
+#include <GL/glext.h>
class OpenGL1Graphics : public Graphics
{
@@ -128,6 +129,8 @@ class OpenGL1Graphics : public Graphics
*/
SDL_Surface *getScreenshot();
+ void prepareScreenshot();
+
static void bindTexture(GLenum target, GLuint texture);
static GLuint mLastImage;
@@ -139,6 +142,10 @@ class OpenGL1Graphics : public Graphics
bool mAlpha, mTexture;
bool mColorAlpha;
bool mSync;
+ GLuint mFboId;
+ GLuint mTextureId;
+ GLuint mRboId;
};
+#endif
#endif
diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp
index bcf46e18b..9dd655420 100644
--- a/src/openglgraphics.cpp
+++ b/src/openglgraphics.cpp
@@ -26,6 +26,7 @@
#include "graphicsvertexes.h"
#include "openglgraphics.h"
+#include "configuration.h"
#include "logger.h"
#include "resources/image.h"
@@ -50,8 +51,8 @@ const unsigned int vertexBufSize = 500;
GLuint OpenGLGraphics::mLastImage = 0;
OpenGLGraphics::OpenGLGraphics():
- mAlpha(false), mTexture(false), mColorAlpha(false),
- mSync(false)
+ mAlpha(false), mTexture(false), mColorAlpha(false), mSync(false),
+ mFboId(0), mTextureId(0), mRboId(0)
{
mOpenGL = 1;
mFloatTexArray = new GLfloat[vertexBufSize * 4 + 30];
@@ -554,8 +555,10 @@ void OpenGLGraphics::drawRescaledImagePattern(Image *image,
{
int width = (px + scaledWidth >= w) ? w - px : scaledWidth;
int dstX = x + px;
- const float visibleFractionW = (float) width / scaledWidth;
- const float visibleFractionH = (float) height / scaledHeight;
+ const float visibleFractionW = static_cast<float>(width)
+ / scaledWidth;
+ const float visibleFractionH = static_cast<float>(height)
+ / scaledHeight;
const float texX2 = texX1 + tFractionW * visibleFractionW;
const float texY2 = texY1 + tFractionH * visibleFractionH;
@@ -597,8 +600,8 @@ void OpenGLGraphics::drawRescaledImagePattern(Image *image,
}
else
{
- const float scaleFactorW = (float) scaledWidth / iw;
- const float scaleFactorH = (float) scaledHeight / ih;
+ const float scaleFactorW = static_cast<float>(scaledWidth) / iw;
+ const float scaleFactorH = static_cast<float>(scaledHeight) / ih;
for (int py = 0; py < h; py += scaledHeight)
{
@@ -1011,7 +1014,6 @@ void OpenGLGraphics::_beginDraw()
glLoadIdentity();
glEnable(GL_SCISSOR_TEST);
- glEnableClientState(GL_VERTEX_ARRAY);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -1037,10 +1039,54 @@ void OpenGLGraphics::_endDraw()
popClipArea();
}
+void OpenGLGraphics::prepareScreenshot()
+{
+#if !defined(_WIN32)
+ if (config.getBoolValue("usefbo"))
+ {
+ int h = mTarget->h;
+ int w = mTarget->w;
+
+ // create a texture object
+ glGenTextures(1, &mTextureId);
+ glBindTexture(GL_TEXTURE_2D, mTextureId);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ // create a renderbuffer object to store depth info
+ glGenRenderbuffersEXT(1, &mRboId);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mRboId);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
+ GL_DEPTH_COMPONENT, w, h);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+
+ // create a framebuffer object
+ glGenFramebuffersEXT(1, &mFboId);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFboId);
+
+ // attach the texture to FBO color attachment point
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ GL_TEXTURE_2D, mTextureId, 0);
+
+ // attach the renderbuffer to depth attachment point
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
+ GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mRboId);
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFboId);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+#endif
+}
+
SDL_Surface* OpenGLGraphics::getScreenshot()
{
- int h = mTarget->h;
- int w = mTarget->w;
+ const int h = mTarget->h;
+ const int w = mTarget->w - (mTarget->w % 4);
GLint pack = 1;
SDL_Surface *screenshot = SDL_CreateRGBSurface(
@@ -1077,6 +1123,29 @@ SDL_Surface* OpenGLGraphics::getScreenshot()
free(buf);
+#if !defined(_WIN32)
+ if (config.getBoolValue("usefbo"))
+ {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ if (mFboId)
+ {
+ glDeleteFramebuffersEXT(1, &mFboId);
+ mFboId = 0;
+ }
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+ if (mRboId)
+ {
+ glDeleteRenderbuffersEXT(1, &mRboId);
+ mRboId = 0;
+ }
+ if (mTextureId)
+ {
+ glDeleteTextures(1, &mTextureId);
+ mTextureId = 0;
+ }
+ }
+#endif
+
glPixelStorei(GL_PACK_ALIGNMENT, pack);
if (SDL_MUSTLOCK(screenshot))
@@ -1104,8 +1173,11 @@ bool OpenGLGraphics::pushClipArea(gcn::Rectangle area)
transY += clipArea.yOffset;
glPushMatrix();
- glTranslatef(static_cast<GLfloat>(transX),
- static_cast<GLfloat>(transY), 0);
+ if (transX || transY)
+ {
+ glTranslatef(static_cast<GLfloat>(transX),
+ static_cast<GLfloat>(transY), 0);
+ }
glScissor(clipArea.x, mTarget->h - clipArea.y - clipArea.height,
clipArea.width, clipArea.height);
@@ -1349,4 +1421,24 @@ inline void OpenGLGraphics::drawLineArrayf(int size)
glDrawArrays(GL_LINES, 0, size / 2);
}
+void OpenGLGraphics::dumpSettings()
+{
+ GLint test[1000];
+ logger->log("\n\n");
+ logger->log("start opengl dump");
+ for (int f = 0; f < 65535; f ++)
+ {
+ test[0] = 0;
+ test[1] = 0;
+ test[2] = 0;
+ test[3] = 0;
+ glGetIntegerv(f, &test[0]);
+ if (test[0] || test[1] || test[2] || test[3])
+ {
+ logger->log("\n%d = %d, %d, %d, %d", f,
+ test[0], test[1], test[2], test[3]);
+ }
+ }
+}
+
#endif // USE_OPENGL
diff --git a/src/openglgraphics.h b/src/openglgraphics.h
index f3bdc4470..650ad668a 100644
--- a/src/openglgraphics.h
+++ b/src/openglgraphics.h
@@ -23,15 +23,16 @@
#ifndef OPENGLGRAPHICS_H
#define OPENGLGRAPHICS_H
-#include "main.h"
+#ifdef USE_OPENGL
+#include "main.h"
#include "graphics.h"
-#ifdef USE_OPENGL
-#define NO_SDL_GLEXT
+//#define NO_SDL_GLEXT
+#define GL_GLEXT_PROTOTYPES 1
#include <SDL_opengl.h>
-#endif
+//#include <GL/glext.h>
class OpenGLGraphics : public Graphics
{
@@ -132,11 +133,15 @@ class OpenGLGraphics : public Graphics
void drawLineArrayf(int size);
+ static void dumpSettings();
+
/**
* Takes a screenshot and returns it as SDL surface.
*/
SDL_Surface *getScreenshot();
+ void prepareScreenshot();
+
bool drawNet(int x1, int y1, int x2, int y2, int width, int height);
static void bindTexture(GLenum target, GLuint texture);
@@ -153,6 +158,10 @@ class OpenGLGraphics : public Graphics
bool mAlpha, mTexture;
bool mColorAlpha;
bool mSync;
+ GLuint mFboId;
+ GLuint mTextureId;
+ GLuint mRboId;
};
+#endif
#endif
diff --git a/src/particlecontainer.h b/src/particlecontainer.h
index a8af163fd..4e402044b 100644
--- a/src/particlecontainer.h
+++ b/src/particlecontainer.h
@@ -57,7 +57,8 @@ public:
/**
* Kills and removes all particle effects (only in this container)
*/
- virtual void clearLocally() {}
+ virtual void clearLocally()
+ { }
/**
* Sets the positions of all elements
diff --git a/src/particleemitterprop.h b/src/particleemitterprop.h
index cadfa0f3a..2b6b7ba1a 100644
--- a/src/particleemitterprop.h
+++ b/src/particleemitterprop.h
@@ -21,6 +21,7 @@
*/
#include <cmath>
+#include <cstdlib>
/**
* Returns a random numeric value that is larger than or equal min and smaller
diff --git a/src/resources/action.cpp b/src/resources/action.cpp
index e1f88ecb7..6c799cdfa 100644
--- a/src/resources/action.cpp
+++ b/src/resources/action.cpp
@@ -69,3 +69,16 @@ void Action::setAnimation(int direction, Animation *animation)
{
mAnimations[direction] = animation;
}
+
+void Action::setLastFrameDelay(int delay)
+{
+ AnimationIter it = mAnimations.begin();
+ AnimationIter it_end = mAnimations.end();
+ for (; it != it_end; ++ it)
+ {
+ Animation *animation = (*it).second;
+ if (!animation)
+ continue;
+ animation->setLastFrameDelay(delay);
+ }
+}
diff --git a/src/resources/action.h b/src/resources/action.h
index 3951cc02c..f9c5da75b 100644
--- a/src/resources/action.h
+++ b/src/resources/action.h
@@ -29,6 +29,7 @@
class Animation;
+
/**
* An action consists of several animations, one for each direction.
*/
@@ -49,9 +50,12 @@ class Action
void setNumber(unsigned n)
{ mNumber = n; }
+ void setLastFrameDelay(int delay);
+
protected:
typedef std::map<int, Animation*> Animations;
- typedef Animations::iterator AnimationIterator;
+ typedef Animations::iterator AnimationIter;
+
Animations mAnimations;
unsigned mNumber;
};
diff --git a/src/resources/animation.cpp b/src/resources/animation.cpp
index 1c1da6ca5..388c1301e 100644
--- a/src/resources/animation.cpp
+++ b/src/resources/animation.cpp
@@ -69,3 +69,17 @@ void Animation::addGoto(std::string name, int rand)
Frame frame = { nullptr, 0, 0, 0, rand, Frame::GOTO, name };
mFrames.push_back(frame);
}
+
+void Animation::setLastFrameDelay(int delay)
+{
+ FramesRevIter it = mFrames.rbegin();
+ FramesRevIter it_end = mFrames.rend();
+ for (; it != it_end; ++ it)
+ {
+ if ((*it).type == Frame::ANIMATION && (*it).image)
+ {
+ (*it).delay = delay;
+ break;
+ }
+ }
+}
diff --git a/src/resources/animation.h b/src/resources/animation.h
index 33bfd76e9..53e9adbea 100644
--- a/src/resources/animation.h
+++ b/src/resources/animation.h
@@ -102,13 +102,19 @@ class Animation
void addGoto(std::string name, int rand);
+ void setLastFrameDelay(int delay);
+
/**
* Determines whether the given animation frame is a terminator.
*/
static bool isTerminator(const Frame &phase);
protected:
- std::vector<Frame> mFrames;
+ typedef std::vector<Frame> Frames;
+ typedef Frames::iterator FramesIter;
+ typedef Frames::reverse_iterator FramesRevIter;
+
+ Frames mFrames;
int mDuration;
};
diff --git a/src/resources/image.cpp b/src/resources/image.cpp
index 1e2bd6b51..c63fcab99 100644
--- a/src/resources/image.cpp
+++ b/src/resources/image.cpp
@@ -765,15 +765,16 @@ Image *Image::_GLload(SDL_Surface *tmpImage)
if (SDL_MUSTLOCK(tmpImage))
SDL_LockSurface(tmpImage);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glTexParameteri(mTextureType, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(mTextureType, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
glTexImage2D(mTextureType, 0, 4, tmpImage->w, tmpImage->h,
0, GL_RGBA, GL_UNSIGNED_BYTE, tmpImage->pixels);
#ifdef DEBUG_OPENGL_LEAKS
textures_count ++;
#endif
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glTexParameteri(mTextureType, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(mTextureType, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
if (SDL_MUSTLOCK(tmpImage))
SDL_UnlockSurface(tmpImage);
diff --git a/src/resources/image.h b/src/resources/image.h
index 68ab09e58..89fe24d89 100644
--- a/src/resources/image.h
+++ b/src/resources/image.h
@@ -36,7 +36,8 @@
* gl.h headers, since they also include these definitions. As we're not using
* extensions anyway it's safe to just disable the SDL version.
*/
-#define NO_SDL_GLEXT
+//#define NO_SDL_GLEXT
+#define GL_GLEXT_PROTOTYPES 1
#include <SDL_opengl.h>
#endif
diff --git a/src/resources/spritedef.cpp b/src/resources/spritedef.cpp
index 0d9b95f6f..02b46f1cf 100644
--- a/src/resources/spritedef.cpp
+++ b/src/resources/spritedef.cpp
@@ -36,6 +36,7 @@
#include "debug.h"
SpriteReference *SpriteReference::Empty = nullptr;
+extern int serverVersion;
Action *SpriteDef::getAction(std::string action, unsigned num) const
{
@@ -99,13 +100,30 @@ SpriteDef *SpriteDef::load(const std::string &animationFile, int variant)
def->mProcessedFiles.insert(animationFile);
def->loadSprite(rootNode, variant, palettes);
def->substituteActions();
+ if (serverVersion < 1)
+ def->fixDeadAction();
return def;
}
+void SpriteDef::fixDeadAction()
+{
+ ActionsIter it = mActions.begin();
+ ActionsIter it_end = mActions.end();
+ for (; it != it_end; ++ it)
+ {
+ ActionMap *d = (*it).second;
+ if (!d)
+ continue;
+ ActionMap::iterator i = d->find("dead");
+ if (i != d->end() && i->second)
+ (i->second)->setLastFrameDelay(0);
+ }
+}
+
void SpriteDef::substituteAction(std::string complete, std::string with)
{
- Actions::const_iterator it = mActions.begin();
- Actions::const_iterator it_end = mActions.end();
+ ActionsConstIter it = mActions.begin();
+ ActionsConstIter it_end = mActions.end();
for (; it != it_end; ++ it)
{
ActionMap *d = (*it).second;
diff --git a/src/resources/spritedef.h b/src/resources/spritedef.h
index 0490bdcb3..e167cf188 100644
--- a/src/resources/spritedef.h
+++ b/src/resources/spritedef.h
@@ -176,6 +176,11 @@ class SpriteDef : public Resource
void substituteActions();
/**
+ * Fix bad timeout in last dead action frame
+ */
+ void fixDeadAction();
+
+ /**
* When there are no animations defined for the action "complete", its
* animations become a copy of those of the action "with".
*/
@@ -185,6 +190,8 @@ class SpriteDef : public Resource
typedef ImageSets::iterator ImageSetIterator;
typedef std::map<std::string, Action*> ActionMap;
typedef std::map<unsigned, ActionMap*> Actions;
+ typedef Actions::const_iterator ActionsConstIter;
+ typedef Actions::iterator ActionsIter;
ImageSets mImageSets;
Actions mActions;
diff --git a/src/sound.cpp b/src/sound.cpp
index 913b55656..5b7f1201d 100644
--- a/src/sound.cpp
+++ b/src/sound.cpp
@@ -66,9 +66,7 @@ Sound::Sound():
Sound::~Sound()
{
- config.removeListener("playBattleSound", this);
- config.removeListener("playGuiSound", this);
- config.removeListener("playMusic", this);
+ config.removeListeners(this);
// Unlink the callback function.
Mix_HookMusicFinished(nullptr);
@@ -82,6 +80,10 @@ void Sound::optionChanged(const std::string &value)
mPlayGui = config.getBoolValue("playGuiSound");
else if (value == "playMusic")
mPlayMusic = config.getBoolValue("playMusic");
+ else if (value == "sfxVolume")
+ setSfxVolume(config.getIntValue("sfxVolume"));
+ else if (value == "musicVolume")
+ setMusicVolume(config.getIntValue("musicVolume"));
}
void Sound::init()
@@ -98,6 +100,8 @@ void Sound::init()
config.addListener("playBattleSound", this);
config.addListener("playGuiSound", this);
config.addListener("playMusic", this);
+ config.addListener("sfxVolume", this);
+ config.addListener("musicVolume", this);
if (SDL_InitSubSystem(SDL_INIT_AUDIO) == -1)
{
@@ -317,6 +321,12 @@ void Sound::playSfx(const std::string &path, int x, int y)
}
}
+void Sound::playGuiSound(const std::string &name)
+{
+ playGuiSfx(branding.getStringValue("systemsounds")
+ + config.getStringValue(name) + ".ogg");
+}
+
void Sound::playGuiSfx(const std::string &path)
{
if (!mInstalled || path.empty() || !mPlayGui)
diff --git a/src/sound.h b/src/sound.h
index 7f9fb64a4..a967d0a92 100644
--- a/src/sound.h
+++ b/src/sound.h
@@ -31,6 +31,15 @@
class Music;
+const static std::string SOUND_INFO = "soundinfo";
+const static std::string SOUND_ERROR = "sounderror";
+const static std::string SOUND_REQUEST = "soundrequest";
+const static std::string SOUND_TRADE = "soundtrade";
+const static std::string SOUND_WHISPER = "soundwhisper";
+const static std::string SOUND_HIGHLIGHT = "soundhighlight";
+const static std::string SOUND_GLOBAL = "soundglobal";
+const static std::string SOUND_GUILD = "soundguild";
+
/** Sound engine
*
* \ingroup CORE
@@ -109,6 +118,8 @@ class Sound : public ConfigListener
*/
void playGuiSfx(const std::string &path);
+ void playGuiSound(const std::string &name);
+
void changeAudio();
void volumeOff();
diff --git a/src/sprite.h b/src/sprite.h
index ffee97d49..ab2dcfc6a 100644
--- a/src/sprite.h
+++ b/src/sprite.h
@@ -32,7 +32,8 @@ class Image;
class Sprite
{
public:
- virtual ~Sprite() {}
+ virtual ~Sprite()
+ { }
/**
* Resets the sprite.
diff --git a/src/utils/checkutils.cpp b/src/utils/checkutils.cpp
index 64bb42d0c..abbc6138a 100644
--- a/src/utils/checkutils.cpp
+++ b/src/utils/checkutils.cpp
@@ -24,6 +24,8 @@
#include "logger.h"
+#include "debug.h"
+
bool reportFalseReal(bool val, const char* file, unsigned line)
{
if (!val)
diff --git a/src/utils/copynpaste.cpp b/src/utils/copynpaste.cpp
index 90e0c5c93..763b579d0 100644
--- a/src/utils/copynpaste.cpp
+++ b/src/utils/copynpaste.cpp
@@ -442,9 +442,15 @@ bool runxsel(std::string& text, const char *p1, const char *p2)
close(fd[0]);
}
if (p2)
- execl("/usr/bin/xsel", "xsel", p1, p2, (char *)nullptr);
+ {
+ execl("/usr/bin/xsel", "xsel", p1, p2,
+ static_cast<char *>(nullptr));
+ }
else
- execl("/usr/bin/xsel", "xsel", p1, (char *)nullptr);
+ {
+ execl("/usr/bin/xsel", "xsel", p1,
+ static_cast<char *>(nullptr));
+ }
exit(1);
}
diff --git a/src/utils/langs.cpp b/src/utils/langs.cpp
index 2efbd781a..c1f9f7ecf 100644
--- a/src/utils/langs.cpp
+++ b/src/utils/langs.cpp
@@ -44,11 +44,11 @@ std::vector<std::string> getLang()
}
int dot = lang.find(".");
- if (dot != (signed)std::string::npos)
+ if (dot != static_cast<signed>(std::string::npos))
lang = lang.substr(0, dot);
langs.push_back(lang);
dot = lang.find("_");
- if (dot != (signed)std::string::npos)
+ if (dot != static_cast<signed>(std::string::npos))
langs.push_back(lang.substr(0, dot));
return langs;
}
@@ -78,10 +78,10 @@ std::string getLangShort()
}
int dot = lang.find(".");
- if (dot != (signed)std::string::npos)
+ if (dot != static_cast<signed>(std::string::npos))
lang = lang.substr(0, dot);
dot = lang.find("_");
- if (dot != (signed)std::string::npos)
+ if (dot != static_cast<signed>(std::string::npos))
return lang.substr(0, dot);
return lang;
}
diff --git a/src/utils/mathutils.h b/src/utils/mathutils.h
index 9f6818146..6d5a8339d 100644
--- a/src/utils/mathutils.h
+++ b/src/utils/mathutils.h
@@ -23,7 +23,9 @@
#ifndef UTILS_MATHUTILS_H
#define UTILS_MATHUTILS_H
+#include <string>
#include <stdint.h>
+#include <cstring>
static uint16_t crc_table[256] =
{
@@ -112,4 +114,9 @@ inline float weightedAverage(float n1, float n2, float w)
return w * n2 + (1.0f - w) * n1;
}
+inline int roundDouble(double v)
+{
+ return (v > 0.0) ? (v + 0.5) : (v - 0.5);
+}
+
#endif // UTILS_MATHUTILS_H
diff --git a/src/utils/physfsrwops.cpp b/src/utils/physfsrwops.cpp
index 1960f0dee..19b08d4c7 100644
--- a/src/utils/physfsrwops.cpp
+++ b/src/utils/physfsrwops.cpp
@@ -27,9 +27,11 @@
#include "localconsts.h"
+#include "debug.h"
+
static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence)
{
- PHYSFS_file *handle = (PHYSFS_file *) rw->hidden.unknown.data1;
+ PHYSFS_file *handle = static_cast<PHYSFS_file *>(rw->hidden.unknown.data1);
int pos = 0;
if (whence == SEEK_SET)
@@ -46,8 +48,8 @@ static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence)
return -1;
} /* if */
- pos = (int)current;
- if (((PHYSFS_sint64)pos) != current)
+ pos = static_cast<int>(current);
+ if (static_cast<PHYSFS_sint64>(pos) != current)
{
SDL_SetError("Can't fit current file position in an int!");
return -1;
@@ -67,8 +69,8 @@ static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence)
return -1;
} /* if */
- pos = (int)len;
- if (((PHYSFS_sint64)pos) != len)
+ pos = static_cast<int>(len);
+ if (static_cast<PHYSFS_sint64>(pos) != len)
{
SDL_SetError("Can't fit end-of-file position in an int!");
return -1;
@@ -88,7 +90,7 @@ static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence)
return -1;
} /* if */
- if (!PHYSFS_seek(handle, (PHYSFS_uint64) pos))
+ if (!PHYSFS_seek(handle, static_cast<PHYSFS_uint64>(pos)))
{
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
return -1;
@@ -99,7 +101,7 @@ static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence)
static int physfsrwops_read(SDL_RWops *rw, void *ptr, int size, int maxnum)
{
- PHYSFS_file *handle = (PHYSFS_file*)rw->hidden.unknown.data1;
+ PHYSFS_file *handle = static_cast<PHYSFS_file*>(rw->hidden.unknown.data1);
PHYSFS_sint64 rc = PHYSFS_read(handle, ptr, size, maxnum);
if (rc != maxnum)
{
@@ -107,22 +109,22 @@ static int physfsrwops_read(SDL_RWops *rw, void *ptr, int size, int maxnum)
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
} /* if */
- return (int)rc;
+ return static_cast<int>(rc);
} /* physfsrwops_read */
static int physfsrwops_write(SDL_RWops *rw, const void *ptr, int size, int num)
{
- PHYSFS_file *handle = (PHYSFS_file*)rw->hidden.unknown.data1;
+ PHYSFS_file *handle = static_cast<PHYSFS_file*>(rw->hidden.unknown.data1);
PHYSFS_sint64 rc = PHYSFS_write(handle, ptr, size, num);
if (rc != num)
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
- return (int) rc;
+ return static_cast<int>(rc);
} /* physfsrwops_write */
static int physfsrwops_close(SDL_RWops *rw)
{
- PHYSFS_file *handle = (PHYSFS_file*)rw->hidden.unknown.data1;
+ PHYSFS_file *handle = static_cast<PHYSFS_file*>(rw->hidden.unknown.data1);
if (!PHYSFS_close(handle))
{
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
diff --git a/src/utils/process.cpp b/src/utils/process.cpp
index fd0ec0fa8..0106c597d 100644
--- a/src/utils/process.cpp
+++ b/src/utils/process.cpp
@@ -112,12 +112,12 @@ int execFile(std::string pathName, std::string name,
if (arg2.empty())
{
execl(pathName.c_str(), name.c_str(),
- arg1.c_str(), (char *)nullptr);
+ arg1.c_str(), static_cast<char *>(nullptr));
}
else
{
- execl(pathName.c_str(), name.c_str(),
- arg1.c_str(), arg2.c_str(), (char *)nullptr);
+ execl(pathName.c_str(), name.c_str(), arg1.c_str(),
+ arg2.c_str(), static_cast<char *>(nullptr));
}
exit(-1);
}
diff --git a/src/utils/stringutils.cpp b/src/utils/stringutils.cpp
index 2f478a909..5a7ea87fd 100644
--- a/src/utils/stringutils.cpp
+++ b/src/utils/stringutils.cpp
@@ -522,9 +522,9 @@ std::string stringToHexPath(const std::string &str)
if (str.empty())
return "";
- std::string hex = strprintf("%%%2x/", (int)str[0]);
+ std::string hex = strprintf("%%%2x/", static_cast<int>(str[0]));
for (unsigned f = 1; f < str.size(); f ++)
- hex += strprintf("%%%2x", (int)str[f]);
+ hex += strprintf("%%%2x", static_cast<int>(str[f]));
return hex;
}
@@ -600,7 +600,7 @@ bool findCutFirst(std::string &str1, std::string str2)
std::string &removeProtocol(std::string &url)
{
int i = url.find("://");
- if (i != (int)std::string::npos)
+ if (i != static_cast<int>(std::string::npos))
url = url.substr(i + 3);
return url;
}