summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt22
-rw-r--r--src/Makefile.am38
-rw-r--r--src/animationparticle.cpp3
-rw-r--r--src/being.cpp90
-rw-r--r--src/being.h42
-rw-r--r--src/game.cpp179
-rw-r--r--src/gui/button.cpp20
-rw-r--r--src/gui/button.h10
-rw-r--r--src/gui/buy.cpp125
-rw-r--r--src/gui/buy.h10
-rw-r--r--src/gui/char_select.cpp12
-rw-r--r--src/gui/char_select.h31
-rw-r--r--src/gui/chat.cpp10
-rw-r--r--src/gui/debugwindow.cpp14
-rw-r--r--src/gui/debugwindow.h9
-rw-r--r--src/gui/equipmentwindow.cpp1
-rw-r--r--src/gui/gui.cpp45
-rw-r--r--src/gui/gui.h43
-rw-r--r--src/gui/inventorywindow.cpp13
-rw-r--r--src/gui/inventorywindow.h11
-rw-r--r--src/gui/itemcontainer.cpp4
-rw-r--r--src/gui/itemshortcutcontainer.cpp224
-rw-r--r--src/gui/itemshortcutcontainer.h115
-rw-r--r--src/gui/itemshortcutwindow.cpp74
-rw-r--r--src/gui/itemshortcutwindow.h69
-rw-r--r--src/gui/menuwindow.cpp12
-rw-r--r--src/gui/popupmenu.cpp6
-rw-r--r--src/gui/selectionlistener.h16
-rw-r--r--src/gui/sell.cpp127
-rw-r--r--src/gui/sell.h16
-rw-r--r--src/gui/setup.cpp10
-rw-r--r--src/gui/setup_keyboard.cpp187
-rw-r--r--src/gui/setup_keyboard.h84
-rw-r--r--src/gui/shoplistbox.cpp20
-rw-r--r--src/gui/skill.cpp6
-rw-r--r--src/gui/skill.h1
-rw-r--r--src/gui/status.cpp6
-rw-r--r--src/gui/status.h3
-rw-r--r--src/gui/updatewindow.cpp4
-rw-r--r--src/gui/viewport.cpp25
-rw-r--r--src/gui/viewport.h13
-rw-r--r--src/gui/window.cpp198
-rw-r--r--src/gui/window.h99
-rw-r--r--src/gui/windowlistener.h86
-rw-r--r--src/imageparticle.cpp8
-rw-r--r--src/itemshortcut.cpp87
-rw-r--r--src/itemshortcut.h130
-rw-r--r--src/keyboardconfig.cpp144
-rw-r--r--src/keyboardconfig.h185
-rw-r--r--src/localplayer.cpp43
-rw-r--r--src/localplayer.h22
-rw-r--r--src/main.cpp19
-rw-r--r--src/monster.cpp10
-rw-r--r--src/net/beinghandler.cpp84
-rw-r--r--src/net/chathandler.cpp2
-rw-r--r--src/net/inventoryhandler.cpp2
-rw-r--r--src/net/playerhandler.cpp3
-rw-r--r--src/particle.cpp96
-rw-r--r--src/particle.h112
-rw-r--r--src/particleemitter.cpp30
-rw-r--r--src/player.cpp50
-rw-r--r--src/player.h3
-rw-r--r--src/resources/equipmentdb.cpp156
-rw-r--r--src/resources/equipmentdb.h55
-rw-r--r--src/resources/itemdb.cpp126
-rw-r--r--src/resources/iteminfo.cpp86
-rw-r--r--src/resources/iteminfo.h118
-rw-r--r--src/resources/mapreader.cpp2
-rw-r--r--src/resources/monsterdb.cpp8
-rw-r--r--src/resources/monsterinfo.cpp12
-rw-r--r--src/resources/monsterinfo.h16
-rw-r--r--src/resources/spritedef.h4
-rw-r--r--src/textparticle.cpp11
-rw-r--r--src/textparticle.h17
-rw-r--r--src/utils/fastsqrt.h2
-rw-r--r--src/utils/minmax.h1
-rw-r--r--src/utils/trim.h (renamed from src/resources/equipmentinfo.h)49
-rw-r--r--src/vector.h134
78 files changed, 2855 insertions, 1105 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index fa19cfb5..96338338 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -97,6 +97,12 @@ SET(SRCS
gui/item_amount.h
gui/itemcontainer.cpp
gui/itemcontainer.h
+ gui/itemshortcutcontainer.cpp
+ gui/itemshortcutcontainer.h
+ gui/itemshortcutwindow.cpp
+ gui/itemshortcutwindow.h
+ gui/item_amount.cpp
+ gui/item_amount.h
gui/linkhandler.h
gui/listbox.cpp
gui/listbox.h
@@ -143,6 +149,8 @@ SET(SRCS
gui/setup.h
gui/setup_joystick.cpp
gui/setup_joystick.h
+ gui/setup_keyboard.cpp
+ gui/setup_keyboard.h
gui/setuptab.h
gui/setup_video.cpp
gui/setup_video.h
@@ -170,12 +178,13 @@ SET(SRCS
gui/updatewindow.h
gui/vbox.cpp
gui/vbox.h
- gui/windowcontainer.cpp
- gui/windowcontainer.h
gui/viewport.cpp
gui/viewport.h
gui/window.cpp
gui/window.h
+ gui/windowcontainer.cpp
+ gui/windowcontainer.h
+ gui/windowlistener.h
gui/widgets/dropdown.cpp
gui/widgets/dropdown.h
net/beinghandler.cpp
@@ -239,9 +248,6 @@ SET(SRCS
resources/buddylist.h
resources/animation.cpp
resources/animation.h
- resources/equipmentdb.cpp
- resources/equipmentdb.h
- resources/equipmentinfo.h
resources/image.cpp
resources/image.h
resources/imagewriter.cpp
@@ -281,6 +287,7 @@ SET(SRCS
utils/strprintf.cpp
utils/strprintf.h
utils/tostring.h
+ utils/trim.h
utils/xml.cpp
utils/xml.h
animatedsprite.cpp
@@ -317,8 +324,12 @@ SET(SRCS
inventory.h
item.cpp
item.h
+ itemshortcut.cpp
+ itemshortcut.h
joystick.cpp
joystick.h
+ keyboardconfig.cpp
+ keyboardconfig.h
localplayer.cpp
localplayer.h
lockedarray.h
@@ -351,6 +362,7 @@ SET(SRCS
textparticle.cpp
textparticle.h
tileset.h
+ vector.h
)
ADD_EXECUTABLE(tmw ${SRCS})
diff --git a/src/Makefile.am b/src/Makefile.am
index 7006f66e..2f29e299 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -5,6 +5,8 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \
gui/widgets/dropdown.h \
gui/widgets/resizegrip.cpp \
gui/widgets/resizegrip.h \
+ gui/box.h \
+ gui/box.cpp \
gui/browserbox.cpp \
gui/browserbox.h \
gui/buddywindow.cpp \
@@ -39,12 +41,20 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \
gui/gccontainer.h \
gui/gui.cpp \
gui/gui.h \
+ gui/hbox.h \
+ gui/hbox.cpp \
gui/help.cpp \
gui/help.h \
+ gui/inttextbox.h \
+ gui/inttextbox.cpp \
gui/inventorywindow.cpp \
gui/inventorywindow.h \
gui/itemcontainer.cpp \
gui/itemcontainer.h \
+ gui/itemshortcutcontainer.cpp \
+ gui/itemshortcutcontainer.h \
+ gui/itemshortcutwindow.cpp \
+ gui/itemshortcutwindow.h \
gui/item_amount.cpp \
gui/item_amount.h \
gui/linkhandler.h \
@@ -95,6 +105,8 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \
gui/setup.h \
gui/setup_joystick.cpp \
gui/setup_joystick.h \
+ gui/setup_keyboard.cpp \
+ gui/setup_keyboard.h \
gui/setuptab.h \
gui/setup_video.cpp \
gui/setup_video.h \
@@ -118,22 +130,17 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \
gui/trade.h \
gui/unregisterdialog.cpp \
gui/unregisterdialog.h \
+ gui/updatewindow.h \
+ gui/updatewindow.cpp \
+ gui/vbox.h \
+ gui/vbox.cpp \
gui/viewport.cpp \
gui/viewport.h \
gui/window.cpp \
gui/window.h \
gui/windowcontainer.cpp \
gui/windowcontainer.h \
- gui/inttextbox.h \
- gui/inttextbox.cpp \
- gui/box.h \
- gui/box.cpp \
- gui/vbox.h \
- gui/vbox.cpp \
- gui/hbox.h \
- gui/hbox.cpp \
- gui/updatewindow.h \
- gui/updatewindow.cpp \
+ gui/windowlistener.h \
net/beinghandler.h \
net/beinghandler.cpp \
net/buysellhandler.h \
@@ -193,9 +200,6 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \
resources/ambientoverlay.h \
resources/animation.cpp \
resources/animation.h \
- resources/equipmentdb.cpp \
- resources/equipmentdb.h \
- resources/equipmentinfo.h \
resources/image.cpp \
resources/image.h \
resources/imageloader.cpp \
@@ -235,6 +239,7 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \
utils/strprintf.h \
utils/strprintf.cpp \
utils/tostring.h \
+ utils/trim.h \
utils/xml.cpp \
utils/xml.h \
animatedsprite.cpp \
@@ -271,8 +276,12 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \
inventory.h \
item.cpp \
item.h \
+ itemshortcut.cpp \
+ itemshortcut.h \
joystick.cpp \
joystick.h \
+ keyboardconfig.cpp \
+ keyboardconfig.h \
localplayer.cpp \
localplayer.h \
lockedarray.h \
@@ -304,7 +313,8 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \
sprite.h \
textparticle.cpp \
textparticle.h \
- tileset.h
+ tileset.h \
+ vector.h
# set the include path found by configure
INCLUDES = \
diff --git a/src/animationparticle.cpp b/src/animationparticle.cpp
index 30c33da7..c79a5bc4 100644
--- a/src/animationparticle.cpp
+++ b/src/animationparticle.cpp
@@ -26,7 +26,7 @@
#include "simpleanimation.h"
AnimationParticle::AnimationParticle(Map *map, Animation *animation):
- ImageParticle(map, 0),
+ ImageParticle(map, NULL),
mAnimation(new SimpleAnimation(animation))
{
}
@@ -40,6 +40,7 @@ AnimationParticle::AnimationParticle(Map *map, xmlNodePtr animationNode):
AnimationParticle::~AnimationParticle()
{
delete mAnimation;
+ mImage = NULL;
}
bool AnimationParticle::update()
diff --git a/src/being.cpp b/src/being.cpp
index bdb27384..81bed667 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -36,12 +36,10 @@
#include "resources/resourcemanager.h"
#include "resources/imageset.h"
+#include "resources/iteminfo.h"
#include "gui/gui.h"
-#include "resources/resourcemanager.h"
-#include "resources/imageset.h"
-
#include "utils/dtor.h"
#include "utils/tostring.h"
@@ -58,11 +56,11 @@ Being::Being(Uint16 id, Uint16 job, Map *map):
mEquipment(new Equipment()),
mId(id),
mSex(2),
- mWeapon(0),
mWalkSpeed(150),
mSpeedModifier(1024),
mSpriteDirection(DIRECTION_DOWN), mDirection(DOWN),
mMap(NULL),
+ mEquippedWeapon(NULL),
mHairStyle(0), mHairColor(0),
mSpeechTime(0),
mPx(0), mPy(0),
@@ -302,7 +300,7 @@ Being::setSpeech(const std::string &text, Uint32 time)
void
Being::takeDamage(int amount)
{
- gcn::Font* font;
+ gcn::Font *font;
std::string damage = amount ? toString(amount) : "miss";
// Selecting the right color
@@ -312,8 +310,9 @@ Being::takeDamage(int amount)
}
else
{
- // hit particle effect
- controlParticle(particleEngine->addEffect("graphics/particles/hit.particle.xml", 0, 0));
+ // Hit particle effect
+ controlParticle(particleEngine->addEffect(
+ "graphics/particles/hit.particle.xml", 0, 0));
if (getType() == MONSTER)
{
@@ -325,7 +324,7 @@ Being::takeDamage(int amount)
}
}
- // show damage number
+ // Show damage number
particleEngine->addTextSplashEffect(damage, 255, 255, 255, font,
mPx + 16, mPy + 16);
}
@@ -340,7 +339,7 @@ void
Being::setMap(Map *map)
{
// Remove sprite from potential previous map
- if (mMap != NULL)
+ if (mMap)
{
mMap->removeSprite(mSpriteIterator);
}
@@ -348,12 +347,12 @@ Being::setMap(Map *map)
mMap = map;
// Add sprite to potential new map
- if (mMap != NULL)
+ if (mMap)
{
mSpriteIterator = mMap->addSprite(this);
}
- //clear particle effect list because child particles became invalid
+ // Clear particle effect list because child particles became invalid
mChildParticleEffects.clear();
}
@@ -362,7 +361,8 @@ Being::controlParticle(Particle *particle)
{
if (particle)
{
- particle->disableAutoDelete(); //the effect may not die without the beings permission or we segvault
+ // The effect may not die without the beings permission or we segfault
+ particle->disableAutoDelete();
mChildParticleEffects.push_back(particle);
}
}
@@ -380,20 +380,12 @@ Being::setAction(Action action)
currentAction = ACTION_SIT;
break;
case ATTACK:
- switch (getWeapon())
+ if (mEquippedWeapon)
{
- case 3:
- currentAction = ACTION_ATTACK;
- break;
- case 2:
- currentAction = ACTION_ATTACK_BOW;
- break;
- case 1:
- currentAction = ACTION_ATTACK_STAB;
- break;
- case 0:
- currentAction = ACTION_ATTACK;
- break;
+ currentAction = mEquippedWeapon->getAttackType();
+ }
+ else {
+ currentAction = ACTION_ATTACK;
}
for (int i = 0; i < VECTOREND_SPRITE; i++)
{
@@ -533,11 +525,9 @@ Being::logic()
}
}
- //Update particle effects
- for ( std::list<Particle *>::iterator i = mChildParticleEffects.begin();
- i != mChildParticleEffects.end();
-
- )
+ // Update particle effects
+ for (std::list<Particle *>::iterator i = mChildParticleEffects.begin();
+ i != mChildParticleEffects.end();)
{
(*i)->setPosition((float)mPx + 16.0f, (float)mPy + 32.0f);
if (!(*i)->isAlive())
@@ -599,46 +589,6 @@ Being::getType() const
return UNKNOWN;
}
-void
-Being::setWeaponById(Uint16 weapon)
-{
- //TODO: Use an external file to map weapon IDs to weapon types
- switch (weapon)
- {
- case 529: // iron arrows
- case 1199: // arrows
- break;
-
- case 623: //scythe
- setWeapon(3);
- break;
-
- case 1200: // bow
- case 530: // short bow
- case 545: // forest bow
- setWeapon(2);
- break;
-
- case 521: // sharp knife
- /* UNCOMMENT TO TEST SHARP KNIFE AS SCYTHE
- * setWeapon(3)
- * break;
- */
- case 522: // dagger
- case 536: // short sword
- case 1201: // knife
- setWeapon(1);
- break;
-
- case 0: // unequip
- setWeapon(0);
- break;
-
- default:
- logger->log("Not a weapon: %d", weapon);
- }
-}
-
int Being::getOffset(int step) const
{
// Check whether we're walking in the requested direction
diff --git a/src/being.h b/src/being.h
index afb3cb8b..fadf9656 100644
--- a/src/being.h
+++ b/src/being.h
@@ -38,6 +38,7 @@
class AnimatedSprite;
class Equipment;
+class ItemInfo;
class Item;
class Map;
class Graphics;
@@ -161,8 +162,7 @@ class Being : public Sprite
void setSpeech(const std::string &text, Uint32 time);
/**
- * Puts a damage bubble above this being for the specified amount of
- * time.
+ * Puts a damage bubble above this being.
*
* @param amount The amount of damage.
*/
@@ -267,27 +267,6 @@ class Being : public Sprite
virtual Type getType() const;
/**
- * Gets the weapon picture id.
- */
- Uint16 getWeapon() const { return mWeapon; }
-
- /**
- * Sets the weapon picture id.
- *
- * @param weapon the picture id
- */
- virtual void
- setWeapon(Uint16 weapon) { mWeapon = weapon; }
-
- /**
- * Sets the weapon picture id with the weapon id.
- *
- * @param weapon the weapon id
- */
- void
- setWeaponById(Uint16 weapon);
-
- /**
* Gets the walk speed.
*/
Uint16
@@ -380,30 +359,26 @@ class Being : public Sprite
getHeight() const;
/**
- * Returns the required size of a target cursor for this being
+ * Returns the required size of a target cursor for this being.
*/
- virtual Being::TargetCursorSize
- getTargetCursorSize() const
+ virtual Being::TargetCursorSize getTargetCursorSize() const
{ return TC_MEDIUM; }
std::auto_ptr<Equipment> mEquipment;
/**
- * Take control of a particle
+ * Take control of a particle.
*/
- void
- controlParticle(Particle *particle);
+ void controlParticle(Particle *particle);
protected:
/**
* Sets the new path for this being.
*/
- void
- setPath(const Path &path, int mod = 1024);
+ void setPath(const Path &path, int mod = 1024);
Uint16 mId; /**< Unique being id */
Uint8 mSex; /**< Character's gender */
- Uint16 mWeapon; /**< Weapon picture id */
Uint16 mWalkSpeed; /**< Walking speed */
Uint16 mSpeedModifier; /**< Modifier to keep course on sync (1024 = normal speed) */
Uint8 mSpriteDirection; /**< Facing direction */
@@ -411,6 +386,9 @@ class Being : public Sprite
Map *mMap; /**< Map on which this being resides */
SpriteIterator mSpriteIterator;
+ /** Engine-related infos about weapon. */
+ const ItemInfo* mEquippedWeapon;
+
Path mPath;
std::string mSpeech;
Uint16 mHairStyle, mHairColor;
diff --git a/src/game.cpp b/src/game.cpp
index 495f9a8d..a40bfa28 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -37,7 +37,9 @@
#include "engine.h"
#include "flooritemmanager.h"
#include "graphics.h"
+#include "itemshortcut.h"
#include "joystick.h"
+#include "keyboardconfig.h"
#include "localplayer.h"
#include "log.h"
#include "npc.h"
@@ -53,6 +55,7 @@
#include "gui/gui.h"
#include "gui/help.h"
#include "gui/inventorywindow.h"
+#include "gui/itemshortcutwindow.h"
#include "gui/menuwindow.h"
#include "gui/minimap.h"
#include "gui/ministatus.h"
@@ -116,6 +119,7 @@ TradeWindow *tradeWindow;
//BuddyWindow *buddyWindow;
HelpWindow *helpWindow;
DebugWindow *debugWindow;
+ItemShortcutWindow *itemShortcutWindow;
BeingManager *beingManager = NULL;
FloorItemManager *floorItemManager = NULL;
@@ -181,6 +185,7 @@ void createGuiWindows()
//buddyWindow = new BuddyWindow();
helpWindow = new HelpWindow();
debugWindow = new DebugWindow();
+ itemShortcutWindow = new ItemShortcutWindow();
// Initialize window positions
//chargeDialog->setPosition(
@@ -193,6 +198,7 @@ void createGuiWindows()
chatWindow->setVisible(true);
miniStatusWindow->setVisible(true);
menuWindow->setVisible(true);
+ itemShortcutWindow->setVisible(true);
}
/**
@@ -220,6 +226,7 @@ void destroyGuiWindows()
//delete buddyWindow;
delete helpWindow;
delete debugWindow;
+ delete itemShortcutWindow;
}
Game::Game():
@@ -420,6 +427,14 @@ void Game::handleInput()
{
gcn::Window *requestedWindow = NULL;
+ if (setupWindow->isVisible() &&
+ keyboard.getNewKeyIndex() > keyboard.KEY_NO_VALUE)
+ {
+ keyboard.setNewKey((int) event.key.keysym.sym);
+ keyboard.callbackNewKey();
+ keyboard.setNewKeyIndex(keyboard.KEY_NO_VALUE);
+ return;
+ }
switch (event.key.keysym.sym)
{
case SDLK_F1:
@@ -473,65 +488,7 @@ void Game::handleInput()
used = true;
}
break;
-
- // Hide certain windows
- case SDLK_h:
- if (!chatWindow->isFocused())
- {
- statusWindow->setVisible(false);
- inventoryWindow->setVisible(false);
- skillDialog->setVisible(false);
- setupWindow->setVisible(false);
- equipmentWindow->setVisible(false);
- helpWindow->setVisible(false);
- debugWindow->setVisible(false);
- }
- break;
-
- // Picking up items on the floor
- case SDLK_g:
- case SDLK_z:
- if (!chatWindow->isFocused())
- {
- Uint16 x = player_node->mX / 32, y = player_node->mY / 32;
- FloorItem *item = floorItemManager->findByCoordinates(x, y);
-
- // If none below the player, try the tile in front of
- // the player
- if (!item)
- {
- // Temporary until tile-based picking is removed.
- switch (player_node->getSpriteDirection())
- {
- case DIRECTION_UP : --y; break;
- case DIRECTION_DOWN : ++y; break;
- case DIRECTION_LEFT : --x; break;
- case DIRECTION_RIGHT: ++x; break;
- default: break;
- }
-
- item = floorItemManager->findByCoordinates(x, y);
- }
-
- if (item)
- player_node->pickUp(item);
-
- used = true;
- }
- break;
-
- // attacking
- // TODO: Reimplement attacking with joystick buttons
- // (old code allowed permanent attacking and not 1 attack
- // with each button push)
- // I would like to do this but i don't own a joystick.
- case SDLK_LCTRL:
- case SDLK_RCTRL:
- player_node->attack();
- used = true;
- break;
-
- // Quitting confirmation dialog
+ // Quitting confirmation dialog
case SDLK_ESCAPE:
if (!quitDialog)
{
@@ -547,6 +504,74 @@ void Game::handleInput()
break;
}
+ if (keyboard.isEnabled() && !chatWindow->isFocused())
+ {
+ const int tKey = keyboard.getKeyIndex(event.key.keysym.sym);
+ // Checks if any item shortcut is pressed.
+ for (int i = KeyboardConfig::KEY_SHORTCUT_0;
+ i <= KeyboardConfig::KEY_SHORTCUT_9;
+ i++)
+ {
+ if (tKey == i) {
+ itemShortcut->useItem(
+ i - KeyboardConfig::KEY_SHORTCUT_0);
+ break;
+ }
+ }
+ switch (tKey) {
+ case KeyboardConfig::KEY_PICKUP:
+ {
+ Uint16 x = player_node->mX / 32;
+ Uint16 y = player_node->mY / 32;
+ FloorItem *item =
+ floorItemManager->findByCoordinates(x, y);
+
+ // If none below the player, try the tile in front
+ // of the player
+ if (!item)
+ {
+ // Temporary until tile-based picking is
+ // removed.
+ switch (player_node->getSpriteDirection())
+ {
+ case DIRECTION_UP : --y; break;
+ case DIRECTION_DOWN : ++y; break;
+ case DIRECTION_LEFT : --x; break;
+ case DIRECTION_RIGHT: ++x; break;
+ default: break;
+ }
+
+ item =
+ floorItemManager->findByCoordinates(x, y);
+ }
+
+ if (item)
+ player_node->pickUp(item);
+
+ used = true;
+ }
+ break;
+ case KeyboardConfig::KEY_SIT:
+ // Player sit action
+ player_node->toggleSit();
+ used = true;
+ break;
+ case KeyboardConfig::KEY_HIDE_WINDOWS:
+ // Hide certain windows
+ if (!chatWindow->isFocused())
+ {
+ statusWindow->setVisible(false);
+ inventoryWindow->setVisible(false);
+ skillDialog->setVisible(false);
+ setupWindow->setVisible(false);
+ equipmentWindow->setVisible(false);
+ helpWindow->setVisible(false);
+ debugWindow->setVisible(false);
+ }
+ break;
+ }
+ }
+
if (requestedWindow)
{
requestedWindow->setVisible(!requestedWindow->isVisible());
@@ -563,19 +588,14 @@ void Game::handleInput()
{
switch (event.key.keysym.sym)
{
- case SDLK_s:
- // Player sit action
- player_node->toggleSit();
- used = true;
- break;
-
case SDLK_p:
// Screenshot (picture, hence the p)
{
SDL_Surface *screenshot = graphics->getScreenshot();
if (!saveScreenshot(screenshot))
{
- logger->log("Error: could not save Screenshot.");
+ logger->log(
+ "Error: could not save Screenshot.");
}
SDL_FreeSurface(screenshot);
}
@@ -606,6 +626,8 @@ void Game::handleInput()
case SDLK_8: emotion = 8; break;
case SDLK_9: emotion = 9; break;
case SDLK_0: emotion = 10; break;
+ case SDLK_MINUS: emotion = 11; break;
+ case SDLK_EQUALS: emotion = 12; break;
default: emotion = 0; break;
}
@@ -638,41 +660,41 @@ void Game::handleInput()
}
} // End while
-
+ // If the user is configuring the keys then don't respond.
+ if (!keyboard.isEnabled())
+ {
+ return;
+ }
// Moving player around
if (player_node->mAction != Being::DEAD &&
current_npc == 0 &&
!chatWindow->isFocused())
{
// Get the state of the keyboard keys
- Uint8* keys;
- keys = SDL_GetKeyState(NULL);
+ keyboard.refreshActiveKeys();
Uint16 x = player_node->mX / 32, y = player_node->mY / 32;
unsigned char direction = 0;
// Translate pressed keys to movement and direction
- if (keys[SDLK_UP] || keys[SDLK_KP8] ||
- keys[SDLK_KP7] || keys[SDLK_KP9] ||
+ if ( keyboard.isKeyActive(keyboard.KEY_MOVE_UP) ||
joystick && joystick->isUp())
{
direction |= Being::UP;
}
- else if (keys[SDLK_DOWN] || keys[SDLK_KP2] ||
- keys[SDLK_KP1] || keys[SDLK_KP3] ||
+ else if ( keyboard.isKeyActive(keyboard.KEY_MOVE_DOWN) ||
joystick && joystick->isDown())
{
direction |= Being::DOWN;
}
- if (keys[SDLK_LEFT] || keys[SDLK_KP4] ||
- keys[SDLK_KP1] || keys[SDLK_KP7] ||
+
+ if ( keyboard.isKeyActive(keyboard.KEY_MOVE_LEFT) ||
joystick && joystick->isLeft())
{
direction |= Being::LEFT;
}
- else if (keys[SDLK_RIGHT] || keys[SDLK_KP6] ||
- keys[SDLK_KP3] || keys[SDLK_KP9] ||
+ else if ( keyboard.isKeyActive(keyboard.KEY_MOVE_RIGHT) ||
joystick && joystick->isRight())
{
direction |= Being::RIGHT;
@@ -681,7 +703,8 @@ void Game::handleInput()
player_node->setWalkingDir(direction);
// Target the nearest monster if 'a' pressed
- if (keys[SDLK_a])
+ if ( keyboard.isKeyActive(keyboard.KEY_TARGET_CLOSEST) )
+ //if (keys[SDLK_a])
{
Being *target =
beingManager->findNearestLivingBeing(x, y, 20, Being::MONSTER);
diff --git a/src/gui/button.cpp b/src/gui/button.cpp
index 4e236c33..0379ebc0 100644
--- a/src/gui/button.cpp
+++ b/src/gui/button.cpp
@@ -60,11 +60,26 @@ static ButtonData const data[BUTTON_COUNT] = {
ImageRect Button::button[BUTTON_COUNT];
+Button::Button():
+ mIsLogged(false)
+{
+ init();
+}
+
Button::Button(const std::string& caption, const std::string &actionEventId,
gcn::ActionListener *listener):
gcn::Button(caption),
mIsLogged(false)
{
+ init();
+ setActionEventId(actionEventId);
+ if (listener) {
+ addActionListener(listener);
+ }
+}
+
+void Button::init()
+{
setBorderSize(0);
if (mInstances == 0)
@@ -91,12 +106,7 @@ Button::Button(const std::string& caption, const std::string &actionEventId,
btn[mode]->decRef();
}
}
-
mInstances++;
- setActionEventId(actionEventId);
- if (listener) {
- addActionListener(listener);
- }
}
Button::~Button()
diff --git a/src/gui/button.h b/src/gui/button.h
index eb73e311..d12173b2 100644
--- a/src/gui/button.h
+++ b/src/gui/button.h
@@ -38,7 +38,13 @@ class ImageRect;
class Button : public gcn::Button {
public:
/**
- * Constructor, sets the caption of the button to the given string.
+ * Default constructor.
+ */
+ Button();
+
+ /**
+ * 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 &actionEventId,
gcn::ActionListener *listener);
@@ -60,6 +66,8 @@ class Button : public gcn::Button {
{ mIsLogged = enable; }
private:
+ void init();
+
static ImageRect button[4]; /**< Button state graphics */
static int mInstances; /**< Number of button instances */
bool mIsLogged; /**< Makes the button appear pressed all the time */
diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp
index 6cfe5e18..bbf2102e 100644
--- a/src/gui/buy.cpp
+++ b/src/gui/buy.cpp
@@ -28,6 +28,7 @@
#include "button.h"
#include "scrollarea.h"
#include "shop.h"
+#include "shoplistbox.h"
#include "slider.h"
#include "../npc.h"
@@ -35,11 +36,15 @@
#include "../resources/itemdb.h"
#include "../utils/tostring.h"
-
BuyDialog::BuyDialog():
Window("Buy"),
mMoney(0), mAmountItems(0), mMaxItems(0)
{
+ setResizable(true);
+ setMinWidth(260);
+ setMinHeight(230);
+ setDefaultSize(0, 0, 260, 230);
+
mShopItems = new ShopItems;
mShopItemList = new ShopListBox(mShopItems, mShopItems);
@@ -54,32 +59,15 @@ BuyDialog::BuyDialog():
mItemDescLabel = new gcn::Label("Description:");
mItemEffectLabel = new gcn::Label("Effect:");
- setContentSize(260, 210);
- mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
- mScrollArea->setDimension(gcn::Rectangle(5, 5, 250, 110));
- mShopItemList->setDimension(gcn::Rectangle(5, 5, 238, 110));
-
- mSlider->setDimension(gcn::Rectangle(5, 120, 200, 10));
- mSlider->setEnabled(false);
-
- mQuantityLabel->setPosition(215, 120);
- mMoneyLabel->setPosition(5, 130);
-
- mIncreaseButton->setPosition(40, 186);
mIncreaseButton->setSize(20, 20);
- mIncreaseButton->setEnabled(false);
-
- mDecreaseButton->setPosition(10, 186);
mDecreaseButton->setSize(20, 20);
- mDecreaseButton->setEnabled(false);
+ mQuantityLabel->setWidth(60);
- mBuyButton->setPosition(180, 186);
+ mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mIncreaseButton->setEnabled(false);
+ mDecreaseButton->setEnabled(false);
mBuyButton->setEnabled(false);
-
- mQuitButton->setPosition(212, 186);
-
- mItemEffectLabel->setDimension(gcn::Rectangle(5, 150, 240, 14));
- mItemDescLabel->setDimension(gcn::Rectangle(5, 169, 240, 14));
+ mSlider->setEnabled(false);
mShopItemList->setActionEventId("item");
mSlider->setActionEventId("slider");
@@ -98,6 +86,8 @@ BuyDialog::BuyDialog():
add(mItemDescLabel);
add(mItemEffectLabel);
+ addWindowListener(this);
+ loadWindowState("Buy");
setLocationRelativeTo(getParent());
}
@@ -118,13 +108,12 @@ void BuyDialog::reset()
{
mShopItems->clear();
mShopItemList->adjustSize();
- mMoney = 0;
- mSlider->setValue(0.0);
- // Reset Previous Selected Items to prevent failing asserts
+ // Reset previous selected items to prevent failing asserts
mShopItemList->setSelected(-1);
+ mSlider->setValue(0);
- updateButtonsAndLabels();
+ setMoney(0);
}
void BuyDialog::addItem(int id, int amount, int price)
@@ -141,6 +130,7 @@ void BuyDialog::action(const gcn::ActionEvent &event)
{
setVisible(false);
current_npc = 0;
+ return;
}
// The following actions require a valid selection
@@ -152,21 +142,19 @@ void BuyDialog::action(const gcn::ActionEvent &event)
if (event.getId() == "slider")
{
- mAmountItems = (int)(mSlider->getValue() * mMaxItems);
+ mAmountItems = (int) mSlider->getValue();
updateButtonsAndLabels();
}
else if (event.getId() == "+" && mAmountItems < mMaxItems)
{
mAmountItems++;
-
- mSlider->setValue((double) mAmountItems / (double) mMaxItems);
+ mSlider->setValue(mAmountItems);
updateButtonsAndLabels();
}
- else if (event.getId() == "-" && mAmountItems > 0)
+ else if (event.getId() == "-" && mAmountItems > 1)
{
mAmountItems--;
-
- mSlider->setValue((double) mAmountItems / (double) mMaxItems);
+ mSlider->setValue(mAmountItems);
updateButtonsAndLabels();
}
// TODO: Actually we'd have a bug elsewhere if this check for the number
@@ -178,25 +166,69 @@ void BuyDialog::action(const gcn::ActionEvent &event)
Net::GameServer::Player::tradeWithNPC
(mShopItems->at(selectedItem).id, mAmountItems);
- // Update money and adjust the max number of items that can be bought
- mMoney -= mAmountItems * mShopItems->at(selectedItem).price;
- mMaxItems -= mAmountItems;
-
// Reset selection
- mAmountItems = 0;
- mSlider->setValue(0.0);
+ mAmountItems = 1;
+ mSlider->setValue(1);
+ mSlider->gcn::Slider::setScale(1, mMaxItems);
- updateButtonsAndLabels();
+ // Update money and adjust the max number of items that can be bought
+ mMaxItems -= mAmountItems;
+ setMoney(mMoney - mAmountItems * mShopItems->at(selectedItem).price);
}
}
void BuyDialog::selectionChanged(const SelectionEvent &event)
{
+
// Reset amount of items and update labels
- mAmountItems = 0;
- mSlider->setValue(0.0);
+ mAmountItems = 1;
+ mSlider->setValue(1);
updateButtonsAndLabels();
+ mSlider->gcn::Slider::setScale(1, mMaxItems);
+}
+
+void BuyDialog::windowResized(const WindowEvent &event)
+{
+ gcn::Rectangle area = getChildrenArea();
+ int width = area.width;
+ int height = area.height;
+
+ mDecreaseButton->setPosition(8, height - 8 - mDecreaseButton->getHeight());
+ mIncreaseButton->setPosition(
+ mDecreaseButton->getX() + mDecreaseButton->getWidth() + 5,
+ mDecreaseButton->getY());
+
+ mQuitButton->setPosition(
+ width - 8 - mQuitButton->getWidth(),
+ height - 8 - mQuitButton->getHeight());
+ mBuyButton->setPosition(
+ mQuitButton->getX() - 5 - mBuyButton->getWidth(),
+ mQuitButton->getY());
+
+ mItemDescLabel->setDimension(gcn::Rectangle(8,
+ mBuyButton->getY() - 5 - mItemDescLabel->getHeight(),
+ width - 16,
+ mItemDescLabel->getHeight()));
+ mItemEffectLabel->setDimension(gcn::Rectangle(8,
+ mItemDescLabel->getY() - 5 - mItemEffectLabel->getHeight(),
+ width - 16,
+ mItemEffectLabel->getHeight()));
+ mMoneyLabel->setDimension(gcn::Rectangle(8,
+ mItemEffectLabel->getY() - 5 - mMoneyLabel->getHeight(),
+ width - 16,
+ mMoneyLabel->getHeight()));
+
+ mQuantityLabel->setPosition(
+ width - mQuantityLabel->getWidth() - 8,
+ mMoneyLabel->getY() - 5 - mQuantityLabel->getHeight());
+ mSlider->setDimension(gcn::Rectangle(8,
+ mQuantityLabel->getY(),
+ mQuantityLabel->getX() - 8 - 8,
+ 10));
+
+ mScrollArea->setDimension(gcn::Rectangle(8, 8, width - 16,
+ mSlider->getY() - 5 - 8));
}
void
@@ -232,14 +264,13 @@ BuyDialog::updateButtonsAndLabels()
// Enable or disable buttons and slider
mIncreaseButton->setEnabled(mAmountItems < mMaxItems);
- mDecreaseButton->setEnabled(mAmountItems > 0);
+ mDecreaseButton->setEnabled(mAmountItems > 1);
mBuyButton->setEnabled(mAmountItems > 0);
- mSlider->setEnabled(mMaxItems > 0);
+ mSlider->setEnabled(mMaxItems > 1);
// Update quantity and money labels
- mQuantityLabel->setCaption(toString(mAmountItems));
- mQuantityLabel->adjustSize();
+ mQuantityLabel->setCaption(
+ toString(mAmountItems) + " / " + toString(mMaxItems));
mMoneyLabel->setCaption("Price: " + toString(price) + " GP / "
+ toString(mMoney - price) + " GP" );
- mMoneyLabel->adjustSize();
}
diff --git a/src/gui/buy.h b/src/gui/buy.h
index 875deef9..63d25583 100644
--- a/src/gui/buy.h
+++ b/src/gui/buy.h
@@ -28,11 +28,11 @@
#include "window.h"
#include "selectionlistener.h"
-#include "shoplistbox.h"
#include "../guichanfwd.h"
class ShopItems;
+class ShopListBox;
class ListBox;
/**
@@ -40,7 +40,8 @@ class ListBox;
*
* \ingroup Interface
*/
-class BuyDialog : public Window, public gcn::ActionListener, SelectionListener
+class BuyDialog : public Window, public gcn::ActionListener, SelectionListener,
+ WindowListener
{
public:
/**
@@ -98,6 +99,11 @@ class BuyDialog : public Window, public gcn::ActionListener, SelectionListener
void
updateButtonsAndLabels();
+ /**
+ * Called whenever the window is resized.
+ */
+ void windowResized(const WindowEvent &event);
+
private:
gcn::Button *mBuyButton;
gcn::Button *mQuitButton;
diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp
index d752cdb3..e8381bef 100644
--- a/src/gui/char_select.cpp
+++ b/src/gui/char_select.cpp
@@ -48,6 +48,7 @@
#include "../utils/gettext.h"
#include "../utils/strprintf.h"
#include "../utils/tostring.h"
+#include "../utils/trim.h"
// Defined in main.cpp, used here for setting the char create dialog
extern CharServerHandler charServerHandler;
@@ -255,11 +256,6 @@ bool CharSelectDialog::selectByName(const std::string &name)
return false;
}
-std::string CharSelectDialog::getName()
-{
- return mNameLabel->getCaption();
-}
-
CharCreateDialog::CharCreateDialog(Window *parent, int slot):
Window(_("Create Character"), true, parent), mSlot(slot)
{
@@ -410,10 +406,12 @@ CharCreateDialog::action(const gcn::ActionEvent &event)
}
}
-const std::string&
+std::string
CharCreateDialog::getName()
{
- return mNameField->getText();
+ std::string name = mNameField->getText();
+ trim(name);
+ return name;
}
void CharCreateDialog::UpdateSliders()
diff --git a/src/gui/char_select.h b/src/gui/char_select.h
index 9d9184ea..5d0b42fa 100644
--- a/src/gui/char_select.h
+++ b/src/gui/char_select.h
@@ -60,11 +60,6 @@ class CharSelectDialog : public Window, public gcn::ActionListener
bool selectByName(const std::string &name);
- /**
- * Returns name of selected player
- */
- std::string getName();
-
private:
LockedArray<LocalPlayer*> *mCharInfo;
@@ -114,22 +109,28 @@ class CharCreateDialog : public Window, public gcn::ActionListener
*/
~CharCreateDialog();
- void
- action(const gcn::ActionEvent &event);
-
- const std::string&
- getName();
+ void action(const gcn::ActionEvent &event);
/**
* Unlocks the dialog, enabling the create character button again.
*/
- void
- unlock();
+ void unlock();
private:
int getDistributedPoints();
+
void UpdateSliders();
+ /**
+ * Returns the name of the character to create.
+ */
+ std::string getName();
+
+ /**
+ * Communicate character creation to the server.
+ */
+ void attemptCharCreate();
+
gcn::TextField *mNameField;
gcn::Label *mNameLabel;
gcn::Button *mNextHairColorButton;
@@ -154,12 +155,6 @@ class CharCreateDialog : public Window, public gcn::ActionListener
static const int mMaxPoints = 70;
int mUsedPoints;
-
-
- /**
- * Communicate character creation to the server.
- */
- void attemptCharCreate();
};
#endif
diff --git a/src/gui/chat.cpp b/src/gui/chat.cpp
index ba7c7f02..4ed8bb97 100644
--- a/src/gui/chat.cpp
+++ b/src/gui/chat.cpp
@@ -44,6 +44,7 @@
#include "../net/gameserver/player.h"
#include "../utils/dtor.h"
+#include "../utils/trim.h"
ChatWindow::ChatWindow():
Window(),
@@ -125,7 +126,7 @@ void
ChatWindow::chatLog(std::string line, int own, std::string channelName)
{
// Delete overhead from the end of the list
- while ((int)mChatlog.size() > mItemsKeep) {
+ while ((int) mChatlog.size() > mItemsKeep) {
mChatlog.pop_back();
}
@@ -142,12 +143,15 @@ ChatWindow::chatLog(std::string line, int own, std::string channelName)
own = BY_SERVER;
}
- int pos = line.find(" : ");
- if (pos > 0) {
+ std::string::size_type pos = line.find(" : ");
+ if (pos != std::string::npos) {
tmp.nick = line.substr(0, pos);
line.erase(0, pos + 3);
}
+ // Trim whitespace
+ trim(line);
+
std::string lineColor = "##0"; // Equiv. to BrowserBox::BLACK
switch (own) {
case BY_GM:
diff --git a/src/gui/debugwindow.cpp b/src/gui/debugwindow.cpp
index 11ad37c2..884cdf7e 100644
--- a/src/gui/debugwindow.cpp
+++ b/src/gui/debugwindow.cpp
@@ -42,6 +42,7 @@ DebugWindow::DebugWindow():
Window("Debug")
{
setResizable(true);
+ setCloseButton(true);
setDefaultSize(0, 0, 400, 100);
loadWindowState("Debug");
@@ -60,15 +61,11 @@ DebugWindow::DebugWindow():
mParticleCountLabel = new gcn::Label("[Particle count: 0]");
mParticleCountLabel->setPosition(100, 60);
- Button *closeButton = new Button("Close", "close", this);
- closeButton->setPosition(5, 60);
-
add(mFPSLabel);
add(mMusicFileLabel);
add(mMapFileLabel);
add(mTileMouseLabel);
add(mParticleCountLabel);
- add(closeButton);
}
void
@@ -106,12 +103,3 @@ DebugWindow::logic()
+"]");
mParticleCountLabel->adjustSize();
}
-
-void
-DebugWindow::action(const gcn::ActionEvent &event)
-{
- if (event.getId() == "close")
- {
- setVisible(false);
- }
-}
diff --git a/src/gui/debugwindow.h b/src/gui/debugwindow.h
index d082b2ca..9b6f2017 100644
--- a/src/gui/debugwindow.h
+++ b/src/gui/debugwindow.h
@@ -33,11 +33,11 @@
#include "../guichanfwd.h"
/**
- * The chat window.
+ * The debug window.
*
* \ingroup Interface
*/
-class DebugWindow : public Window, public gcn::ActionListener
+class DebugWindow : public Window
{
public:
/**
@@ -50,11 +50,6 @@ class DebugWindow : public Window, public gcn::ActionListener
*/
void logic();
- /**
- * Performs action.
- */
- void action(const gcn::ActionEvent &event);
-
private:
gcn::Label *mMusicFileLabel, *mMapFileLabel;
gcn::Label *mTileMouseLabel, *mFPSLabel;
diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp
index 5e835985..c86a27fc 100644
--- a/src/gui/equipmentwindow.cpp
+++ b/src/gui/equipmentwindow.cpp
@@ -59,6 +59,7 @@ EquipmentWindow::EquipmentWindow(Equipment *equipment):
mBackground(NULL),
mSelected(-1)
{
+ setCloseButton(true);
setDefaultSize(5, 195, 216, 260);
loadWindowState("Equipment");
diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp
index dc51054c..97dd4d44 100644
--- a/src/gui/gui.cpp
+++ b/src/gui/gui.cpp
@@ -42,7 +42,7 @@
#include "../graphics.h"
#include "../log.h"
-#include "../resources/image.h"
+#include "../resources/imageset.h"
#include "../resources/resourcemanager.h"
#include "../resources/imageloader.h"
@@ -77,8 +77,9 @@ class GuiConfigListener : public ConfigListener
};
Gui::Gui(Graphics *graphics):
- mMouseCursor(NULL),
- mCustomCursor(false)
+ mCustomCursor(false),
+ mMouseCursors(NULL),
+ mCursorType(CURSOR_POINTER)
{
logger->log("Initializing GUI...");
// Set graphics
@@ -106,7 +107,7 @@ Gui::Gui(Graphics *graphics):
// Set global font
try {
- mGuiFont = new TrueTypeFont("data/fonts/dejavusans.ttf", 12);
+ mGuiFont = new TrueTypeFont("data/fonts/dejavusans.ttf", 11);
}
catch (gcn::Exception e)
{
@@ -139,7 +140,7 @@ Gui::Gui(Graphics *graphics):
hitBlueFont = new gcn::ImageFont("graphics/gui/hits_blue.png",
"0123456789");
hitYellowFont = new gcn::ImageFont("graphics/gui/hits_yellow.png",
- "mis");
+ "0123456789misxp ");
}
catch (gcn::Exception e)
{
@@ -169,8 +170,8 @@ Gui::~Gui()
delete hitBlueFont;
delete hitYellowFont;
- if (mMouseCursor) {
- mMouseCursor->decRef();
+ if (mMouseCursors) {
+ mMouseCursors->decRef();
}
delete mGuiFont;
@@ -182,12 +183,6 @@ Gui::~Gui()
}
void
-Gui::logic()
-{
- gcn::Gui::logic();
-}
-
-void
Gui::draw()
{
mGraphics->pushClipArea(mTop->getDimension());
@@ -196,11 +191,13 @@ Gui::draw()
int mouseX, mouseY;
Uint8 button = SDL_GetMouseState(&mouseX, &mouseY);
- if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS || button & SDL_BUTTON(1))
- && mCustomCursor)
+ if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS || button & SDL_BUTTON(1)) &&
+ mCustomCursor)
{
- static_cast<Graphics*>(mGraphics)->
- drawImage(mMouseCursor, mouseX - 5, mouseY - 2);
+ static_cast<Graphics*>(mGraphics)->drawImage(
+ mMouseCursors->get(mCursorType),
+ mouseX - 15,
+ mouseY - 17);
}
mGraphics->popClipArea();
@@ -220,9 +217,11 @@ Gui::setUseCustomCursor(bool customCursor)
// Load the mouse cursor
ResourceManager *resman = ResourceManager::getInstance();
- mMouseCursor = resman->getImage("graphics/gui/mouse.png");
- if (!mMouseCursor) {
- logger->error("Unable to load mouse cursor.");
+ mMouseCursors =
+ resman->getImageSet("graphics/gui/mouse.png", 40, 40);
+
+ if (!mMouseCursors) {
+ logger->error("Unable to load mouse cursors.");
}
}
else
@@ -231,9 +230,9 @@ Gui::setUseCustomCursor(bool customCursor)
SDL_ShowCursor(SDL_ENABLE);
// Unload the mouse cursor
- if (mMouseCursor) {
- mMouseCursor->decRef();
- mMouseCursor = NULL;
+ if (mMouseCursors) {
+ mMouseCursors->decRef();
+ mMouseCursors = NULL;
}
}
}
diff --git a/src/gui/gui.h b/src/gui/gui.h
index 5f2cc810..1e4b9348 100644
--- a/src/gui/gui.h
+++ b/src/gui/gui.h
@@ -30,7 +30,7 @@
class GuiConfigListener;
class Graphics;
-class Image;
+class ImageSet;
class Viewport;
/**
@@ -60,35 +60,48 @@ class Gui : public gcn::Gui
~Gui();
/**
- * Works around Guichan bug
- */
- void
- logic();
-
- /**
* Draws the whole Gui by calling draw functions down in the
* Gui hierarchy. It also draws the mouse pointer.
*/
- void
- draw();
+ void draw();
/**
- * Return game font
+ * Return game font.
*/
- gcn::Font*
- getFont() { return mGuiFont; }
+ gcn::Font* getFont() const
+ { return mGuiFont; }
/**
* Sets whether a custom cursor should be rendered.
*/
- void
- setUseCustomCursor(bool customCursor);
+ void setUseCustomCursor(bool customCursor);
+
+ /**
+ * Sets which cursor should be used.
+ */
+ void setCursorType(int index)
+ { mCursorType = index; }
+
+ /**
+ * Cursors are in graphic order from left to right.
+ * CURSOR_POINTER should be left untouched.
+ * CURSOR_TOTAL should always be last.
+ */
+ enum {
+ CURSOR_POINTER = 0,
+ CURSOR_RESIZE_ACROSS,
+ CURSOR_RESIZE_DOWN,
+ CURSOR_RESIZE_DOWN_LEFT,
+ CURSOR_RESIZE_DOWN_RIGHT,
+ CURSOR_TOTAL
+ };
private:
GuiConfigListener *mConfigListener;
gcn::Font *mGuiFont; /**< The global GUI font */
- Image *mMouseCursor; /**< Mouse cursor image */
bool mCustomCursor; /**< Show custom cursor */
+ ImageSet *mMouseCursors; /**< Mouse cursor images */
+ int mCursorType;
};
extern Gui *gui; /**< The GUI system */
diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp
index 085ab188..1e62b130 100644
--- a/src/gui/inventorywindow.cpp
+++ b/src/gui/inventorywindow.cpp
@@ -51,6 +51,7 @@ InventoryWindow::InventoryWindow():
mSplit(false)
{
setResizable(true);
+ setCloseButton(true);
setMinWidth(240);
setMinHeight(172);
// If you adjust these defaults, don't forget to adjust the trade window's.
@@ -69,7 +70,6 @@ InventoryWindow::InventoryWindow():
mItems->addSelectionListener(this);
mInvenScroll = new ScrollArea(mItems);
- mInvenScroll->setPosition(8, 8);
mItemNameLabel = new gcn::Label(strprintf(_("Name: %s"), ""));
mItemDescriptionLabel = new gcn::Label(
@@ -100,8 +100,8 @@ InventoryWindow::InventoryWindow():
mSplitButton->setWidth(48);
}
+ addWindowListener(this);
loadWindowState("Inventory");
- updateContentSize();
}
InventoryWindow::~InventoryWindow()
@@ -130,7 +130,6 @@ void InventoryWindow::logic()
mWeightLabel->setCaption(
strprintf(_("Total Weight: %d - Maximum Weight: %d"),
player_node->getTotalWeight(), player_node->getMaxWeight()));
- mWeightLabel->adjustSize();
}
void InventoryWindow::action(const gcn::ActionEvent &event)
@@ -215,7 +214,7 @@ void InventoryWindow::mouseClicked(gcn::MouseEvent &event)
}
}
-void InventoryWindow::updateContentSize()
+void InventoryWindow::windowResized(const WindowEvent &event)
{
const gcn::Rectangle area = getChildrenArea();
@@ -260,8 +259,7 @@ Item* InventoryWindow::getItem()
return mItems->getItem();
}
-void
-InventoryWindow::keyPressed(gcn::KeyEvent &event)
+void InventoryWindow::keyPressed(gcn::KeyEvent &event)
{
switch (event.getKey().getValue())
{
@@ -271,8 +269,7 @@ InventoryWindow::keyPressed(gcn::KeyEvent &event)
}
}
-void
-InventoryWindow::keyReleased(gcn::KeyEvent &event)
+void InventoryWindow::keyReleased(gcn::KeyEvent &event)
{
switch (event.getKey().getValue())
{
diff --git a/src/gui/inventorywindow.h b/src/gui/inventorywindow.h
index 37ef0406..a9fdadf2 100644
--- a/src/gui/inventorywindow.h
+++ b/src/gui/inventorywindow.h
@@ -29,8 +29,9 @@
#include <guichan/widgets/checkbox.hpp>
-#include "window.h"
#include "selectionlistener.h"
+#include "window.h"
+#include "windowlistener.h"
#include "../guichanfwd.h"
@@ -45,7 +46,8 @@ class ItemContainer;
class InventoryWindow : public Window,
public gcn::ActionListener,
public gcn::KeyListener,
- public SelectionListener
+ public SelectionListener,
+ public WindowListener
{
public:
/**
@@ -92,7 +94,10 @@ class InventoryWindow : public Window,
*/
void selectionChanged(const SelectionEvent &event);
- void updateContentSize(); /**< Updates widgets size/position. */
+ /**
+ * Called whenever the window is resized.
+ */
+ void windowResized(const WindowEvent &event);
private:
void updateButtons(); /**< Updates button states. */
diff --git a/src/gui/itemcontainer.cpp b/src/gui/itemcontainer.cpp
index b032bd49..bddf7cee 100644
--- a/src/gui/itemcontainer.cpp
+++ b/src/gui/itemcontainer.cpp
@@ -30,6 +30,7 @@
#include "../graphics.h"
#include "../inventory.h"
#include "../item.h"
+#include "../itemshortcut.h"
#include "../localplayer.h"
#include "../resources/image.h"
@@ -38,6 +39,9 @@
#include "../utils/tostring.h"
+// TODO: Add support for adding items to the item shortcut window (global
+// itemShortcut).
+
static const int BOX_WIDTH = 36;
static const int BOX_HEIGHT = 44;
diff --git a/src/gui/itemshortcutcontainer.cpp b/src/gui/itemshortcutcontainer.cpp
new file mode 100644
index 00000000..1943ef93
--- /dev/null
+++ b/src/gui/itemshortcutcontainer.cpp
@@ -0,0 +1,224 @@
+/*
+ * The Mana World
+ * Copyright 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "itemshortcutcontainer.h"
+
+#include "../graphics.h"
+#include "../item.h"
+#include "../itemshortcut.h"
+#include "../keyboardconfig.h"
+
+#include "../resources/image.h"
+#include "../resources/resourcemanager.h"
+
+#include "../utils/tostring.h"
+
+ItemShortcutContainer::ItemShortcutContainer():
+ mGridWidth(1),
+ mGridHeight(1),
+ mItemClicked(false),
+ mItemMoved(NULL)
+{
+ addMouseListener(this);
+
+ ResourceManager *resman = ResourceManager::getInstance();
+
+ mBackgroundImg = resman->getImage("graphics/gui/item_shortcut_bgr.png");
+ mMaxItems = itemShortcut->getItemCount();
+
+ mBoxHeight = 42;
+ mBoxWidth = 36;
+}
+
+ItemShortcutContainer::~ItemShortcutContainer()
+{
+ mBackgroundImg->decRef();
+}
+
+void
+ItemShortcutContainer::logic()
+{
+ gcn::Widget::logic();
+
+ int i = itemShortcut->getItemCount();
+
+ if (i != mMaxItems)
+ {
+ mMaxItems = i;
+ setWidth(getWidth());
+ }
+}
+
+void
+ItemShortcutContainer::draw(gcn::Graphics *graphics)
+{
+ Graphics *g = static_cast<Graphics*>(graphics);
+
+ for (int i = 0; i < mMaxItems; i++)
+ {
+ const int itemX = (i % mGridWidth) * mBoxWidth;
+ const int itemY = (i / mGridWidth) * mBoxHeight;
+
+ g->drawImage(mBackgroundImg, itemX, itemY);
+
+ // Draw item keyboard shortcut.
+ const char *key = SDL_GetKeyName(
+ (SDLKey) keyboard.getKeyValue(keyboard.KEY_SHORTCUT_0+i));
+ g->drawText(key, itemX + 2, itemY + 2, gcn::Graphics::LEFT);
+
+ Item *item = itemShortcut->getItem(i);
+ if (item) {
+ // Draw item icon.
+ Image* image = item->getInfo().getImage();
+ if (image) {
+ g->drawImage(image, itemX, itemY);
+ g->drawText(
+ toString(item->getQuantity()),
+ itemX + mBoxWidth / 2,
+ itemY + mBoxHeight - 14,
+ gcn::Graphics::CENTER);
+ }
+ }
+ }
+ if (mItemMoved)
+ {
+ // Draw the item image being dragged by the cursor.
+ Image* image = mItemMoved->getInfo().getImage();
+ if (image)
+ {
+ const int tPosX = mCursorPosX - (image->getWidth() / 2);
+ const int tPosY = mCursorPosY - (image->getHeight() / 2);
+
+ g->drawImage(image, tPosX, tPosY);
+ g->drawText(
+ toString(mItemMoved->getQuantity()),
+ tPosX + mBoxWidth / 2,
+ tPosY + mBoxHeight - 14,
+ gcn::Graphics::CENTER);
+ }
+ }
+}
+
+void
+ItemShortcutContainer::setWidth(int width)
+{
+ gcn::Widget::setWidth(width);
+
+ mGridWidth = getWidth() / mBoxWidth;
+ if (mGridWidth < 1) {
+ mGridWidth = 1;
+ }
+
+ setHeight((mMaxItems / mGridWidth +
+ (mMaxItems % mGridWidth > 0 ? 1 : 0)) * mBoxHeight);
+
+ mGridHeight = getHeight() / mBoxHeight;
+ if (mGridHeight < 1) {
+ mGridHeight = 1;
+ }
+}
+
+void
+ItemShortcutContainer::mouseDragged(gcn::MouseEvent &event)
+{
+ if (event.getButton() == gcn::MouseEvent::LEFT) {
+ if (!mItemMoved && mItemClicked) {
+ const int index = getIndexFromGrid(event.getX(), event.getY());
+ if (index == -1) {
+ return;
+ }
+ Item *item = itemShortcut->getItem(index);
+ if (item)
+ {
+ mItemMoved = item;
+ itemShortcut->removeItem(index);
+ }
+ }
+ if (mItemMoved) {
+ mCursorPosX = event.getX();
+ mCursorPosY = event.getY();
+ }
+ }
+}
+
+void
+ItemShortcutContainer::mousePressed(gcn::MouseEvent &event)
+{
+ const int index = getIndexFromGrid(event.getX(), event.getY());
+ if (index == -1) {
+ return;
+ }
+
+ // Stores the selected item if theirs one.
+ if (itemShortcut->isItemSelected()) {
+ itemShortcut->setItem(index);
+ itemShortcut->setItemSelected(NULL);
+ }
+ else if (itemShortcut->getItem(index)) {
+ mItemClicked = true;
+ }
+}
+
+void
+ItemShortcutContainer::mouseReleased(gcn::MouseEvent &event)
+{
+ if (event.getButton() == gcn::MouseEvent::LEFT)
+ {
+ if (itemShortcut->isItemSelected())
+ {
+ itemShortcut->setItemSelected(NULL);
+ }
+ const int index = getIndexFromGrid(event.getX(), event.getY());
+ if (index == -1) {
+ mItemMoved = NULL;
+ return;
+ }
+ if (mItemMoved) {
+ itemShortcut->setItems(index, mItemMoved);
+ mItemMoved = NULL;
+ }
+ else if (itemShortcut->getItem(index) && mItemClicked)
+ {
+ itemShortcut->useItem(index);
+ }
+ if (mItemClicked) {
+ mItemClicked = false;
+ }
+ }
+}
+
+int
+ItemShortcutContainer::getIndexFromGrid(int pointX, int pointY) const
+{
+ const gcn::Rectangle tRect = gcn::Rectangle(
+ 0, 0, mGridWidth * mBoxWidth, mGridHeight * mBoxHeight);
+ if (!tRect.isPointInRect(pointX, pointY)) {
+ return -1;
+ }
+ const int index = ((pointY / mBoxHeight) * mGridWidth) +
+ pointX / mBoxWidth;
+ if (index >= mMaxItems)
+ {
+ return -1;
+ }
+ return index;
+}
diff --git a/src/gui/itemshortcutcontainer.h b/src/gui/itemshortcutcontainer.h
new file mode 100644
index 00000000..4b154cbb
--- /dev/null
+++ b/src/gui/itemshortcutcontainer.h
@@ -0,0 +1,115 @@
+/*
+ * The Mana World
+ * Copyright 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _TMW_ITEMSHORTCUTCONTAINER_H__
+#define _TMW_ITEMSHORTCUTCONTAINER_H__
+
+#include <guichan/mouselistener.hpp>
+#include <guichan/widget.hpp>
+
+#include <list>
+
+class Image;
+class Item;
+
+/**
+ * An item shortcut container. Used to quickly use items.
+ *
+ * \ingroup GUI
+ */
+class ItemShortcutContainer : public gcn::Widget, public gcn::MouseListener
+{
+ public:
+ /**
+ * Constructor. Initializes the graphic.
+ */
+ ItemShortcutContainer();
+
+ /**
+ * Destructor.
+ */
+ virtual ~ItemShortcutContainer();
+
+ /**
+ * Handles the logic of the ItemContainer
+ */
+ void logic();
+
+ /**
+ * Draws the items.
+ */
+ void draw(gcn::Graphics *graphics);
+
+ /**
+ * Sets the width of the container. This is used to determine the new
+ * height of the container.
+ */
+ void setWidth(int width);
+
+ /**
+ * Handles mouse when dragged.
+ */
+ void mouseDragged(gcn::MouseEvent &event);
+
+ /**
+ * Handles mouse when pressed.
+ */
+ void mousePressed(gcn::MouseEvent &event);
+
+ /**
+ * Handles mouse release.
+ */
+ void mouseReleased(gcn::MouseEvent &event);
+
+
+ int getMaxItems()
+ { return mMaxItems; }
+
+ int getBoxWidth()
+ { return mBoxWidth; }
+
+ int getBoxHeight()
+ { return mBoxHeight; }
+
+ private:
+ /**
+ * Gets the index from the grid provided the point is in an item box.
+ *
+ * @param pointX X coordinate of the point.
+ * @param pointY Y coordinate of the point.
+ * @return index on success, -1 on failure.
+ */
+ int getIndexFromGrid(int pointX, int pointY) const;
+
+ Image *mBackgroundImg;
+
+ int mMaxItems;
+ int mBoxWidth;
+ int mBoxHeight;
+ int mCursorPosX, mCursorPosY;
+ int mGridWidth, mGridHeight;
+ bool mItemClicked;
+ Item *mItemMoved;
+
+};
+
+#endif
diff --git a/src/gui/itemshortcutwindow.cpp b/src/gui/itemshortcutwindow.cpp
new file mode 100644
index 00000000..dd97a7db
--- /dev/null
+++ b/src/gui/itemshortcutwindow.cpp
@@ -0,0 +1,74 @@
+/*
+ * The Mana World
+ * Copyright 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "itemshortcutwindow.h"
+
+#include "itemshortcutcontainer.h"
+#include "scrollarea.h"
+
+static const int SCROLL_PADDING = 0;
+
+ItemShortcutWindow::ItemShortcutWindow()
+{
+ // no title presented, title bar is padding so window can be moved.
+ gcn::Window::setTitleBarHeight(gcn::Window::getPadding());
+ setShowTitle(false);
+ setResizable(true);
+ setDefaultSize(758, 174, 42, 426);
+
+ mItems = new ItemShortcutContainer();
+
+ int border = SCROLL_PADDING * 2 + getPadding() * 2;
+ setMinWidth(mItems->getBoxWidth() + border);
+ setMinHeight(mItems->getBoxHeight() + border);
+ setMaxWidth(mItems->getBoxWidth() * mItems->getMaxItems() + border);
+ setMaxHeight(mItems->getBoxHeight() * mItems->getMaxItems() + border);
+
+ mInvenScroll = new ScrollArea(mItems);
+ mInvenScroll->setPosition(SCROLL_PADDING, SCROLL_PADDING);
+ mInvenScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+
+ add(mInvenScroll);
+
+ addWindowListener(this);
+ loadWindowState("ItemShortcut");
+}
+
+ItemShortcutWindow::~ItemShortcutWindow()
+{
+ delete mItems;
+ delete mInvenScroll;
+}
+
+void ItemShortcutWindow::logic()
+{
+ Window::logic();
+}
+
+void ItemShortcutWindow::windowResized(const WindowEvent &event)
+{
+ const gcn::Rectangle area = getChildrenArea();
+
+ mInvenScroll->setSize(
+ area.width - SCROLL_PADDING,
+ area.height - SCROLL_PADDING);
+}
diff --git a/src/gui/itemshortcutwindow.h b/src/gui/itemshortcutwindow.h
new file mode 100644
index 00000000..83bc348d
--- /dev/null
+++ b/src/gui/itemshortcutwindow.h
@@ -0,0 +1,69 @@
+/*
+ * The Mana World
+ * Copyright 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _TMW_ITEMSHORTCUTWINDOW_H
+#define _TMW_ITEMSHORTCUTWINDOW_H
+
+#include "window.h"
+#include "windowlistener.h"
+
+#include "../guichanfwd.h"
+
+class ItemShortcutContainer;
+
+/**
+ * Inventory dialog.
+ *
+ * \ingroup Interface
+ */
+class ItemShortcutWindow : public Window, WindowListener
+{
+ public:
+ /**
+ * Constructor.
+ */
+ ItemShortcutWindow();
+
+ /**
+ * Destructor.
+ */
+ ~ItemShortcutWindow();
+
+ /**
+ * Logic (updates buttons and weight information).
+ */
+ void logic();
+
+ /**
+ * Called whenever the window is resized.
+ */
+ void windowResized(const WindowEvent &event);
+
+ private:
+ ItemShortcutContainer *mItems;
+
+ gcn::ScrollArea *mInvenScroll;
+};
+
+extern ItemShortcutWindow *itemShortcutWindow;
+
+#endif
diff --git a/src/gui/menuwindow.cpp b/src/gui/menuwindow.cpp
index bfa2f1f2..8d4d184d 100644
--- a/src/gui/menuwindow.cpp
+++ b/src/gui/menuwindow.cpp
@@ -37,6 +37,7 @@ extern Window *inventoryWindow;
extern Window *equipmentWindow;
extern Window *skillDialog;
extern Window *statusWindow;
+extern Window *itemShortcutWindow;
namespace {
struct MenuWindowListener : public gcn::ActionListener
@@ -62,6 +63,7 @@ MenuWindow::MenuWindow():
N_("Equipment"),
N_("Inventory"),
N_("Skills"),
+ N_("Shortcut"),
N_("Setup"),
0
};
@@ -109,14 +111,20 @@ void MenuWindowListener::action(const gcn::ActionEvent &event)
{
window = skillDialog;
}
+ else if (event.getId() == "Shortcut")
+ {
+ window = itemShortcutWindow;
+ }
else if (event.getId() == "Setup")
{
window = setupWindow;
}
- if (window) {
+ if (window)
+ {
window->setVisible(!window->isVisible());
- if (window->isVisible()) {
+ if (window->isVisible())
+ {
window->requestMoveToTop();
}
}
diff --git a/src/gui/popupmenu.cpp b/src/gui/popupmenu.cpp
index 48bbd3d0..aeb6637d 100644
--- a/src/gui/popupmenu.cpp
+++ b/src/gui/popupmenu.cpp
@@ -200,12 +200,6 @@ void PopupMenu::handleLink(const std::string& link)
setVisible(false);
- /*
- * This is need cause of a bug in guichan that leave
- * the focus on the popup menu even if is not visible.
- */
- _getFocusHandler()->focusNone();
-
mBeing = NULL;
mFloorItem = NULL;
mItem = NULL;
diff --git a/src/gui/selectionlistener.h b/src/gui/selectionlistener.h
index b39672b5..917a4871 100644
--- a/src/gui/selectionlistener.h
+++ b/src/gui/selectionlistener.h
@@ -25,33 +25,23 @@
#define _TMW_SELECTIONLISTENER_H__
#include <guichan/widget.hpp>
+#include <guichan/event.hpp>
/**
* An event that characterizes a change in the current selection.
*
* \ingroup GUI
*/
-class SelectionEvent
+class SelectionEvent : public gcn::Event
{
public:
/**
* Constructor.
*/
SelectionEvent(gcn::Widget *source):
- mSource(source)
+ gcn::Event(source)
{
}
-
- /**
- * The widget from which the event originated.
- */
- gcn::Widget* getSource() const
- {
- return mSource;
- }
-
- private:
- gcn::Widget *mSource;
};
/**
diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp
index b601d70c..5f1011c1 100644
--- a/src/gui/sell.cpp
+++ b/src/gui/sell.cpp
@@ -44,58 +44,44 @@ SellDialog::SellDialog():
Window("Sell"),
mMaxItems(0), mAmountItems(0)
{
+ setResizable(true);
+ setMinWidth(260);
+ setMinHeight(230);
+ setDefaultSize(0, 0, 260, 230);
+
mShopItems = new ShopItems();
mShopItemList = new ShopListBox(mShopItems, mShopItems);
- ScrollArea *scrollArea = new ScrollArea(mShopItemList);
+ mScrollArea = new ScrollArea(mShopItemList);
mSlider = new Slider(1.0);
mQuantityLabel = new gcn::Label("0");
mMoneyLabel = new gcn::Label("Money: 0 GP / Total: 0 GP");
- mItemDescLabel = new gcn::Label("Description:");
- mItemEffectLabel = new gcn::Label("Effect:");
mIncreaseButton = new Button("+", "+", this);
mDecreaseButton = new Button("-", "-", this);
mSellButton = new Button("Sell", "sell", this);
- Button *quitButton = new Button("Quit", "quit", this);
- mSellButton->setEnabled(false);
-
- setContentSize(260, 210);
- scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
- scrollArea->setDimension(gcn::Rectangle(5, 5, 250, 110));
- mShopItemList->setDimension(gcn::Rectangle(5, 5, 238, 110));
-
- mSlider->setDimension(gcn::Rectangle(5, 120, 200, 10));
- mSlider->setEnabled(false);
-
- mQuantityLabel->setPosition(215, 120);
+ mQuitButton = new Button("Quit", "quit", this);
+ mItemDescLabel = new gcn::Label("Description:");
+ mItemEffectLabel = new gcn::Label("Effect:");
- mIncreaseButton->setPosition(40, 186);
mIncreaseButton->setSize(20, 20);
- mIncreaseButton->setEnabled(false);
-
- mDecreaseButton->setPosition(10, 186);
mDecreaseButton->setSize(20, 20);
- mDecreaseButton->setEnabled(false);
+ mQuantityLabel->setWidth(60);
- mMoneyLabel->setPosition(5, 130);
- mItemEffectLabel->setDimension(gcn::Rectangle(5, 150, 240, 14));
- mItemDescLabel->setDimension(gcn::Rectangle(5, 169, 240, 14));
-
- mSellButton->setPosition(175, 186);
+ mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mIncreaseButton->setEnabled(false);
+ mDecreaseButton->setEnabled(false);
mSellButton->setEnabled(false);
+ mSlider->setEnabled(false);
- quitButton->setPosition(208, 186);
-
+ mShopItemList->setPriceCheck(false);
mShopItemList->setActionEventId("item");
mSlider->setActionEventId("slider");
- mShopItemList->setPriceCheck(false);
-
mShopItemList->addActionListener(this);
mShopItemList->addSelectionListener(this);
mSlider->addActionListener(this);
- add(scrollArea);
+ add(mScrollArea);
add(mSlider);
add(mQuantityLabel);
add(mMoneyLabel);
@@ -104,8 +90,10 @@ SellDialog::SellDialog():
add(mIncreaseButton);
add(mDecreaseButton);
add(mSellButton);
- add(quitButton);
+ add(mQuitButton);
+ addWindowListener(this);
+ loadWindowState("Sell");
setLocationRelativeTo(getParent());
}
@@ -117,7 +105,7 @@ SellDialog::~SellDialog()
void SellDialog::reset()
{
mShopItems->clear();
- mSlider->setValue(0.0);
+ mSlider->setValue(0);
// Reset previous selected item to prevent failing asserts
mShopItemList->setSelected(-1);
@@ -135,16 +123,11 @@ void SellDialog::action(const gcn::ActionEvent &event)
{
int selectedItem = mShopItemList->getSelected();
- if (event.getId() == "item")
- {
- mAmountItems = 0;
- mSlider->setValue(0);
- updateButtonsAndLabels();
- }
- else if (event.getId() == "quit")
+ if (event.getId() == "quit")
{
setVisible(false);
current_npc = 0;
+ return;
}
// The following actions require a valid item selection
@@ -156,21 +139,19 @@ void SellDialog::action(const gcn::ActionEvent &event)
if (event.getId() == "slider")
{
- mAmountItems = (int) (mSlider->getValue() * mMaxItems);
+ mAmountItems = (int) mSlider->getValue();
updateButtonsAndLabels();
}
else if (event.getId() == "+" && mAmountItems < mMaxItems)
{
mAmountItems++;
-
- mSlider->setValue((double) mAmountItems /(double) mMaxItems);
+ mSlider->setValue(mAmountItems);
updateButtonsAndLabels();
}
- else if (event.getId() == "-" && mAmountItems > 0)
+ else if (event.getId() == "-" && mAmountItems > 1)
{
mAmountItems--;
-
- mSlider->setValue((double) mAmountItems / (double) mMaxItems);
+ mSlider->setValue(mAmountItems);
updateButtonsAndLabels();
}
else if (event.getId() == "sell" && mAmountItems > 0
@@ -182,8 +163,7 @@ void SellDialog::action(const gcn::ActionEvent &event)
mMaxItems -= mAmountItems;
mShopItems->getShop()->at(selectedItem).quantity = mMaxItems;
mPlayerMoney += (mAmountItems * mShopItems->at(selectedItem).price);
- mAmountItems = 0;
- mSlider->setValue(0);
+ mAmountItems = 1;
if (!mMaxItems)
{
@@ -194,6 +174,7 @@ void SellDialog::action(const gcn::ActionEvent &event)
}
else
{
+ mSlider->gcn::Slider::setScale(1, mMaxItems);
// Update only when there are items left, the entry doesn't exist
// otherwise and can't be updated
updateButtonsAndLabels();
@@ -204,10 +185,54 @@ void SellDialog::action(const gcn::ActionEvent &event)
void SellDialog::selectionChanged(const SelectionEvent &event)
{
// Reset amount of items and update labels
- mAmountItems = 0;
+ mAmountItems = 1;
mSlider->setValue(0);
updateButtonsAndLabels();
+ mSlider->gcn::Slider::setScale(1, mMaxItems);
+}
+
+void SellDialog::windowResized(const WindowEvent &event)
+{
+ gcn::Rectangle area = getChildrenArea();
+ int width = area.width;
+ int height = area.height;
+
+ mDecreaseButton->setPosition(8, height - 8 - mDecreaseButton->getHeight());
+ mIncreaseButton->setPosition(
+ mDecreaseButton->getX() + mDecreaseButton->getWidth() + 5,
+ mDecreaseButton->getY());
+
+ mQuitButton->setPosition(
+ width - 8 - mQuitButton->getWidth(),
+ height - 8 - mQuitButton->getHeight());
+ mSellButton->setPosition(
+ mQuitButton->getX() - 5 - mSellButton->getWidth(),
+ mQuitButton->getY());
+
+ mItemDescLabel->setDimension(gcn::Rectangle(8,
+ mSellButton->getY() - 5 - mItemDescLabel->getHeight(),
+ width - 16,
+ mItemDescLabel->getHeight()));
+ mItemEffectLabel->setDimension(gcn::Rectangle(8,
+ mItemDescLabel->getY() - 5 - mItemEffectLabel->getHeight(),
+ width - 16,
+ mItemEffectLabel->getHeight()));
+ mMoneyLabel->setDimension(gcn::Rectangle(8,
+ mItemEffectLabel->getY() - 5 - mMoneyLabel->getHeight(),
+ width - 16,
+ mMoneyLabel->getHeight()));
+
+ mQuantityLabel->setPosition(
+ width - mQuantityLabel->getWidth() - 8,
+ mMoneyLabel->getY() - 5 - mQuantityLabel->getHeight());
+ mSlider->setDimension(gcn::Rectangle(8,
+ mQuantityLabel->getY(),
+ mQuantityLabel->getX() - 8 - 8,
+ 10));
+
+ mScrollArea->setDimension(gcn::Rectangle(8, 8, width - 16,
+ mSlider->getY() - 5 - 8));
}
void SellDialog::setMoney(int amount)
@@ -246,15 +271,13 @@ SellDialog::updateButtonsAndLabels()
// Update Buttons and slider
mSellButton->setEnabled(mAmountItems > 0);
- mDecreaseButton->setEnabled(mAmountItems > 0);
+ mDecreaseButton->setEnabled(mAmountItems > 1);
mIncreaseButton->setEnabled(mAmountItems < mMaxItems);
- mSlider->setEnabled(selectedItem > -1);
+ mSlider->setEnabled(mMaxItems > 1);
// Update the quantity and money labels
mQuantityLabel->setCaption(
toString(mAmountItems) + " / " + toString(mMaxItems));
- mQuantityLabel->adjustSize();
mMoneyLabel->setCaption("Money: " + toString(income) + " GP / Total: "
+ toString(mPlayerMoney + income) + " GP");
- mMoneyLabel->adjustSize();
}
diff --git a/src/gui/sell.h b/src/gui/sell.h
index fc42fd1c..d1e2ddd2 100644
--- a/src/gui/sell.h
+++ b/src/gui/sell.h
@@ -28,6 +28,7 @@
#include "window.h"
#include "selectionlistener.h"
+#include "windowlistener.h"
#include "../guichanfwd.h"
@@ -40,7 +41,8 @@ class ShopListBox;
*
* \ingroup Interface
*/
-class SellDialog : public Window, gcn::ActionListener, SelectionListener
+class SellDialog : public Window, gcn::ActionListener, SelectionListener,
+ WindowListener
{
public:
/**
@@ -78,21 +80,27 @@ class SellDialog : public Window, gcn::ActionListener, SelectionListener
void selectionChanged(const SelectionEvent &event);
/**
+ * Called whenever the window is resized.
+ */
+ void windowResized(const WindowEvent &event);
+
+ /**
* Gives Player's Money amount
*/
void setMoney(int amount);
+ private:
/**
* Updates the state of buttons and labels.
*/
- void
- updateButtonsAndLabels();
+ void updateButtonsAndLabels();
- private:
gcn::Button *mSellButton;
+ gcn::Button *mQuitButton;
gcn::Button *mIncreaseButton;
gcn::Button *mDecreaseButton;
ShopListBox *mShopItemList;
+ gcn::ScrollArea *mScrollArea;
gcn::Label *mMoneyLabel;
gcn::Label *mItemDescLabel;
gcn::Label *mItemEffectLabel;
diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp
index 3ea19059..6a13232a 100644
--- a/src/gui/setup.cpp
+++ b/src/gui/setup.cpp
@@ -27,6 +27,7 @@
#include "setup_audio.h"
#include "setup_joystick.h"
#include "setup_video.h"
+#include "setup_keyboard.h"
#include "tabbedcontainer.h"
#include "../utils/dtor.h"
@@ -43,7 +44,8 @@ extern Window *skillDialog;
Setup::Setup():
Window(_("Setup"))
{
- int width = 230;
+ setCloseButton(true);
+ int width = 250;
int height = 245;
setContentSize(width, height);
@@ -59,7 +61,7 @@ Setup::Setup():
}
TabbedContainer *panel = new TabbedContainer();
- panel->setDimension(gcn::Rectangle(5, 5, 220, 205));
+ panel->setDimension(gcn::Rectangle(5, 5, 250, 205));
panel->setOpaque(false);
SetupTab *tab;
@@ -76,6 +78,10 @@ Setup::Setup():
panel->addTab(tab, _("Joystick"));
mTabs.push_back(tab);
+ tab = new Setup_Keyboard();
+ panel->addTab(tab, "Keyboard");
+ mTabs.push_back(tab);
+
add(panel);
setLocationRelativeTo(getParent());
diff --git a/src/gui/setup_keyboard.cpp b/src/gui/setup_keyboard.cpp
new file mode 100644
index 00000000..e88080b5
--- /dev/null
+++ b/src/gui/setup_keyboard.cpp
@@ -0,0 +1,187 @@
+/*
+ * The Mana World
+ * Copyright 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "setup_keyboard.h"
+
+#include <guichan/widgets/label.hpp>
+#include <guichan/listmodel.hpp>
+
+#include "button.h"
+#include "listbox.h"
+#include "ok_dialog.h"
+#include "scrollarea.h"
+
+#include "../configuration.h"
+#include "../keyboardconfig.h"
+
+#include "../utils/tostring.h"
+
+#include <SDL_keyboard.h>
+
+/**
+ * The list model for key function list.
+ *
+ * \ingroup Interface
+ */
+class KeyListModel : public gcn::ListModel
+{
+ public:
+ /**
+ * Returns the number of elements in container.
+ */
+ int getNumberOfElements() { return keyboard.KEY_TOTAL; }
+
+ /**
+ * Returns element from container.
+ */
+ std::string getElementAt(int i) { return mKeyFunctions[i]; }
+
+ /**
+ * Sets element from container.
+ */
+ void setElementAt(int i, std::string caption)
+ {
+ mKeyFunctions[i] = caption;
+ }
+
+ private:
+ std::string mKeyFunctions[KeyboardConfig::KEY_TOTAL];
+};
+
+Setup_Keyboard::Setup_Keyboard():
+ mKeyListModel(new KeyListModel()),
+ mKeyList(new ListBox(mKeyListModel)),
+ mKeySetting(false)
+{
+ keyboard.setSetupKeyboard(this);
+ setOpaque(false);
+
+ refreshKeys();
+
+ mKeyList->setDimension(gcn::Rectangle(0, 0, 185, 140));
+ mKeyList->addActionListener(this);
+ mKeyList->setSelected(-1);
+
+ ScrollArea *scrollArea = new ScrollArea(mKeyList);
+ scrollArea->setDimension(gcn::Rectangle(10, 10, 200, 140));
+ add(scrollArea);
+
+ mAssignKeyButton = new Button("Assign", "assign", this);
+ mAssignKeyButton->setPosition(165, 155);
+ mAssignKeyButton->addActionListener(this);
+ mAssignKeyButton->setEnabled(false);
+ add(mAssignKeyButton);
+
+ mMakeDefaultButton = new Button("Default", "makeDefault", this);
+ mMakeDefaultButton->setPosition(10, 155);
+ mMakeDefaultButton->addActionListener(this);
+ add(mMakeDefaultButton);
+}
+
+Setup_Keyboard::~Setup_Keyboard()
+{
+ delete mKeyList;
+ delete mKeyListModel;
+
+ delete mAssignKeyButton;
+ delete mMakeDefaultButton;
+}
+
+void Setup_Keyboard::apply()
+{
+ keyUnresolved();
+
+ if (keyboard.hasConflicts())
+ {
+ new OkDialog("Key Conflict(s) Detected.",
+ "Resolve them, or gameplay may result in strange behaviour.");
+ }
+ keyboard.setEnabled(true);
+ keyboard.store();
+}
+
+void Setup_Keyboard::cancel()
+{
+ keyUnresolved();
+
+ keyboard.retrieve();
+ keyboard.setEnabled(true);
+
+ refreshKeys();
+}
+
+void Setup_Keyboard::action(const gcn::ActionEvent &event)
+{
+ if (event.getSource() == mKeyList)
+ {
+ if (!mKeySetting) {
+ mAssignKeyButton->setEnabled(true);
+ }
+ }
+ else if (event.getId() == "assign")
+ {
+ mKeySetting = true;
+ mAssignKeyButton->setEnabled(false);
+ keyboard.setEnabled(false);
+ int i(mKeyList->getSelected());
+ keyboard.setNewKeyIndex(i);
+ mKeyListModel->setElementAt(i, keyboard.getKeyCaption(i) + ": ?");
+ }
+ else if (event.getId() == "makeDefault")
+ {
+ keyboard.makeDefault();
+ refreshKeys();
+ }
+}
+
+void Setup_Keyboard::refreshAssignedKey(int index)
+{
+ std::string caption;
+ char *temp = SDL_GetKeyName(
+ (SDLKey) keyboard.getKeyValue(index));
+ caption = keyboard.getKeyCaption(index) + ": " + toString(temp);
+ mKeyListModel->setElementAt(index, caption);
+}
+
+void Setup_Keyboard::newKeyCallback(int index)
+{
+ mKeySetting = false;
+ refreshAssignedKey(index);
+ mAssignKeyButton->setEnabled(true);
+}
+
+void Setup_Keyboard::refreshKeys()
+{
+ for(int i = 0; i < keyboard.KEY_TOTAL; i++)
+ {
+ refreshAssignedKey(i);
+ }
+}
+
+void Setup_Keyboard::keyUnresolved()
+{
+ if (mKeySetting) {
+ newKeyCallback(keyboard.getNewKeyIndex());
+ keyboard.setNewKeyIndex(keyboard.KEY_NO_VALUE);
+ }
+}
diff --git a/src/gui/setup_keyboard.h b/src/gui/setup_keyboard.h
new file mode 100644
index 00000000..b72e8746
--- /dev/null
+++ b/src/gui/setup_keyboard.h
@@ -0,0 +1,84 @@
+/*
+ * The Mana World
+ * Copyright 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#ifndef _TMW_GUI_SETUP_KEYBOARD_H
+#define _TMW_GUI_SETUP_KEYBOARD_H
+
+#include "setuptab.h"
+#include "button.h"
+#include "../guichanfwd.h"
+
+#include <guichan/actionlistener.hpp>
+
+
+#include <string>
+
+class Setup_Keyboard : public SetupTab, public gcn::ActionListener
+{
+ public:
+ /**
+ * Constructor
+ */
+ Setup_Keyboard();
+
+ /**
+ * Destructor
+ */
+ ~Setup_Keyboard();
+
+ void apply();
+ void cancel();
+
+ void action(const gcn::ActionEvent &event);
+
+ /**
+ * Get an update on the assigned key.
+ */
+ void refreshAssignedKey(int index);
+
+ /**
+ * The callback function when a new key has been pressed.
+ */
+ void newKeyCallback(int index);
+
+ /**
+ * Shorthand method to update all the keys.
+ */
+ void refreshKeys();
+
+ /**
+ * If a key function is unresolved, then this reverts it.
+ */
+ void keyUnresolved();
+
+ private:
+ class KeyListModel *mKeyListModel;
+ gcn::ListBox *mKeyList;
+
+ gcn::Button *mAssignKeyButton;
+ gcn::Button *mMakeDefaultButton;
+
+ bool mKeySetting; /**< flag to check if key being set. */
+};
+
+#endif
diff --git a/src/gui/shoplistbox.cpp b/src/gui/shoplistbox.cpp
index 0e2ea6d3..ae787ab7 100644
--- a/src/gui/shoplistbox.cpp
+++ b/src/gui/shoplistbox.cpp
@@ -129,24 +129,8 @@ void ShopListBox::mousePressed(gcn::MouseEvent &event)
{
if (event.getButton() == gcn::MouseEvent::LEFT)
{
- bool enoughMoney = false;
- int y = event.getY();
-
- if (mShopItems && mPriceCheck)
- {
- if (mPlayerMoney >= mShopItems->at(y / mRowHeight).price)
- enoughMoney = true;
- }
- else // Old Behaviour
- {
- enoughMoney = true;
- }
-
- if (enoughMoney)
- {
- setSelected(y / mRowHeight);
- generateAction();
- }
+ setSelected(event.getY() / mRowHeight);
+ generateAction();
}
}
diff --git a/src/gui/skill.cpp b/src/gui/skill.cpp
index 884b3744..d5cfe76a 100644
--- a/src/gui/skill.cpp
+++ b/src/gui/skill.cpp
@@ -63,22 +63,18 @@ const char *skill_db[] = {
SkillDialog::SkillDialog():
Window("Skills")
{
+ setCloseButton(true);
setDefaultSize(windowContainer->getWidth() - 255, 25, 240, 240);
mSkillListBox = new ListBox(this);
ScrollArea *skillScrollArea = new ScrollArea(mSkillListBox);
- mCloseButton = new Button("Close", "close", this);
mSkillListBox->setActionEventId("skill");
skillScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
skillScrollArea->setDimension(gcn::Rectangle(5, 5, 230, 180));
- mCloseButton->setPosition(
- skillScrollArea->getX() + skillScrollArea->getWidth() - mCloseButton->getWidth(),
- 210);
add(skillScrollArea);
- add(mCloseButton);
mSkillListBox->addActionListener(this);
diff --git a/src/gui/skill.h b/src/gui/skill.h
index b8794e35..f1a14d50 100644
--- a/src/gui/skill.h
+++ b/src/gui/skill.h
@@ -71,7 +71,6 @@ class SkillDialog : public Window, public gcn::ActionListener,
private:
gcn::ListBox *mSkillListBox;
- gcn::Button *mCloseButton;
std::vector<SKILL*> mSkillList;
};
diff --git a/src/gui/status.cpp b/src/gui/status.cpp
index 7da3b905..323a6b16 100644
--- a/src/gui/status.cpp
+++ b/src/gui/status.cpp
@@ -39,6 +39,7 @@ StatusWindow::StatusWindow(LocalPlayer *player):
mPlayer(player)
{
setResizable(true);
+ setCloseButton(true);
setDefaultSize((windowContainer->getWidth() - 365) / 2,
(windowContainer->getHeight() - 255) / 2, 365, 280);
loadWindowState("Status");
@@ -219,7 +220,7 @@ void StatusWindow::update()
mHpBar->setColor(0, 171, 34); // Green
}
- mHpBar->setProgress((float)hp / maxHp);
+ mHpBar->setProgress((float) hp / maxHp);
// Stats Part
// ----------
@@ -235,7 +236,8 @@ void StatusWindow::update()
int statusPoints = mPlayer->getAttributeIncreasePoints();
// Update labels
- for (int i = 0; i < 7; i++) {
+ for (int i = 0; i < 7; i++)
+ {
mStatsLabel[i]->setCaption(attrNames[i]);
mStatsDisplayLabel[i]->setCaption(
strprintf("%d / %d",
diff --git a/src/gui/status.h b/src/gui/status.h
index 40d25a2a..62cd8805 100644
--- a/src/gui/status.h
+++ b/src/gui/status.h
@@ -41,7 +41,8 @@ class ProgressBar;
*
* \ingroup Interface
*/
-class StatusWindow : public Window, public gcn::ActionListener {
+class StatusWindow : public Window, public gcn::ActionListener
+{
public:
/**
* Constructor.
diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp
index ed75e5b3..5d81bb9c 100644
--- a/src/gui/updatewindow.cpp
+++ b/src/gui/updatewindow.cpp
@@ -46,6 +46,8 @@
#include "../resources/resourcemanager.h"
+extern std::string homeDir;
+
/**
* Calculates the Alder-32 checksum for the given file.
*/
@@ -119,7 +121,7 @@ UpdaterWindow::UpdaterWindow():
mUpdateHost =
config.getValue("updatehost", "http://updates.themanaworld.org");
- mBasePath = config.getValue("homeDir", ".");
+ mBasePath = homeDir;
// Try to download the updates list
download();
diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp
index 2af1d960..4c6b04a2 100644
--- a/src/gui/viewport.cpp
+++ b/src/gui/viewport.cpp
@@ -55,8 +55,7 @@ Viewport::Viewport():
mCameraX(0),
mCameraY(0),
mShowDebugPath(false),
- mPlayerFollowMouse(false),
- mPopupActive(false)
+ mPlayerFollowMouse(false)
{
setOpaque(false);
addMouseListener(this);
@@ -372,21 +371,20 @@ Viewport::mousePressed(gcn::MouseEvent &event)
if ((being = beingManager->findBeing(tilex, tiley)) &&
being->getType() != Being::LOCALPLAYER)
{
- showPopup(event.getX(), event.getY(), being);
+ mPopupMenu->showPopup(event.getX(), event.getY(), being);
return;
}
else if((floorItem = floorItemManager->findByCoordinates(tilex, tiley)))
{
- showPopup(event.getX(), event.getY(), floorItem);
+ mPopupMenu->showPopup(event.getX(), event.getY(), floorItem);
return;
}
}
// If a popup is active, just remove it
- if (mPopupActive)
+ if (mPopupMenu->isVisible())
{
mPopupMenu->setVisible(false);
- mPopupActive = false;
return;
}
@@ -450,21 +448,6 @@ void
Viewport::showPopup(int x, int y, Item *item)
{
mPopupMenu->showPopup(x, y, item);
- mPopupActive = true;
-}
-
-void
-Viewport::showPopup(int x, int y, FloorItem *floorItem)
-{
- mPopupMenu->showPopup(x, y, floorItem);
- mPopupActive = true;
-}
-
-void
-Viewport::showPopup(int x, int y, Being *being)
-{
- mPopupMenu->showPopup(x, y, being);
- mPopupActive = true;
}
void
diff --git a/src/gui/viewport.h b/src/gui/viewport.h
index 22d0f249..eeb31bae 100644
--- a/src/gui/viewport.h
+++ b/src/gui/viewport.h
@@ -130,18 +130,6 @@ class Viewport : public WindowContainer, public gcn::MouseListener,
private:
/**
- * Shows a popup for a floor item.
- * TODO Find some way to get rid of FloorItem here
- */
- void showPopup(int x, int y, FloorItem *floorItem);
-
- /**
- * Shows a popup for a being.
- * TODO Find some way to get rid of Being here
- */
- void showPopup(int x, int y, Being *being);
-
- /**
* Helper function for loading target cursors
*/
void
@@ -187,7 +175,6 @@ class Viewport : public WindowContainer, public gcn::MouseListener,
int mWalkTime;
PopupMenu *mPopupMenu; /**< Popup menu. */
- bool mPopupActive;
};
#endif
diff --git a/src/gui/window.cpp b/src/gui/window.cpp
index 84f4466c..17447009 100644
--- a/src/gui/window.cpp
+++ b/src/gui/window.cpp
@@ -26,6 +26,7 @@
#include <guichan/exception.hpp>
#include <guichan/widgets/icon.hpp>
+#include "gui.h"
#include "gccontainer.h"
#include "windowcontainer.h"
@@ -42,7 +43,9 @@
ConfigListener *Window::windowConfigListener = 0;
WindowContainer *Window::windowContainer = 0;
int Window::instances = 0;
+int Window::mouseResize = 0;
ImageRect Window::border;
+Image *Window::closeImage = NULL;
class WindowConfigListener : public ConfigListener
{
@@ -60,7 +63,7 @@ Window::Window(const std::string& caption, bool modal, Window *parent):
mParent(parent),
mModal(modal),
mResizable(false),
- mMouseResize(0),
+ mCloseButton(false),
mSticky(false),
mMinWinWidth(100),
mMinWinHeight(40),
@@ -88,6 +91,8 @@ Window::Window(const std::string& caption, bool modal, Window *parent):
border.grid[7] = dBorders->getSubImage(4, 15, 3, 4);
border.grid[8] = dBorders->getSubImage(7, 15, 4, 4);
dBorders->decRef();
+ closeImage = resman->getImage("graphics/gui/close_button.png");
+
windowConfigListener = new WindowConfigListener();
// Send GUI alpha changed for initialization
windowConfigListener->optionChanged("guialpha");
@@ -110,6 +115,7 @@ Window::Window(const std::string& caption, bool modal, Window *parent):
if (mModal)
{
+ gui->setCursorType(Gui::CURSOR_POINTER);
requestModalFocus();
}
@@ -153,6 +159,7 @@ Window::~Window()
delete border.grid[6];
delete border.grid[7];
delete border.grid[8];
+ closeImage->decRef();
}
delete mChrome;
@@ -173,11 +180,19 @@ void Window::draw(gcn::Graphics *graphics)
// Draw title
if (getTitleBarHeight())
{
- graphics->setColor(gcn::Color(0, 0, 0));
- graphics->setFont(getFont());
- graphics->drawText(getCaption(), 7, 5, gcn::Graphics::LEFT);
+ g->setColor(gcn::Color(0, 0, 0));
+ g->setFont(getFont());
+ g->drawText(getCaption(), 7, 5, gcn::Graphics::LEFT);
}
+ // Draw Close Button
+ if (mCloseButton)
+ {
+ g->drawImage(closeImage,
+ getWidth() - closeImage->getWidth() - getPadding(),
+ getPadding()
+ );
+ }
drawChildren(graphics);
}
@@ -207,6 +222,8 @@ void Window::setWidth(int width)
{
mGrip->setX(getWidth() - mGrip->getWidth() - getChildrenArea().x);
}
+
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_RESIZED));
}
void Window::setHeight(int height)
@@ -217,6 +234,8 @@ void Window::setHeight(int height)
{
mGrip->setY(getHeight() - mGrip->getHeight() - getChildrenArea().y);
}
+
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_RESIZED));
}
void Window::setDimension(const gcn::Rectangle &dimension)
@@ -228,6 +247,27 @@ void Window::setDimension(const gcn::Rectangle &dimension)
mGrip->setX(getWidth() - mGrip->getWidth() - getChildrenArea().x);
mGrip->setY(getHeight() - mGrip->getHeight() - getChildrenArea().y);
}
+
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_RESIZED));
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_MOVED));
+}
+
+void Window::setPosition(int x, int y)
+{
+ gcn::Window::setPosition(x, y);
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_MOVED));
+}
+
+void Window::setX(int x)
+{
+ gcn::Window::setX(x);
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_MOVED));
+}
+
+void Window::setY(int y)
+{
+ gcn::Window::setY(y);
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_MOVED));
}
void Window::setLocationRelativeTo(gcn::Widget *widget)
@@ -280,6 +320,11 @@ void Window::setResizable(bool r)
}
}
+void Window::setCloseButton(bool flag)
+{
+ mCloseButton = flag;
+}
+
bool Window::isResizable()
{
return mResizable;
@@ -327,27 +372,73 @@ void Window::mousePressed(gcn::MouseEvent &event)
// Let Guichan move window to top and figure out title bar drag
gcn::Window::mousePressed(event);
- const int x = event.getX();
- const int y = event.getY();
- mMouseResize = 0;
+ if (event.getButton() == gcn::MouseEvent::LEFT)
+ {
+ const int x = event.getX();
+ const int y = event.getY();
+
+ // Handle close button
+ if (mCloseButton)
+ {
+ gcn::Rectangle closeButtonRect(
+ getWidth() - closeImage->getWidth() - getPadding(),
+ getPadding(),
+ closeImage->getWidth(),
+ closeImage->getHeight());
+
+ if (closeButtonRect.isPointInRect(x, y))
+ {
+ setVisible(false);
+ }
+ }
+
+ // Handle window resizing
+ mouseResize = getResizeHandles(event);
+ }
+}
+
+void Window::mouseReleased(gcn::MouseEvent &event)
+{
+ if (mResizable && mouseResize)
+ {
+ mouseResize = 0;
+ gui->setCursorType(Gui::CURSOR_POINTER);
+ }
+
+ // This should be the responsibility of Guichan (and is from 0.8.0 on)
+ mIsMoving = false;
+}
- // Activate resizing handles as appropriate
- if (event.getSource() == this && isResizable() &&
- event.getButton() == gcn::MouseEvent::LEFT &&
- !getChildrenArea().isPointInRect(x, y))
+void Window::mouseExited(gcn::MouseEvent &event)
+{
+ if (mResizable && !mouseResize)
{
- mMouseResize |= (x > getWidth() - resizeBorderWidth) ? RIGHT :
- (x < resizeBorderWidth) ? LEFT : 0;
- mMouseResize |= (y > getHeight() - resizeBorderWidth) ? BOTTOM :
- (y < resizeBorderWidth) ? TOP : 0;
+ gui->setCursorType(Gui::CURSOR_POINTER);
}
- else if (event.getSource() == mGrip &&
- event.getButton() == gcn::MouseEvent::LEFT)
+}
+
+void Window::mouseMoved(gcn::MouseEvent &event)
+{
+ int resizeHandles = getResizeHandles(event);
+
+ // Changes the custom mouse cursor based on it's current position.
+ switch (resizeHandles)
{
- mDragOffsetX = x;
- mDragOffsetY = y;
- mMouseResize |= BOTTOM | RIGHT;
- mIsMoving = false;
+ case BOTTOM | RIGHT:
+ gui->setCursorType(Gui::CURSOR_RESIZE_DOWN_RIGHT);
+ break;
+ case BOTTOM | LEFT:
+ gui->setCursorType(Gui::CURSOR_RESIZE_DOWN_LEFT);
+ break;
+ case BOTTOM:
+ gui->setCursorType(Gui::CURSOR_RESIZE_DOWN);
+ break;
+ case RIGHT:
+ case LEFT:
+ gui->setCursorType(Gui::CURSOR_RESIZE_ACROSS);
+ break;
+ default:
+ gui->setCursorType(Gui::CURSOR_POINTER);
}
}
@@ -366,31 +457,31 @@ void Window::mouseDragged(gcn::MouseEvent &event)
setPosition(newX, newY);
}
- if (mMouseResize && !mIsMoving)
+ if (mouseResize && !mIsMoving)
{
const int dx = event.getX() - mDragOffsetX;
const int dy = event.getY() - mDragOffsetY;
gcn::Rectangle newDim = getDimension();
- if (mMouseResize & (TOP | BOTTOM))
+ if (mouseResize & (TOP | BOTTOM))
{
- int newHeight = newDim.height + ((mMouseResize & TOP) ? -dy : dy);
+ int newHeight = newDim.height + ((mouseResize & TOP) ? -dy : dy);
newDim.height = std::min(mMaxWinHeight,
std::max(mMinWinHeight, newHeight));
- if (mMouseResize & TOP)
+ if (mouseResize & TOP)
{
newDim.y -= newDim.height - getHeight();
}
}
- if (mMouseResize & (LEFT | RIGHT))
+ if (mouseResize & (LEFT | RIGHT))
{
- int newWidth = newDim.width + ((mMouseResize & LEFT) ? -dx : dx);
+ int newWidth = newDim.width + ((mouseResize & LEFT) ? -dx : dx);
newDim.width = std::min(mMaxWinWidth,
std::max(mMinWinWidth, newWidth));
- if (mMouseResize & LEFT)
+ if (mouseResize & LEFT)
{
newDim.x -= newDim.width - getWidth();
}
@@ -417,11 +508,11 @@ void Window::mouseDragged(gcn::MouseEvent &event)
}
// Update mouse offset when dragging bottom or right border
- if (mMouseResize & BOTTOM)
+ if (mouseResize & BOTTOM)
{
mDragOffsetY += newDim.height - getHeight();
}
- if (mMouseResize & RIGHT)
+ if (mouseResize & RIGHT)
{
mDragOffsetX += newDim.width - getWidth();
}
@@ -469,3 +560,50 @@ void Window::resetToDefaultSize()
setContentSize(mDefaultWidth, mDefaultHeight);
updateContentSize();
}
+
+int Window::getResizeHandles(gcn::MouseEvent &event)
+{
+ int resizeHandles = 0;
+ const int y = event.getY();
+
+ if (mResizable && y > (int) mTitleBarHeight)
+ {
+ const int x = event.getX();
+
+ if (!getChildrenArea().isPointInRect(x, y) &&
+ event.getSource() == this)
+ {
+ resizeHandles |= (x > getWidth() - resizeBorderWidth) ? RIGHT :
+ (x < resizeBorderWidth) ? LEFT : 0;
+ resizeHandles |= (y > getHeight() - resizeBorderWidth) ? BOTTOM :
+ (y < resizeBorderWidth) ? TOP : 0;
+ }
+
+ if (event.getSource() == mGrip)
+ {
+ mDragOffsetX = x;
+ mDragOffsetY = y;
+ resizeHandles |= BOTTOM | RIGHT;
+ }
+ }
+
+ return resizeHandles;
+}
+
+void Window::fireWindowEvent(const WindowEvent &event)
+{
+ WindowListeners::iterator i_end = mListeners.end();
+ WindowListeners::iterator i = mListeners.begin();
+
+ switch (event.getType())
+ {
+ case WindowEvent::WINDOW_MOVED:
+ for (; i != i_end; ++i)
+ { (*i)->windowMoved(event); }
+ break;
+ case WindowEvent::WINDOW_RESIZED:
+ for (; i != i_end; ++i)
+ { (*i)->windowResized(event); }
+ break;
+ }
+}
diff --git a/src/gui/window.h b/src/gui/window.h
index 1ba23fb2..ab266422 100644
--- a/src/gui/window.h
+++ b/src/gui/window.h
@@ -28,11 +28,14 @@
#include "../guichanfwd.h"
+#include "windowlistener.h"
+
class ConfigListener;
class GCContainer;
class ImageRect;
class ResizeGrip;
class WindowContainer;
+class Image;
/**
* A window. This window can be dragged around and has a title bar. Windows are
@@ -120,16 +123,36 @@ class Window : public gcn::Window
void setDimension(const gcn::Rectangle &dimension);
/**
+ * Sets the position of this window.
+ */
+ void setPosition(int x, int y);
+
+ /**
+ * Sets the window x coordinate.
+ */
+ void setX(int x);
+
+ /**
+ * Sets the window y coordinate.
+ */
+ void setY(int y);
+
+ /**
* Sets the location relative to the given widget.
*/
void setLocationRelativeTo(gcn::Widget *widget);
/**
- * Sets whether of not the window can be resized.
+ * Sets whether or not the window can be resized.
*/
void setResizable(bool resize);
/**
+ * Sets whether or not the window has a close button.
+ */
+ void setCloseButton(bool flag);
+
+ /**
* Returns whether the window can be resized.
*/
bool isResizable();
@@ -155,9 +178,14 @@ class Window : public gcn::Window
void setMaxHeight(unsigned int height);
/**
- * Sets whether the window is sticky.
- * A sticky window will not have its visibility set to false
- * on a general setVisible(false) call.
+ * Sets flag to show a title or not.
+ */
+ void setShowTitle(bool flag)
+ { mShowTitle = flag; }
+
+ /**
+ * Sets whether the window is sticky. A sticky window will not have
+ * its visibility set to false on a general setVisible(false) call.
*/
void setSticky(bool sticky);
@@ -167,10 +195,9 @@ class Window : public gcn::Window
bool isSticky();
/**
- * Overloads window setVisible by guichan to allow sticky window
- * Handling
+ * Overloads window setVisible by Guichan to allow sticky window
+ * handling.
*/
-
void setVisible(bool visible);
/**
@@ -199,6 +226,24 @@ class Window : public gcn::Window
void mouseDragged(gcn::MouseEvent &event);
/**
+ * Implements custom cursor image changing context, based on mouse
+ * relative position.
+ */
+ void mouseMoved(gcn::MouseEvent &event);
+
+ /**
+ * When the mouse button has been let go, this ensures that the mouse
+ * custom cursor is restored back to it's standard image.
+ */
+ void mouseReleased(gcn::MouseEvent &event);
+
+ /**
+ * When the mouse leaves the window this ensures that the custom cursor
+ * is restored back to it's standard image.
+ */
+ void mouseExited(gcn::MouseEvent &event);
+
+ /**
* Read the x, y, and width and height for resizables in the config
* based on the given string.
* That function let the values set with set{X, Y, Height, width}()
@@ -216,11 +261,25 @@ class Window : public gcn::Window
int defaultWidth, int defaultHeight);
/**
- * Reset the win pos and size to default.
- * Don't forget to set defaults first.
+ * Reset the win pos and size to default. Don't forget to set defaults
+ * first.
*/
void resetToDefaultSize();
+ /**
+ * Adds a listener to the list that's notified when the window is
+ * moved or resized.
+ */
+ void addWindowListener(WindowListener *listener)
+ { mListeners.push_back(listener); }
+
+ /**
+ * Removes a listener from the list that's notified when the window is
+ * moved or resized.
+ */
+ void removeWindowListener(WindowListener *listener)
+ { mListeners.remove(listener); }
+
enum ResizeHandles
{
TOP = 0x01,
@@ -233,13 +292,23 @@ class Window : public gcn::Window
static WindowContainer *windowContainer;
private:
+ /**
+ * Determines if the mouse is in a resize area and returns appropriate
+ * resize handles. Also initializes drag offset in case the resize
+ * grip is used.
+ *
+ * @see ResizeHandles
+ */
+ int getResizeHandles(gcn::MouseEvent &event);
+
GCContainer *mChrome; /**< Contained container */
ResizeGrip *mGrip; /**< Resize grip */
Window *mParent; /**< The parent window */
std::string mConfigName; /**< Name used for saving window-related data */
+ bool mShowTitle; /**< Window has a title bar */
bool mModal; /**< Window is modal */
bool mResizable; /**< Window can be resized */
- int mMouseResize; /**< Window is being resized */
+ bool mCloseButton; /**< Window has a close button */
bool mSticky; /**< Window resists minimization */
int mMinWinWidth; /**< Minimum window width */
int mMinWinHeight; /**< Minimum window height */
@@ -255,8 +324,10 @@ class Window : public gcn::Window
*/
static ConfigListener *windowConfigListener;
+ static int mouseResize; /**< Active resize handles */
static int instances; /**< Number of Window instances */
static ImageRect border; /**< The window border and background */
+ static Image *closeImage; /**< Close Button Image */
/**
* The width of the resize border. Is independent of the actual window
@@ -264,6 +335,14 @@ class Window : public gcn::Window
* where two borders are moved at the same time.
*/
static const int resizeBorderWidth = 10;
+
+ private:
+ /**
+ * Sends out a window event to the list of selection listeners.
+ */
+ void fireWindowEvent(const WindowEvent &event);
+
+ WindowListeners mListeners;
};
#endif
diff --git a/src/gui/windowlistener.h b/src/gui/windowlistener.h
new file mode 100644
index 00000000..08aab71d
--- /dev/null
+++ b/src/gui/windowlistener.h
@@ -0,0 +1,86 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#ifndef _TMW_WINDOW_LISTENER_H_
+#define _TMW_WINDOW_LISTENER_H_
+
+#include <guichan/widgets/window.hpp>
+#include <guichan/event.hpp>
+
+/**
+ * An event that characterizes a window move or resize.
+ *
+ * \ingroup GUI
+ */
+class WindowEvent : public gcn::Event
+{
+ public:
+ /**
+ * Constructor.
+ */
+ WindowEvent(gcn::Window *source, int type):
+ gcn::Event(source)
+ {
+ mType = type;
+ }
+
+ /**
+ * Returns the event type.
+ */
+ int getType() const
+ { return mType; }
+
+ enum WindowEventType
+ {
+ WINDOW_MOVED,
+ WINDOW_RESIZED
+ };
+};
+
+/**
+ * The listener that's notified when a window is moved or resized.
+ *
+ * \ingroup GUI
+ */
+class WindowListener
+{
+ public:
+ /**
+ * Virtual destructor.
+ */
+ virtual ~WindowListener() {}
+
+ /**
+ * Called whenever the window is moved.
+ */
+ virtual void windowMoved(const WindowEvent &event) {}
+
+ /**
+ * Called whenever the window is resized.
+ */
+ virtual void windowResized(const WindowEvent &event) {}
+};
+
+typedef std::list<WindowListener*> WindowListeners;
+
+#endif
diff --git a/src/imageparticle.cpp b/src/imageparticle.cpp
index 35cc21ad..17581a2a 100644
--- a/src/imageparticle.cpp
+++ b/src/imageparticle.cpp
@@ -31,12 +31,12 @@ ImageParticle::ImageParticle(Map *map, Image *image):
Particle(map),
mImage(image)
{
- mImage->incRef();
+ if (mImage) mImage->incRef();
}
ImageParticle::~ImageParticle()
{
- mImage->decRef();
+ if (mImage) mImage->decRef();
}
void ImageParticle::draw(Graphics *graphics, int offsetX, int offsetY) const
@@ -44,8 +44,8 @@ void ImageParticle::draw(Graphics *graphics, int offsetX, int offsetY) const
if (!mAlive)
return;
- int screenX = (int) mPosX + offsetX - mImage->getWidth() / 2;
- int screenY = (int) mPosY - (int) mPosZ + offsetY - mImage->getHeight()/2;
+ int screenX = (int) mPos.x + offsetX - mImage->getWidth() / 2;
+ int screenY = (int) mPos.y - (int)mPos.z + offsetY - mImage->getHeight()/2;
// Check if on screen
if (screenX + mImage->getWidth() < 0 ||
diff --git a/src/itemshortcut.cpp b/src/itemshortcut.cpp
new file mode 100644
index 00000000..8a514c7e
--- /dev/null
+++ b/src/itemshortcut.cpp
@@ -0,0 +1,87 @@
+/*
+ * The Mana World
+ * Copyright 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "itemshortcut.h"
+
+#include "localplayer.h"
+#include "configuration.h"
+
+#include "utils/tostring.h"
+
+ItemShortcut::ItemShortcut *itemShortcut;
+
+ItemShortcut::ItemShortcut():
+ mItemSelected(NULL)
+{
+ for (int i = 0; i < SHORTCUT_ITEMS; i++)
+ {
+ mItems[i] = NULL;
+ }
+}
+
+ItemShortcut::~ItemShortcut()
+{
+ save();
+}
+
+void ItemShortcut::load()
+{
+ for (int i = 0; i < SHORTCUT_ITEMS; i++)
+ {
+ int itemId = (int) config.getValue("itemShortcut" + toString(i), -1);
+
+ if (itemId != -1)
+ {
+ ItemPtr item = player_node->searchForItem(itemId);
+ if (item)
+ {
+ mItems[i] = item;
+ }
+ }
+ }
+}
+
+void ItemShortcut::save()
+{
+ for (int i = 0; i < SHORTCUT_ITEMS; i++)
+ {
+ if (mItems[i])
+ {
+ config.setValue("shortcut" + toString(i), mItems[i]->getId());
+ }
+ else
+ {
+ config.setValue("shortcut" + toString(i), -1);
+ }
+ }
+}
+
+void ItemShortcut::useItem(int index)
+{
+ if (mItems[index])
+ {
+ if (mItems[index]->getQuantity()) {
+ // TODO: Fix this (index vs. pointer mismatch)
+ //player_node->useItem(mItems[index]);
+ }
+ }
+}
diff --git a/src/itemshortcut.h b/src/itemshortcut.h
new file mode 100644
index 00000000..d211c7f3
--- /dev/null
+++ b/src/itemshortcut.h
@@ -0,0 +1,130 @@
+/*
+ * The Mana World
+ * Copyright 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _TMW_ITEMSHORTCUT_H__
+#define _TMW_ITEMSHORTCUT_H__
+
+#include "item.h"
+
+#define SHORTCUT_ITEMS 10
+
+/**
+ * The item pointer
+ */
+typedef Item* ItemPtr;
+
+class ItemShortcut
+{
+ public:
+ /**
+ * Constructor.
+ */
+ ItemShortcut();
+
+ /**
+ * Destructor.
+ */
+ ~ItemShortcut();
+
+ /**
+ * Load the configuration information.
+ */
+ void load();
+
+ /**
+ * Returns the shortcut item specified by the index.
+ *
+ * @param index Index of the shortcut item.
+ */
+ ItemPtr getItem(int index) const
+ { return mItems[index]; }
+
+ /**
+ * Returns the amount of shortcut items.
+ */
+ int getItemCount() const
+ { return SHORTCUT_ITEMS; }
+
+ /**
+ * Returns the item that is currently selected.
+ */
+ ItemPtr getItemSelected() const
+ { return mItemSelected; }
+
+ /**
+ * Adds the selected item to the items specified by the index.
+ *
+ * @param index Index of the items.
+ */
+ void setItem(int index)
+ { mItems[index] = mItemSelected; }
+
+ /**
+ * Adds an item to the items store specified by the index.
+ *
+ * @param index Index of the items.
+ * @param item Item to store.
+ */
+ void setItems(int index, Item *item)
+ { mItems[index] = item; }
+
+ /**
+ * Set the item that is selected.
+ *
+ * @param item The item that is to be assigned.
+ */
+ void setItemSelected(ItemPtr item)
+ { mItemSelected = item; }
+
+ /**
+ * A flag to check if the item is selected.
+ */
+ bool isItemSelected()
+ { return (mItemSelected) ? true : false; }
+
+ /**
+ * Remove a item from the shortcut.
+ */
+ void removeItem(int index)
+ { mItems[index] = NULL; }
+
+ /**
+ * Try to use the item specified by the index.
+ *
+ * @param index Index of the item shortcut.
+ */
+ void useItem(int index);
+
+ private:
+ /**
+ * Save the configuration information.
+ */
+ void save();
+
+ ItemPtr mItems[SHORTCUT_ITEMS]; /**< the items stored */
+ ItemPtr mItemSelected; /**< the item held by cursor */
+
+};
+
+extern ItemShortcut *itemShortcut;
+
+#endif
diff --git a/src/keyboardconfig.cpp b/src/keyboardconfig.cpp
new file mode 100644
index 00000000..271961c8
--- /dev/null
+++ b/src/keyboardconfig.cpp
@@ -0,0 +1,144 @@
+/*
+ * The Mana World
+ * Copyright 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "keyboardconfig.h"
+#include "configuration.h"
+#include "log.h"
+
+#include <guichan/sdl/sdlinput.hpp>
+
+#include "gui/setup_keyboard.h"
+
+struct KeyData
+{
+ const char *configField;
+ int defaultValue;
+ const char *caption;
+};
+
+// keyData must be in same order as enum keyAction.
+static KeyData const keyData[KeyboardConfig::KEY_TOTAL] = {
+ {"keyMoveUp", SDLK_UP, "Move Up"},
+ {"keyMoveDown", SDLK_DOWN, "Move Down"},
+ {"keyMoveLeft", SDLK_LEFT, "Move Left"},
+ {"keyMoveRight", SDLK_RIGHT, "Move Right"},
+ {"keyAttack", SDLK_LCTRL, "Attack"},
+ {"keyTarget", SDLK_LSHIFT, "Target"},
+ {"keyTargetClosest", SDLK_a, "Target Closest"},
+ {"keyPickup", SDLK_z, "Pickup"},
+ {"keyHideWindows", SDLK_h, "Hide Windows"},
+ {"keyBeingSit", SDLK_s, "Sit"},
+ {"keyShortcut0", SDLK_0, "Item Shortcut 0"},
+ {"keyShortcut1", SDLK_1, "Item Shortcut 1"},
+ {"keyShortcut2", SDLK_2, "Item Shortcut 2"},
+ {"keyShortcut3", SDLK_3, "Item Shortcut 3"},
+ {"keyShortcut4", SDLK_4, "Item Shortcut 4"},
+ {"keyShortcut5", SDLK_5, "Item Shortcut 5"},
+ {"keyShortcut6", SDLK_6, "Item Shortcut 6"},
+ {"keyShortcut7", SDLK_7, "Item Shortcut 7"},
+ {"keyShortcut8", SDLK_8, "Item Shortcut 8"},
+ {"keyShortcut9", SDLK_9, "Item Shortcut 9"}
+};
+
+void KeyboardConfig::init()
+{
+ for (int i = 0; i < KEY_TOTAL; i++)
+ {
+ mKey[i].configField = keyData[i].configField;
+ mKey[i].defaultValue = keyData[i].defaultValue;
+ mKey[i].caption = keyData[i].caption;
+ mKey[i].value = KEY_NO_VALUE;
+ }
+ mNewKeyIndex = KEY_NO_VALUE;
+ mEnabled = true;
+
+ retrieve();
+}
+
+void KeyboardConfig::retrieve()
+{
+ for (int i = 0; i < KEY_TOTAL; i++)
+ {
+ mKey[i].value = (int) config.getValue(
+ mKey[i].configField, mKey[i].defaultValue);
+ }
+}
+
+void KeyboardConfig::store()
+{
+ for (int i = 0; i < KEY_TOTAL; i++)
+ {
+ config.setValue(mKey[i].configField, mKey[i].value);
+ }
+}
+
+void KeyboardConfig::makeDefault()
+{
+ for (int i = 0; i < KEY_TOTAL; i++)
+ {
+ mKey[i].value = mKey[i].defaultValue;
+ }
+}
+
+bool KeyboardConfig::hasConflicts()
+{
+ int i, j;
+ for (i = 0; i < KEY_TOTAL; i++)
+ {
+ for (j = 0; j < KEY_TOTAL; j++)
+ {
+ if (i != j && mKey[i].value == mKey[j].value)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void KeyboardConfig::callbackNewKey()
+{
+ mSetupKey->newKeyCallback(mNewKeyIndex);
+}
+
+int KeyboardConfig::getKeyIndex(int keyValue) const
+{
+ for (int i = 0; i < KEY_TOTAL; i++)
+ {
+ if(keyValue == mKey[i].value)
+ {
+ return i;
+ }
+ }
+ return KEY_NO_VALUE;
+}
+
+bool KeyboardConfig::isKeyActive(int index)
+{
+ return mActiveKeys[ mKey[index].value];
+}
+
+void KeyboardConfig::refreshActiveKeys()
+{
+ mActiveKeys = SDL_GetKeyState(NULL);
+}
diff --git a/src/keyboardconfig.h b/src/keyboardconfig.h
new file mode 100644
index 00000000..46394fa5
--- /dev/null
+++ b/src/keyboardconfig.h
@@ -0,0 +1,185 @@
+/*
+ * The Mana World
+ * Copyright 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#ifndef _TMW_KEYBOARDCONFIG_H
+#define _TMW_KEYBOARDCONFIG_H
+
+#include <string>
+
+#include "gui/setup_keyboard.h"
+
+#include <guichan/sdl/sdlinput.hpp>
+
+/**
+ * Each key represents a key function. Such as 'Move up', 'Attack' etc.
+ */
+struct KeyFunction
+{
+ const char* configField; /** Field index that is in the config file. */
+ int defaultValue; /** The default key value used. */
+ std::string caption; /** The caption value for the key function. */
+ int value; /** The actual value that is used. */
+};
+
+class KeyboardConfig
+{
+ public:
+ /**
+ * Initializes the keyboard config explicitly.
+ */
+ void init();
+
+ /**
+ * Retrieve the key values from config file.
+ */
+ void retrieve();
+
+ /**
+ * Store the key values to config file.
+ */
+ void store();
+
+ /**
+ * Make the keys their default values.
+ */
+ void makeDefault();
+
+ /**
+ * Determines if any key assignments are the same as each other.
+ */
+ bool hasConflicts();
+
+ /**
+ * Calls a function back so the key re-assignment(s) can be seen.
+ */
+ void callbackNewKey();
+
+ /**
+ * Obtain the value stored in memory.
+ */
+ int getKeyValue(int index) const
+ { return mKey[index].value; }
+
+ /**
+ * Get the index of the new key to be assigned.
+ */
+ int getNewKeyIndex() const
+ { return mNewKeyIndex; }
+
+ /**
+ * Get the enable flag, which will stop the user from doing actions.
+ */
+ bool isEnabled() const
+ { return mEnabled; }
+
+ /**
+ * Get the key caption, providing more meaning to the user.
+ */
+ const std::string &getKeyCaption(int index) const
+ { return mKey[index].caption; }
+
+ /**
+ * Get the key function index by providing the keys value.
+ */
+ int getKeyIndex(int keyValue) const;
+
+ /**
+ * Set the enable flag, which will stop the user from doing actions.
+ */
+ void setEnabled(bool flag)
+ { mEnabled = flag; }
+
+ /**
+ * Set the index of the new key to be assigned.
+ */
+ void setNewKeyIndex(int value)
+ { mNewKeyIndex = value; }
+
+ /**
+ * Set the value of the new key.
+ */
+ void setNewKey(int value)
+ { mKey[mNewKeyIndex].value = value; }
+
+ /**
+ * Set a reference to the key setup window.
+ */
+ void setSetupKeyboard(Setup_Keyboard *setupKey)
+ { mSetupKey = setupKey; }
+
+ /**
+ * Checks if the key is active, by providing the key function index.
+ */
+ bool isKeyActive(int index);
+
+ /**
+ * Takes a snapshot of all the active keys.
+ */
+ void refreshActiveKeys();
+
+ /**
+ * All the key functions.
+ * KEY_NO_VALUE is used in initialization, and should be unchanged.
+ * KEY_TOTAL should always be last (used as a conditional in loops).
+ * The key assignment view gets arranged according to the order of
+ * these values.
+ */
+ enum KeyAction {
+ KEY_NO_VALUE = -1,
+ KEY_MOVE_UP,
+ KEY_MOVE_DOWN,
+ KEY_MOVE_LEFT,
+ KEY_MOVE_RIGHT,
+ KEY_ATTACK,
+ KEY_TARGET,
+ KEY_TARGET_CLOSEST,
+ KEY_PICKUP,
+ KEY_HIDE_WINDOWS,
+ KEY_SIT,
+ KEY_SHORTCUT_0,
+ KEY_SHORTCUT_1,
+ KEY_SHORTCUT_2,
+ KEY_SHORTCUT_3,
+ KEY_SHORTCUT_4,
+ KEY_SHORTCUT_5,
+ KEY_SHORTCUT_6,
+ KEY_SHORTCUT_7,
+ KEY_SHORTCUT_8,
+ KEY_SHORTCUT_9,
+ KEY_TOTAL
+ };
+
+ private:
+ int mNewKeyIndex; /**< Index of new key to be assigned */
+ bool mEnabled; /**< Flag to respond to key input */
+
+ Setup_Keyboard *mSetupKey; /**< Reference to setup window */
+
+ KeyFunction mKey[KEY_TOTAL]; /**< Pointer to all the key data */
+
+ Uint8 *mActiveKeys; /**< Stores a list of all the keys */
+};
+
+extern KeyboardConfig keyboard;
+
+#endif
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index 95e7a478..f4ad7587 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -29,11 +29,19 @@
#include "inventory.h"
#include "item.h"
#include "main.h"
+#include "particle.h"
#include "sound.h"
#include "log.h"
#include "net/gameserver/player.h"
+#include "gui/gui.h"
+
+#include "net/messageout.h"
+#include "net/protocol.h"
+
+#include "utils/tostring.h"
+
LocalPlayer *player_node = NULL;
LocalPlayer::LocalPlayer():
@@ -46,6 +54,7 @@ LocalPlayer::LocalPlayer():
mLevel(1), mMoney(0),
mTotalWeight(1), mMaxWeight(1),
mHP(1), mMaxHP(1),
+ mXp(0),
mTarget(NULL), mPickUpTarget(NULL),
mTrading(false),
mLastAction(-1), mWalkingDir(0),
@@ -112,6 +121,17 @@ LocalPlayer::moveInvItem(Item *item, int newIndex)
item->getInvIndex(), newIndex, item->getQuantity());
}
+Item* LocalPlayer::searchForItem(int itemId)
+{
+ for (int i = 0; i < INVENTORY_SIZE; i++)
+ {
+ if (itemId == mInventory->getItem(i)->getId()) {
+ return mInventory->getItem(i);
+ }
+ }
+ return NULL;
+}
+
void LocalPlayer::equipItem(Item *item)
{
Net::GameServer::Player::equip(item->getInvIndex());
@@ -302,10 +322,14 @@ void LocalPlayer::attack()
setAction(ATTACK);
- if (getWeapon() == 2)
- sound.playSfx("sfx/bow_shoot_1.ogg");
- else
+ if (mEquippedWeapon)
+ {
+ std::string soundFile = mEquippedWeapon->getSound(EQUIP_EVENT_STRIKE);
+ if (soundFile != "") sound.playSfx(soundFile);
+ }
+ else {
sound.playSfx("sfx/fist-swish.ogg");
+ }
Net::GameServer::Player::attack(getSpriteDirection());
}
@@ -329,3 +353,16 @@ void LocalPlayer::raiseAttribute(size_t attr)
mAttributeBase.at(attr)++;
// TODO: Inform the server about our desire to raise the attribute
}
+
+void LocalPlayer::setXp(int xp)
+{
+ if (mMap && xp > mXp)
+ {
+ const std::string text = toString(xp - mXp) + " xp";
+
+ // Show XP number
+ particleEngine->addTextRiseFadeOutEffect(text, hitYellowFont,
+ mPx + 16, mPy - 16);
+ }
+ mXp = xp;
+}
diff --git a/src/localplayer.h b/src/localplayer.h
index 4f38fdad..ff7bf0b7 100644
--- a/src/localplayer.h
+++ b/src/localplayer.h
@@ -152,6 +152,14 @@ class LocalPlayer : public Player
void moveInvItem(Item *item, int newIndex);
/**
+ * Searches for the specified item by it's identification.
+ *
+ * @param itemId The id of the item to be searched.
+ * @return Item found on success, NULL on failure.
+ */
+ Item* searchForItem(int itemId);
+
+ /**
* Equips an item.
*/
void equipItem(Item *item);
@@ -237,6 +245,19 @@ class LocalPlayer : public Player
int getHP() const
{ return mHP; }
+ /**
+ * Sets the amount of XP. Shows XP gaining effect if the player is on
+ * a map.
+ */
+ void setXp(int xp);
+
+ /**
+ * Returns the amount of experience points.
+ */
+ int getXp() const { return mXp; }
+
+ Uint32 mCharId;
+
int getMaxHP() const
{ return mMaxHP; }
@@ -298,6 +319,7 @@ class LocalPlayer : public Player
int mMaxWeight;
int mHP;
int mMaxHP;
+ int mXp; /**< Experience points. */
Being *mTarget;
FloorItem *mPickUpTarget;
diff --git a/src/main.cpp b/src/main.cpp
index 1f4eafde..30fb7c1c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -48,8 +48,10 @@
#endif
#include "configuration.h"
+#include "keyboardconfig.h"
#include "game.h"
#include "graphics.h"
+#include "itemshortcut.h"
#include "lockedarray.h"
#include "localplayer.h"
#include "log.h"
@@ -84,7 +86,6 @@
#include "net/gameserver/gameserver.h"
-#include "resources/equipmentdb.h"
#include "resources/image.h"
#include "resources/itemdb.h"
#include "resources/monsterdb.h"
@@ -108,6 +109,7 @@ Music *bgm;
Configuration config; /**< XML file configuration reader */
Logger *logger; /**< Log object */
+KeyboardConfig keyboard;
Net::Connection *accountServerConnection = 0;
Net::Connection *gameServerConnection = 0;
@@ -189,7 +191,6 @@ void initConfiguration(const Options &options)
config.setValue("fpslimit", 0);
config.setValue("updatehost", "http://updates.themanaworld.org");
config.setValue("customcursor", 1);
- config.setValue("homeDir", homeDir);
// Checking if the configuration file exists... otherwise create it with
// default options.
@@ -319,6 +320,9 @@ void initEngine()
// Initialize for drawing
graphics->_beginDraw();
+ // Initialize the item shortcuts.
+ itemShortcut = new ItemShortcut();
+
gui = new Gui(graphics);
state = STATE_CHOOSE_SERVER; /**< Initial game state */
@@ -337,12 +341,19 @@ void initEngine()
errorMessage = err;
logger->log("Warning: %s", err);
}
+
+ // Initialize keyboard
+ keyboard.init();
}
/** Clear the engine */
void exit_engine()
{
+ // Before config.write() since it writes the shortcuts to the config
+ delete itemShortcut;
+
config.write();
+
delete gui;
delete graphics;
@@ -353,7 +364,6 @@ void exit_engine()
sound.close();
// Unload XML databases
- EquipmentDB::unload();
ItemDB::unload();
MonsterDB::unload();
@@ -457,7 +467,6 @@ void loadUpdates()
const std::string updatesFile = "updates/resources2.txt";
ResourceManager *resman = ResourceManager::getInstance();
std::vector<std::string> lines = resman->loadTextFile(updatesFile);
- std::string homeDir = config.getValue("homeDir", "");
for (unsigned int i = 0; i < lines.size(); ++i)
{
@@ -895,7 +904,6 @@ int main(int argc, char *argv[])
false);
// Load XML databases
- EquipmentDB::load();
ItemDB::load();
MonsterDB::load();
state = STATE_LOGIN;
@@ -1039,7 +1047,6 @@ int main(int argc, char *argv[])
}
}
}
-
}
catch (...)
{
diff --git a/src/monster.cpp b/src/monster.cpp
index 768bf16a..2522a3e1 100644
--- a/src/monster.cpp
+++ b/src/monster.cpp
@@ -57,7 +57,7 @@ Monster::setAction(Action action)
break;
case DEAD:
currentAction = ACTION_DEAD;
- sound.playSfx(getInfo().getSound(EVENT_DIE));
+ sound.playSfx(getInfo().getSound(MONSTER_EVENT_DIE));
break;
case ATTACK:
currentAction = ACTION_ATTACK;
@@ -87,10 +87,10 @@ Monster::handleAttack()
const MonsterInfo &mi = getInfo();
- // TODO: It's not possible to determine hit or miss here, so this stuff probably needs
- // to be moved somewhere else. We may lose synchronization between attack animation and
- // the sound, unless we adapt the protocol...
- sound.playSfx(mi.getSound(EVENT_HIT));
+ // TODO: It's not possible to determine hit or miss here, so this stuff
+ // probably needs to be moved somewhere else. We may lose synchronization
+ // between attack animation and the sound, unless we adapt the protocol...
+ sound.playSfx(mi.getSound(MONSTER_EVENT_HIT));
}
Being::TargetCursorSize
diff --git a/src/net/beinghandler.cpp b/src/net/beinghandler.cpp
index 87972212..b88d443e 100644
--- a/src/net/beinghandler.cpp
+++ b/src/net/beinghandler.cpp
@@ -114,7 +114,7 @@ void BeingHandler::handleMessage(MessageIn &msg)
dstBeing = beingManager->findBeing(id);
- if (dstBeing == NULL)
+ if (!dstBeing)
{
// Being with id >= 110000000 and job 0 are better
// known as ghosts, so don't create those.
@@ -138,30 +138,32 @@ void BeingHandler::handleMessage(MessageIn &msg)
dstBeing->setWalkSpeed(speed);
dstBeing->mJob = job;
- dstBeing->setHairStyle(msg.readShort());
- dstBeing->setWeapon(msg.readShort());
+ dstBeing->setHairStyle(msg->readShort());
+ dstBeing->setVisibleEquipment(
+ Being::WEAPON_SPRITE, msg->readShort());
dstBeing->setVisibleEquipment(
- Being::BOTTOMCLOTHES_SPRITE, msg.readShort());
+ Being::BOTTOMCLOTHES_SPRITE, msg->readShort());
if (msg.getId() == SMSG_BEING_MOVE)
{
msg.readLong(); // server tick
}
- msg.readShort(); // shield
- dstBeing->setVisibleEquipment(Being::HAIT_SPRITE, msg.readShort());
- dstBeing->setVisibleEquipment(
- Being::TOPCLOTHES_SPRITE, msg.readShort());
- dstBeing->setHairColor(msg.readShort());
- msg.readShort(); // unknown
- msg.readShort(); // head dir
- msg.readShort(); // guild
- msg.readShort(); // unknown
- msg.readShort(); // unknown
- msg.readShort(); // manner
- msg.readShort(); // karma
- msg.readByte(); // unknown
- dstBeing->setSex(1 - msg.readByte()); // sex
+ msg->readShort(); // shield
+ headTop = msg->readShort();
+ headMid = msg->readShort();
+ dstBeing->setVisibleEquipment(Being::HAT_SPRITE, headTop);
+ dstBeing->setVisibleEquipment(Being::TOPCLOTHES_SPRITE, headMid);
+ dstBeing->setHairColor(msg->readShort());
+ msg->readShort(); // unknown
+ msg->readShort(); // head dir
+ msg->readShort(); // guild
+ msg->readShort(); // unknown
+ msg->readShort(); // unknown
+ msg->readShort(); // manner
+ msg->readShort(); // karma
+ msg->readByte(); // unknown
+ dstBeing->setSex(1 - msg->readByte()); // sex
if (msg.getId() == SMSG_BEING_MOVE)
{
@@ -256,10 +258,12 @@ void BeingHandler::handleMessage(MessageIn &msg)
}
Particle *levelupFX;
if (msg->readLong() == 0) { // type
- levelupFX = particleEngine->addEffect("graphics/particles/levelup.particle.xml", 0, 0);
+ levelupFX = particleEngine->addEffect(
+ "graphics/particles/levelup.particle.xml", 0, 0);
}
else {
- levelupFX = particleEngine->addEffect("graphics/particles/skillup.particle.xml", 0, 0);
+ levelupFX = particleEngine->addEffect(
+ "graphics/particles/skillup.particle.xml", 0, 0);
}
beingManager->findBeing(id)->controlParticle(levelupFX);
break;
@@ -289,28 +293,26 @@ void BeingHandler::handleMessage(MessageIn &msg)
dstBeing->setHairStyle(id);
break;
case 2:
- dstBeing->setWeapon(id);
+ dstBeing->setVisibleEquipment(Being::WEAPON_SPRITE, id);
break;
case 3: // Change lower headgear for eAthena, pants for us
dstBeing->setVisibleEquipment(
- Being::BOTTOMCLOTHES_SPRITE,
- id);
+ Being::BOTTOMCLOTHES_SPRITE, id);
break;
case 4: // Change upper headgear for eAthena, hat for us
dstBeing->setVisibleEquipment(
- Being::HAT_SPRITE,
- id);
+ Being::HAT_SPRITE, id);
break;
case 5: // Change middle headgear for eathena, armor for us
dstBeing->setVisibleEquipment(
- Being::TOPCLOTHES_SPRITE,
- id);
+ Being::TOPCLOTHES_SPRITE, id);
break;
case 6:
dstBeing->setHairColor(id);
break;
default:
- logger->log("c3: %i\n", id); // unsupported
+ logger->log("SMSG_BEING_CHANGE_LOOKS: unsupported type: "
+ "%d, id: %d", type, id);
break;
}
}
@@ -336,17 +338,18 @@ void BeingHandler::handleMessage(MessageIn &msg)
dstBeing = beingManager->findBeing(id);
- if (dstBeing == NULL)
+ if (!dstBeing)
{
dstBeing = beingManager->createBeing(id, job);
}
dstBeing->setWalkSpeed(speed);
dstBeing->mJob = job;
- dstBeing->setHairStyle(msg.readShort());
- dstBeing->setWeaponById(msg.readShort()); // item id 1
- msg.readShort(); // item id 2
- headBottom = msg.readShort();
+ dstBeing->setHairStyle(msg->readShort());
+ dstBeing->setVisibleEquipment(
+ Being::WEAPON_SPRITE, msg->readShort());
+ msg->readShort(); // item id 2
+ headBottom = msg->readShort();
if (msg.getId() == SMSG_PLAYER_MOVE)
{
@@ -407,9 +410,9 @@ void BeingHandler::handleMessage(MessageIn &msg)
case 0x0119:
// Change in players look
- logger->log("0x0119 %li %i %i %x %i\n", msg.readLong(),
- msg.readShort(), msg.readShort(), msg.readShort(),
- msg.readByte());
+ logger->log("0x0119 %i %i %i %x %i", msg->readLong(),
+ msg->readShort(), msg->readShort(), msg->readShort(),
+ msg->readByte());
break;
*/
}
@@ -428,11 +431,9 @@ static void handleLooks(Being *being, MessageIn &msg)
if (mask & (1 << 7))
{
// The equipment has to be cleared first.
- being->setWeaponById(0);
for (int i = 0; i < nb_slots; ++i)
{
- if (slots[i] != Being::WEAPON_SPRITE)
- being->setVisibleEquipment(slots[i], 0);
+ being->setVisibleEquipment(slots[i], 0);
}
}
@@ -441,10 +442,7 @@ static void handleLooks(Being *being, MessageIn &msg)
{
if (!(mask & (1 << i))) continue;
int id = msg.readShort();
- if (slots[i] != Being::WEAPON_SPRITE)
- being->setVisibleEquipment(slots[i], id);
- else
- being->setWeaponById(id);
+ being->setVisibleEquipment(slots[i], id);
}
}
diff --git a/src/net/chathandler.cpp b/src/net/chathandler.cpp
index 3efe3174..afdc2ab5 100644
--- a/src/net/chathandler.cpp
+++ b/src/net/chathandler.cpp
@@ -37,6 +37,7 @@
#include "../gui/chat.h"
#include "../utils/tostring.h"
+#include "../utils/trim.h"
extern Being *player_node;
@@ -167,6 +168,7 @@ void ChatHandler::handleMessage(MessageIn &msg)
chatMsg = msg.readString(chatMsgLength);
chatWindow->chatLog(chatMsg, BY_OTHER);
chatMsg.erase(0, chatMsg.find(" : ", 0) + 3);
+ trim(chatMsg);
being->setSpeech(chatMsg, SPEECH_TIME);
break;
diff --git a/src/net/inventoryhandler.cpp b/src/net/inventoryhandler.cpp
index 354dd685..de74e8f5 100644
--- a/src/net/inventoryhandler.cpp
+++ b/src/net/inventoryhandler.cpp
@@ -31,6 +31,7 @@
#include "../equipment.h"
#include "../inventory.h"
#include "../item.h"
+#include "../itemshortcut.h"
#include "../localplayer.h"
#include "../gui/chat.h"
@@ -77,6 +78,7 @@ void InventoryHandler::handleMessage(MessageIn &msg)
it->setQuantity(amount);
}
};
+ itemShortcut->load();
break;
}
}
diff --git a/src/net/playerhandler.cpp b/src/net/playerhandler.cpp
index b94b5128..afaeca69 100644
--- a/src/net/playerhandler.cpp
+++ b/src/net/playerhandler.cpp
@@ -133,7 +133,8 @@ void PlayerHandler::handleMessage(MessageIn &msg)
}
else
{
- logger->log("Warning: server wants to update unknown attribute %d to %d", stat, value);
+ logger->log("Warning: server wants to update unknown "
+ "attribute %d to %d", stat, value);
}
}
} break;
diff --git a/src/particle.cpp b/src/particle.cpp
index 805da102..148bbf6f 100644
--- a/src/particle.cpp
+++ b/src/particle.cpp
@@ -52,14 +52,12 @@ const float Particle::PARTICLE_SKY = 800.0f;
Particle::Particle(Map *map):
mAlive(true),
- mPosX(0.0f), mPosY(0.0f), mPosZ(0.0f),
mLifetimeLeft(-1),
mLifetimePast(0),
mFadeOut(0),
mFadeIn(0),
mAutoDelete(true),
mMap(map),
- mVectorX(0.0f), mVectorY(0.0f), mVectorZ(0.0f),
mGravity(0.0f),
mRandomnes(0),
mBounce(0.0f),
@@ -109,7 +107,7 @@ Particle::update()
p++
)
{
- (*p)->moveBy(mPosX, mPosY, mPosZ);
+ (*p)->moveBy(mPos.x, mPos.y, mPos.z);
mChildParticles.push_back (*p);
}
}
@@ -117,31 +115,28 @@ Particle::update()
if (mMomentum != 1.0f)
{
- mVectorX *= mMomentum;
- mVectorY *= mMomentum;
- mVectorZ *= mMomentum;
+ mVelocity *= mMomentum;
}
if (mTarget && mAcceleration != 0.0f)
{
- float distX = (mPosX - mTarget->getPosX()) * SIN45;
- float distY = mPosY - mTarget->getPosY();
- float distZ = mPosZ - mTarget->getPosZ();
+ Vector dist = mPos - mTarget->getPosition();
+ dist.x *= SIN45;
float invHypotenuse;
- switch(Particle::fastPhysics)
+ switch (Particle::fastPhysics)
{
case 1:
invHypotenuse = fastInvSqrt(
- distX * distX + distY * distY + distZ * distZ);
+ dist.x * dist.x + dist.y * dist.y + dist.z * dist.z);
break;
case 2:
invHypotenuse = 2.0f /
- fabs(distX) + fabs(distY) + fabs(distZ);
+ fabs(dist.x) + fabs(dist.y) + fabs(dist.z);
break;
default:
invHypotenuse = 1.0f / sqrt(
- distX * distX + distY * distY + distZ * distZ);
+ dist.x * dist.x + dist.y * dist.y + dist.z * dist.z);
break;
}
@@ -152,25 +147,23 @@ Particle::update()
mAlive = false;
}
float accFactor = invHypotenuse * mAcceleration;
- mVectorX -= distX * accFactor;
- mVectorY -= distY * accFactor;
- mVectorZ -= distZ * accFactor;
+ mVelocity -= dist * accFactor;
}
}
if (mRandomnes > 0)
{
- mVectorX += (rand()%mRandomnes - rand()%mRandomnes) / 1000.0f;
- mVectorY += (rand()%mRandomnes - rand()%mRandomnes) / 1000.0f;
- mVectorZ += (rand()%mRandomnes - rand()%mRandomnes) / 1000.0f;
+ mVelocity.x += (rand()%mRandomnes - rand()%mRandomnes) / 1000.0f;
+ mVelocity.y += (rand()%mRandomnes - rand()%mRandomnes) / 1000.0f;
+ mVelocity.z += (rand()%mRandomnes - rand()%mRandomnes) / 1000.0f;
}
- mVectorZ -= mGravity;
+ mVelocity.z -= mGravity;
// Update position
- mPosX += mVectorX;
- mPosY += mVectorY * SIN45;
- mPosZ += mVectorZ * SIN45;
+ mPos.x += mVelocity.x;
+ mPos.y += mVelocity.y * SIN45;
+ mPos.z += mVelocity.z * SIN45;
// Update other stuff
if (mLifetimeLeft > 0)
@@ -179,14 +172,13 @@ Particle::update()
}
mLifetimePast++;
- if (mPosZ > PARTICLE_SKY || mPosZ < 0.0f)
+ if (mPos.z > PARTICLE_SKY || mPos.z < 0.0f)
{
if (mBounce > 0.0f)
{
- mPosZ *= -mBounce;
- mVectorX *= mBounce;
- mVectorY *= mBounce;
- mVectorZ *= -mBounce;
+ mPos.z *= -mBounce;
+ mVelocity *= mBounce;
+ mVelocity.z = -mVelocity.z;
}
else {
mAlive = false;
@@ -195,10 +187,8 @@ Particle::update()
}
// Update child particles
- for ( ParticleIterator p = mChildParticles.begin();
- p != mChildParticles.end();
-
- )
+ for (ParticleIterator p = mChildParticles.begin();
+ p != mChildParticles.end();)
{
if ((*p)->update())
{
@@ -217,14 +207,9 @@ Particle::update()
return true;
}
-
-void Particle::draw(Graphics *graphics, int offsetX, int offsetY) const
-{
-}
-
-
Particle*
-Particle::addEffect(std::string particleEffectFile, int pixelX, int pixelY)
+Particle::addEffect(const std::string &particleEffectFile,
+ int pixelX, int pixelY)
{
Particle *newParticle = NULL;
@@ -289,9 +274,9 @@ Particle::addEffect(std::string particleEffectFile, int pixelX, int pixelY)
int offsetY = XML::getProperty(effectChildNode, "position-y", 0);
int offsetZ = XML::getProperty(effectChildNode, "position-z", 0);
- int particleX = (int)mPosX + pixelX + offsetX;
- int particleY = (int)mPosY + pixelY + offsetY;
- int particleZ = (int)mPosZ + offsetZ;
+ int particleX = (int) mPos.x + pixelX + offsetX;
+ int particleY = (int) mPos.y + pixelY + offsetY;
+ int particleZ = (int) mPos.z + offsetZ;
int lifetime = XML::getProperty(effectChildNode, "lifetime", -1);
@@ -317,17 +302,16 @@ Particle::addEffect(std::string particleEffectFile, int pixelX, int pixelY)
Particle*
-Particle::addTextSplashEffect(std::string text,
+Particle::addTextSplashEffect(const std::string &text,
int colorR, int colorG, int colorB,
gcn::Font *font, int x, int y)
{
Particle *newParticle = new TextParticle(mMap, text, colorR, colorG, colorB,
font);
newParticle->setPosition(x, y, 0);
- newParticle->setVector ( ((rand()%100) - 50) / 200.0f, // X vector
- ((rand()%100) - 50) / 200.0f, // Y vector
- ((rand()%100) / 200.0f) + 4.0f // Z vector
- );
+ newParticle->setVelocity(((rand() % 100) - 50) / 200.0f, // X
+ ((rand() % 100) - 50) / 200.0f, // Y
+ ((rand() % 100) / 200.0f) + 4.0f); // Z
newParticle->setGravity(0.1f);
newParticle->setBounce(0.5f);
newParticle->setLifetime(200);
@@ -338,14 +322,28 @@ Particle::addTextSplashEffect(std::string text,
return newParticle;
}
+Particle*
+Particle::addTextRiseFadeOutEffect(const std::string &text, gcn::Font *font,
+ int x, int y)
+{
+ Particle *newParticle = new TextParticle(mMap, text, 255, 255, 255, font);
+ newParticle->setPosition(x, y, 0);
+ newParticle->setVelocity(0.0f, 0.0f, 0.5f);
+ newParticle->setGravity(0.0015f);
+ newParticle->setLifetime(300);
+ newParticle->setFadeOut(50);
+ newParticle->setFadeIn(200);
+
+ mChildParticles.push_back(newParticle);
+
+ return newParticle;
+}
void
Particle::setMap(Map *map)
{
mMap = map;
if (mMap) setSpriteIterator(mMap->addSprite(this));
-
- // TODO: Create map emitters based on emitter data in map data
}
diff --git a/src/particle.h b/src/particle.h
index 9e9223c7..dd7c5ee2 100644
--- a/src/particle.h
+++ b/src/particle.h
@@ -31,7 +31,7 @@
#include "guichanfwd.h"
#include "sprite.h"
-
+#include "vector.h"
class Map;
class Particle;
@@ -67,43 +67,37 @@ class Particle : public Sprite
~Particle();
/**
- * Deletes all child particles and emitters
+ * Deletes all child particles and emitters.
*/
void
clear();
/**
* Gives a particle the properties of an engine root particle and loads
- * the particle-related config settings
+ * the particle-related config settings.
*/
void
setupEngine();
/**
* Updates particle position, returns false when the particle should
- * be deleted
+ * be deleted.
*/
virtual bool
update();
/**
- * Draws the particle image
+ * Draws the particle image.
*/
virtual void
- draw(Graphics *graphics, int offsetX, int offsetY) const;
+ draw(Graphics *graphics, int offsetX, int offsetY) const {}
/**
- * Necessary for sorting with the other sprites
+ * Necessary for sorting with the other sprites.
*/
virtual int
getPixelY() const
- {
- return (int)(mPosY + mPosZ) - 64;
- };
-
- /*
- Basic Particle properties:
- */
+ { return (int) (mPos.y + mPos.z) - 64; }
/**
* Sets the map the particle is on.
@@ -115,16 +109,25 @@ class Particle : public Sprite
* particleEffectFile.
*/
Particle*
- addEffect(std::string particleEffectFile, int pixelX, int pixelY);
+ addEffect(const std::string &particleEffectFile,
+ int pixelX, int pixelY);
/**
* Creates a standalone text particle.
*/
Particle*
- addTextSplashEffect(std::string text, int colorR, int colorG, int colorB,
+ addTextSplashEffect(const std::string &text,
+ int colorR, int colorG, int colorB,
gcn::Font *font, int x, int y);
/**
+ * Creates a standalone text particle.
+ */
+ Particle*
+ addTextRiseFadeOutEffect(const std::string &text, gcn::Font *font,
+ int x, int y);
+
+ /**
* Adds an emitter to the particle.
*/
void
@@ -132,34 +135,31 @@ class Particle : public Sprite
{ mChildEmitters.push_back(emitter); }
/**
- * Sets the position in 3 dimensional space in pixels relative to map
+ * Sets the position in 3 dimensional space in pixels relative to map.
*/
void
setPosition(float x, float y, float z)
- { mPosX = x; mPosY = y; mPosZ = z; }
+ { mPos.x = x; mPos.y = y; mPos.z = z; }
/**
- * Sets the position in 2 dimensional space in pixels relative to map
+ * Sets the position in 2 dimensional space in pixels relative to map.
*/
void
setPosition(float x, float y)
- { mPosX = x; mPosY = y; }
-
- float getPosX() const
- { return mPosX; }
+ { mPos.x = x; mPos.y = y; }
- float getPosY() const
- { return mPosY; }
-
- float getPosZ() const
- { return mPosZ; }
+ /**
+ * Returns the particle position.
+ */
+ const Vector& getPosition() const
+ { return mPos; }
/**
* Changes the particle position relative
*/
void
moveBy(float x, float y, float z)
- { mPosX += x; mPosY += y; mPosZ += z; }
+ { mPos.x += x; mPos.y += y; mPos.z += z; }
/**
* Sets the time in game ticks until the particle is destroyed.
@@ -170,48 +170,48 @@ class Particle : public Sprite
/**
* Sets the age of the pixel in game ticks where the particle has
- * faded in completely
+ * faded in completely.
*/
void
- setFadeOut (int fadeOut)
+ setFadeOut(int fadeOut)
{ mFadeOut = fadeOut; }
/**
* Sets the remaining particle lifetime where the particle starts to
- * fade out
+ * fade out.
*/
void
- setFadeIn (int fadeIn)
+ setFadeIn(int fadeIn)
{ mFadeIn = fadeIn; }
/**
* Sets the sprite iterator of the particle on the current map to make
- * it easier to remove the particle from the map when it is destroyed
+ * it easier to remove the particle from the map when it is destroyed.
*/
void
setSpriteIterator(std::list<Sprite*>::iterator spriteIterator)
{ mSpriteIterator = spriteIterator; }
/**
- * Gets the sprite iterator of the particle on the current map
+ * Gets the sprite iterator of the particle on the current map.
*/
std::list<Sprite*>::iterator
getSpriteIterator() const
{ return mSpriteIterator; }
/**
- * Sets the current velocity in 3 dimensional space
+ * Sets the current velocity in 3 dimensional space.
*/
void
- setVector(float x, float y, float z)
- { mVectorX = x; mVectorY = y; mVectorZ = z; }
+ setVelocity(float x, float y, float z)
+ { mVelocity.x = x; mVelocity.y = y; mVelocity.z = z; }
/**
- * Sets the downward acceleration
+ * Sets the downward acceleration.
*/
void
- setGravity(float g)
- { mGravity = g; }
+ setGravity(float gravity)
+ { mGravity = gravity; }
/**
* Sets the ammount of random vector changes
@@ -237,8 +237,8 @@ class Particle : public Sprite
/**
* Sets the distance in pixel the particle can come near the target
- * particle before it is destroyed. Does only make sense after a
- * target particle has been set using setDestination.
+ * particle before it is destroyed. Does only make sense after a target
+ * particle has been set using setDestination.
*/
void setDieDistance(float dist)
{ mInvDieDistance = 1.0f / dist; }
@@ -247,7 +247,7 @@ class Particle : public Sprite
{ return mAlive; }
/**
- * Manually marks the particle for deletion
+ * Manually marks the particle for deletion.
*/
void kill()
{ mAlive = false; mAutoDelete = true; }
@@ -261,7 +261,7 @@ class Particle : public Sprite
protected:
bool mAlive; /**< Is the particle supposed to be drawn and updated?*/
- float mPosX, mPosY, mPosZ; /**< Position in 3 dimensonal space - pixel based relative to map */
+ Vector mPos; /**< Position in pixels relative to map. */
int mLifetimeLeft; /**< Lifetime left in game ticks*/
int mLifetimePast; /**< Age of the particle in game ticks*/
int mFadeOut; /**< Lifetime in game ticks left where fading out begins*/
@@ -269,17 +269,19 @@ class Particle : public Sprite
private:
// generic properties
- bool mAutoDelete; /**< May the particle request its deletion by the parent particle?*/
- Map *mMap; /**< Map the particle is on*/
+ bool mAutoDelete; /**< May the particle request its deletion by the parent particle? */
+ Map *mMap; /**< Map the particle is on. */
std::list<Sprite*>::iterator mSpriteIterator; /**< iterator of the particle on the current map */
- Emitters mChildEmitters; /**< List of child emitters*/
- Particles mChildParticles; /**< List of particles controlled by this particle*/
- //dynamic particle
- float mVectorX, mVectorY, mVectorZ; /**< Speed in 3 dimensional space in pixels per game-tick */
- float mGravity; /**< Downward acceleration in pixels per game-tick²*/
- int mRandomnes; /**< Ammount of random vector change*/
- float mBounce; /**< How much the particle bounces off when hitting the ground*/
- //follow-point particles
+ Emitters mChildEmitters; /**< List of child emitters. */
+ Particles mChildParticles; /**< List of particles controlled by this particle */
+
+ // dynamic particle
+ Vector mVelocity; /**< Speed in pixels per game-tick. */
+ float mGravity; /**< Downward acceleration in pixels per game-tick. */
+ int mRandomnes; /**< Ammount of random vector change */
+ float mBounce; /**< How much the particle bounces off when hitting the ground */
+
+ // follow-point particles
Particle *mTarget; /**< The particle that attracts this particle*/
float mAcceleration; /**< Acceleration towards the target particle in pixels per game-tick²*/
float mInvDieDistance; /**< Distance in pixels from the target particle that causes the destruction of the particle*/
diff --git a/src/particleemitter.cpp b/src/particleemitter.cpp
index 60a98cc5..035882b6 100644
--- a/src/particleemitter.cpp
+++ b/src/particleemitter.cpp
@@ -248,10 +248,9 @@ ParticleEmitter::readMinMax(xmlNodePtr propertyNode, T def)
{
MinMax<T> retval;
- def = (T)XML::getFloatProperty(propertyNode, "value", (double)def);
- retval.set ( (T)XML::getFloatProperty(propertyNode, "min", (double)def),
- (T)XML::getFloatProperty(propertyNode, "max", (double)def)
- );
+ def = (T) XML::getFloatProperty(propertyNode, "value", (double) def);
+ retval.set((T) XML::getFloatProperty(propertyNode, "min", (double) def),
+ (T) XML::getFloatProperty(propertyNode, "max", (double) def));
return retval;
}
@@ -284,19 +283,17 @@ ParticleEmitter::createParticles()
newParticle->setPosition(
- mParticlePosX.value(),
- mParticlePosY.value(),
- mParticlePosZ.value()
- );
+ mParticlePosX.value(),
+ mParticlePosY.value(),
+ mParticlePosZ.value());
float angleH = mParticleAngleHorizontal.value();
float angleV = mParticleAngleVertical.value();
float power = mParticlePower.value();
- newParticle->setVector(
- cos(angleH) * cos(angleV) * power,
- sin(angleH) * cos(angleV) * power,
- sin(angleV) * power
- );
+ newParticle->setVelocity(
+ cos(angleH) * cos(angleV) * power,
+ sin(angleH) * cos(angleV) * power,
+ sin(angleV) * power);
newParticle->setRandomnes(mParticleRandomnes.value());
newParticle->setGravity(mParticleGravity.value());
@@ -312,10 +309,9 @@ ParticleEmitter::createParticles()
newParticle->setFadeOut(mParticleFadeOut.value());
newParticle->setFadeIn(mParticleFadeIn.value());
- for ( std::list<ParticleEmitter>::iterator i = mParticleChildEmitters.begin();
- i != mParticleChildEmitters.end();
- i++
- )
+ for (std::list<ParticleEmitter>::iterator i = mParticleChildEmitters.begin();
+ i != mParticleChildEmitters.end();
+ i++)
{
newParticle->addEmitter(new ParticleEmitter(*i));
}
diff --git a/src/player.cpp b/src/player.cpp
index d3c27aa0..b63dcd5b 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -28,7 +28,8 @@
#include "graphics.h"
#include "log.h"
-#include "resources/equipmentdb.h"
+#include "resources/itemdb.h"
+#include "resources/iteminfo.h"
#include "utils/tostring.h"
@@ -37,7 +38,6 @@
Player::Player(Uint16 id, Uint16 job, Map *map):
Being(id, job, map)
{
- setWeapon(0);
}
Being::Type
@@ -93,8 +93,8 @@ Player::setSex(Uint8 sex)
if (i != HAIR_SPRITE && mEquipmentSpriteIDs.at(i) != 0)
{
AnimatedSprite *newEqSprite = new AnimatedSprite(
- "graphics/sprites/" + EquipmentDB::get(
- mEquipmentSpriteIDs.at(i))->getSprite(sex));
+ "graphics/sprites/" + ItemDB::get(
+ mEquipmentSpriteIDs.at(i)).getSprite(sex));
delete mSprites[i];
mSprites[i] = newEqSprite;
}
@@ -103,39 +103,6 @@ Player::setSex(Uint8 sex)
}
void
-Player::setWeapon(Uint16 weapon)
-{
- if (weapon != mWeapon)
- {
- AnimatedSprite *newWeaponSprite = NULL;
-
- switch (weapon)
- {
- case 0:
- newWeaponSprite =
- new AnimatedSprite("graphics/sprites/weapon-fist.xml");
- break;
- case 1:
- newWeaponSprite =
- new AnimatedSprite("graphics/sprites/weapon-dagger.xml");
- break;
- case 2:
- newWeaponSprite =
- new AnimatedSprite("graphics/sprites/weapon-bow.xml");
- break;
- case 3:
- newWeaponSprite =
- new AnimatedSprite("graphics/sprites/weapon-scythe.xml");
- break;
- }
-
- delete mSprites[WEAPON_SPRITE];
- mSprites[WEAPON_SPRITE] = newWeaponSprite;
- }
- Being::setWeapon(weapon);
-}
-
-void
Player::setHairColor(Uint16 color)
{
if (color != mHairColor)
@@ -189,11 +156,11 @@ Player::setVisibleEquipment(Uint8 slot, int id)
if (mSex == 0)
{
equipmentSprite = new AnimatedSprite(
- "graphics/sprites/" + EquipmentDB::get(id)->getSprite(0));
+ "graphics/sprites/" + ItemDB::get(id).getSprite(0));
}
else {
equipmentSprite = new AnimatedSprite(
- "graphics/sprites/" + EquipmentDB::get(id)->getSprite(1));
+ "graphics/sprites/" + ItemDB::get(id).getSprite(1));
}
equipmentSprite->setDirection(getSpriteDirection());
@@ -201,6 +168,11 @@ Player::setVisibleEquipment(Uint8 slot, int id)
delete mSprites[slot];
mSprites[slot] = equipmentSprite;
+ if (slot == WEAPON_SPRITE)
+ {
+ mEquippedWeapon = &ItemDB::get(id);
+ }
+
setAction(mAction);
}
diff --git a/src/player.h b/src/player.h
index 8aa84992..2c06bfba 100644
--- a/src/player.h
+++ b/src/player.h
@@ -59,9 +59,6 @@ class Player : public Being
virtual void
setVisibleEquipment(Uint8 slot, int id);
-
- virtual void
- setWeapon(Uint16 weapon);
};
#endif
diff --git a/src/resources/equipmentdb.cpp b/src/resources/equipmentdb.cpp
deleted file mode 100644
index 38ac6415..00000000
--- a/src/resources/equipmentdb.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * The Mana World
- * Copyright 2006 The Mana World Development Team
- *
- * This file is part of The Mana World.
- *
- * The Mana World 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.
- *
- * The Mana World 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 The Mana World; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id$
- */
-
-#include "equipmentdb.h"
-
-#include "resourcemanager.h"
-
-#include "../log.h"
-
-#include "../utils/dtor.h"
-#include "../utils/xml.h"
-
-namespace
-{
- EquipmentDB::EquipmentInfos mEquipmentInfos;
- EquipmentInfo mUnknown;
- bool mLoaded = false;
-}
-
-void
-EquipmentDB::load()
-{
- if (mLoaded)
- return;
-
- logger->log("Initializing equipment database...");
- mUnknown.setSprite("error.xml", 0);
- mUnknown.setSprite("error.xml", 1);
-
- ResourceManager *resman = ResourceManager::getInstance();
- int size;
- char *data = (char*)resman->loadFile("equipment.xml", size);
-
- if (!data)
- {
- logger->error("Equipment Database: Could not find equipment.xml!");
- }
-
- xmlDocPtr doc = xmlParseMemory(data, size);
- free(data);
-
- if (!doc)
- {
- logger->error("Equipment Database: Error while parsing equipment database (equipment.xml)!");
- }
-
- xmlNodePtr rootNode = xmlDocGetRootElement(doc);
- if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "equipments"))
- {
- logger->error("Equipment Database: equipment.xml is not a valid database file!");
- }
-
- //iterate <equipment>s
- for_each_xml_child_node(equipmentNode, rootNode)
- {
- if (!xmlStrEqual(equipmentNode->name, BAD_CAST "equipment"))
- {
- continue;
- }
-
- EquipmentInfo *currentInfo = new EquipmentInfo();
-
- currentInfo->setSlot (XML::getProperty(equipmentNode, "slot", 0));
-
- //iterate <sprite>s
- for_each_xml_child_node(spriteNode, equipmentNode)
- {
- if (!xmlStrEqual(spriteNode->name, BAD_CAST "sprite"))
- {
- continue;
- }
-
- std::string gender = XML::getProperty(spriteNode, "gender", "unisex");
- std::string filename = (const char*) spriteNode->xmlChildrenNode->content;
-
- if (gender == "male" || gender == "unisex")
- {
- currentInfo->setSprite(filename, 0);
- }
-
- if (gender == "female" || gender == "unisex")
- {
- currentInfo->setSprite(filename, 1);
- }
- }
-
- setEquipment( XML::getProperty(equipmentNode, "id", 0),
- currentInfo);
- }
-
- mLoaded = true;
-}
-
-void
-EquipmentDB::unload()
-{
- // kill EquipmentInfos
- for_each ( mEquipmentInfos.begin(), mEquipmentInfos.end(),
- make_dtor(mEquipmentInfos));
- mEquipmentInfos.clear();
-
- mLoaded = false;
-}
-
-EquipmentInfo*
-EquipmentDB::get(int id)
-{
- if (!mLoaded) {
- logger->error("Error: Equipment database used before initialization!");
- }
-
- EquipmentInfoIterator i = mEquipmentInfos.find(id);
-
- if (i == mEquipmentInfos.end() )
- {
- logger->log("EquipmentDB: Error, unknown equipment ID# %d", id);
- return &mUnknown;
- }
- else
- {
- return i->second;
- }
-}
-
-void
-EquipmentDB::setEquipment(int id, EquipmentInfo* equipmentInfo)
-{
- if (mEquipmentInfos.find(id) != mEquipmentInfos.end()) {
- logger->log("Warning: Equipment Piece with ID %d defined multiple times",
- id);
- delete equipmentInfo;
- }
- else {
- mEquipmentInfos[id] = equipmentInfo;
- };
-}
diff --git a/src/resources/equipmentdb.h b/src/resources/equipmentdb.h
deleted file mode 100644
index 1c1db7d1..00000000
--- a/src/resources/equipmentdb.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * The Mana World
- * Copyright 2006 The Mana World Development Team
- *
- * This file is part of The Mana World.
- *
- * The Mana World 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.
- *
- * The Mana World 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 The Mana World; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id$
- */
-
-#ifndef _TMW_EQUIPMENT_DB_H
-#define _TMW_EQUIPMENT_DB_H
-
-#include <map>
-
-#include "equipmentinfo.h"
-
-/**
- * Equipment information database.
- */
-namespace EquipmentDB
-{
- /**
- * Loads the equipment info from Items.xml
- */
- void load();
-
- /**
- * Frees equipment data
- */
- void unload();
-
- void setEquipment(int id, EquipmentInfo* equipmentInfo);
-
- EquipmentInfo* get(int id);
-
- // Equipment database types
- typedef std::map<int, EquipmentInfo*> EquipmentInfos;
- typedef EquipmentInfos::iterator EquipmentInfoIterator;
-}
-
-#endif
diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp
index 7b16339c..18952ae9 100644
--- a/src/resources/itemdb.cpp
+++ b/src/resources/itemdb.cpp
@@ -18,9 +18,11 @@
* along with The Mana World; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id:
+ * $Id$
*/
+#include <cassert>
+
#include "itemdb.h"
#include <libxml/tree.h>
@@ -36,10 +38,13 @@
namespace
{
ItemDB::ItemInfos mItemInfos;
- ItemInfo mUnknown;
+ ItemInfo *mUnknown;
bool mLoaded = false;
}
+// Forward declarations
+static void loadSpriteRef(ItemInfo *itemInfo, xmlNodePtr node);
+static void loadSoundRef(ItemInfo *itemInfo, xmlNodePtr node);
void ItemDB::load()
{
@@ -47,11 +52,16 @@ void ItemDB::load()
return;
logger->log("Initializing item database...");
- mUnknown.setName("Unknown item");
+
+ mUnknown = new ItemInfo();
+ mUnknown->setName("Unknown item");
+ mUnknown->setImage("");
+ mUnknown->setSprite("error.xml", 0);
+ mUnknown->setSprite("error.xml", 1);
ResourceManager *resman = ResourceManager::getInstance();
int size;
- char *data = (char*)resman->loadFile("items.xml", size);
+ char *data = (char*) resman->loadFile("items.xml", size);
if (!data) {
logger->error("ItemDB: Could not find items.xml!");
@@ -73,48 +83,66 @@ void ItemDB::load()
for_each_xml_child_node(node, rootNode)
{
- if (!xmlStrEqual(node->name, BAD_CAST "item")) {
+ if (!xmlStrEqual(node->name, BAD_CAST "item"))
continue;
- }
int id = XML::getProperty(node, "id", 0);
- int art = XML::getProperty(node, "art", 0);
+
+ if (id == 0)
+ {
+ logger->log("ItemDB: Invalid or missing item ID in items.xml!");
+ continue;
+ }
+ else if (mItemInfos.find(id) != mItemInfos.end())
+ {
+ logger->log("ItemDB: Redefinition of item ID %d", id);
+ }
+
int type = XML::getProperty(node, "type", 0);
int weight = XML::getProperty(node, "weight", 0);
+ int view = XML::getProperty(node, "view", 0);
int slot = XML::getProperty(node, "slot", 0);
std::string name = XML::getProperty(node, "name", "");
std::string image = XML::getProperty(node, "image", "");
std::string description = XML::getProperty(node, "description", "");
std::string effect = XML::getProperty(node, "effect", "");
+ std::string attackType = XML::getProperty(node, "attacktype", "");
- if (id && name != "")
+ if (id)
{
ItemInfo *itemInfo = new ItemInfo();
itemInfo->setImage(image);
- itemInfo->setArt(art);
- itemInfo->setName(name);
+ itemInfo->setName((name == "") ? "Unnamed" : name);
itemInfo->setDescription(description);
itemInfo->setEffect(effect);
itemInfo->setType(type);
+ itemInfo->setView(view);
itemInfo->setWeight(weight);
itemInfo->setSlot(slot);
- mItemInfos[id] = itemInfo;
- }
+ itemInfo->setAttackType(attackType);
+
+ for_each_xml_child_node(itemChild, node)
+ {
+ if (xmlStrEqual(itemChild->name, BAD_CAST "sprite"))
+ {
+ loadSpriteRef(itemInfo, itemChild);
+ }
+ else if (xmlStrEqual(itemChild->name, BAD_CAST "sound"))
+ {
+ loadSoundRef(itemInfo, itemChild);
+ }
+ }
- if (id == 0)
- {
- logger->log("ItemDB: An item has no ID in items.xml!");
+ mItemInfos[id] = itemInfo;
}
#define CHECK_PARAM(param, error_value) \
if (param == error_value) \
- logger->log("ItemDB: Missing" #param " parameter for item %i! %s", \
- id, name.c_str())
+ logger->log("ItemDB: Missing " #param " attribute for item %i!",id)
CHECK_PARAM(name, "");
CHECK_PARAM(image, "");
- // CHECK_PARAM(art, 0);
// CHECK_PARAM(description, "");
// CHECK_PARAM(effect, "");
// CHECK_PARAM(type, 0);
@@ -131,19 +159,65 @@ void ItemDB::load()
void ItemDB::unload()
{
- for (ItemInfoIterator i = mItemInfos.begin(); i != mItemInfos.end(); i++)
- {
- delete i->second;
- }
- mItemInfos.clear();
+ logger->log("Unloading item database...");
+
+ delete mUnknown;
+ mUnknown = NULL;
+ for_each(mItemInfos.begin(), mItemInfos.end(), make_dtor(mItemInfos));
+ mItemInfos.clear();
mLoaded = false;
}
-const ItemInfo&
-ItemDB::get(int id)
+const ItemInfo& ItemDB::get(int id)
{
+ assert(mLoaded);
+
ItemInfoIterator i = mItemInfos.find(id);
- return (i != mItemInfos.end()) ? *(i->second) : mUnknown;
+ if (i == mItemInfos.end())
+ {
+ logger->log("ItemDB: Error, unknown item ID# %d", id);
+ return *mUnknown;
+ }
+ else
+ {
+ return *(i->second);
+ }
+}
+
+void loadSpriteRef(ItemInfo *itemInfo, xmlNodePtr node)
+{
+ std::string gender = XML::getProperty(node, "gender", "unisex");
+ std::string filename = (const char*) node->xmlChildrenNode->content;
+
+ if (gender == "male" || gender == "unisex")
+ {
+ itemInfo->setSprite(filename, 0);
+ }
+
+ if (gender == "female" || gender == "unisex")
+ {
+ itemInfo->setSprite(filename, 1);
+ }
+}
+
+void loadSoundRef(ItemInfo *itemInfo, xmlNodePtr node)
+{
+ std::string event = XML::getProperty(node, "event", "");
+ std::string filename = (const char*) node->xmlChildrenNode->content;
+
+ if (event == "hit")
+ {
+ itemInfo->addSound(EQUIP_EVENT_HIT, filename);
+ }
+ else if (event == "strike")
+ {
+ itemInfo->addSound(EQUIP_EVENT_STRIKE, filename);
+ }
+ else
+ {
+ logger->log("ItemDB: Ignoring unknown sound event '%s'",
+ event.c_str());
+ }
}
diff --git a/src/resources/iteminfo.cpp b/src/resources/iteminfo.cpp
index 3a41c657..b5b25ac0 100644
--- a/src/resources/iteminfo.cpp
+++ b/src/resources/iteminfo.cpp
@@ -25,11 +25,11 @@
#include "resourcemanager.h"
#include "image.h"
-
+#include "itemdb.h"
ItemInfo::~ItemInfo()
{
- if (mImage != NULL)
+ if (mImage)
{
mImage->decRef();
}
@@ -38,19 +38,87 @@ ItemInfo::~ItemInfo()
void
ItemInfo::setImage(const std::string &image)
{
+ if (mImage)
+ {
+ mImage->decRef();
+ }
+
+ ResourceManager *resman = ResourceManager::getInstance();
mImageName = "graphics/items/" + image;
+ mImage = ResourceManager::getInstance()->getImage(mImageName);
- if (mImageName != "")
+ if (!mImage)
{
- if (mImage != NULL)
- {
- mImage->decRef();
- }
+ mImage = resman->getImage("graphics/gui/unknown-item.png");
+ }
+}
- mImage = ResourceManager::getInstance()->getImage(mImageName);
+const std::string&
+ItemInfo::getSprite(int gender) const
+{
+ if (mView)
+ {
+ // Forward the request to the item defining how to view this item
+ return ItemDB::get(mView).getSprite(gender);
}
else
{
- mImage = NULL;
+ static const std::string empty = "";
+ std::map<int, std::string>::const_iterator i =
+ mAnimationFiles.find(gender);
+
+ return (i != mAnimationFiles.end()) ? i->second : empty;
+ }
+}
+
+void
+ItemInfo::setAttackType(const std::string &attackType)
+{
+ if (attackType == "swing")
+ {
+ mAttackType = ACTION_ATTACK_SWING;
+ }
+ else if (attackType == "stab")
+ {
+ mAttackType = ACTION_ATTACK_STAB;
+ }
+ else if (attackType == "bow")
+ {
+ mAttackType = ACTION_ATTACK_BOW;
}
+ else if (attackType == "throw")
+ {
+ mAttackType = ACTION_ATTACK_THROW;
+ }
+ else if (attackType == "none")
+ {
+ mAttackType = ACTION_DEFAULT;
+ }
+ else
+ {
+ mAttackType = ACTION_ATTACK;
+ }
+}
+
+void
+ItemInfo::addSound(EquipmentSoundEvent event, const std::string &filename)
+{
+ if (mSounds.find(event) == mSounds.end())
+ {
+ mSounds[event] = new std::vector<std::string>;
+ }
+
+ mSounds[event]->push_back("sfx/" + filename);
+}
+
+
+const std::string&
+ItemInfo::getSound(EquipmentSoundEvent event) const
+{
+ static const std::string empty = "";
+ std::map<EquipmentSoundEvent, std::vector<std::string>*>::const_iterator i;
+ i = mSounds.find(event);
+
+ return (i == mSounds.end()) ? empty :
+ i->second->at(rand() % i->second->size());
}
diff --git a/src/resources/iteminfo.h b/src/resources/iteminfo.h
index e4f851bb..4fd1638e 100644
--- a/src/resources/iteminfo.h
+++ b/src/resources/iteminfo.h
@@ -24,12 +24,23 @@
#ifndef _TMW_ITEMINFO_H_
#define _TMW_ITEMINFO_H_
+#include <map>
#include <string>
+#include <vector>
+
+#include "spritedef.h"
class Image;
+enum EquipmentSoundEvent
+{
+ EQUIP_EVENT_STRIKE,
+ EQUIP_EVENT_HIT
+};
+
/**
- * Defines a class for storing item infos.
+ * Defines a class for storing item infos. This includes information used when
+ * the item is equipped.
*/
class ItemInfo
{
@@ -40,10 +51,11 @@ class ItemInfo
ItemInfo():
mImageName(""),
mImage(NULL),
- mArt(0),
mType(0),
mWeight(0),
- mSlot(0)
+ mView(0),
+ mSlot(0),
+ mAttackType(ACTION_DEFAULT)
{
}
@@ -52,73 +64,89 @@ class ItemInfo
*/
~ItemInfo();
- void
- setArt(short art) { mArt = art; }
+ void setName(const std::string &name)
+ { mName = name; }
- short
- getArt() const { return mArt; }
+ const std::string& getName() const
+ { return mName; }
- void
- setName(const std::string &name) { mName = name; }
+ void setImage(const std::string &image);
- const std::string&
- getName() const { return mName; }
+ Image* getImage() const
+ { return mImage; }
- void
- setImage(const std::string &image);
+ void setDescription(const std::string &description)
+ { mDescription = description; }
- Image*
- getImage() const { return mImage; }
+ const std::string& getDescription() const
+ { return mDescription; }
- void
- setDescription(const std::string &description)
- {
- mDescription = description;
- }
+ void setEffect(const std::string &effect)
+ { mEffect = effect; }
const std::string&
- getDescription() const { return mDescription; }
+ getEffect() const { return mEffect; }
- void
- setEffect(const std::string &effect) { mEffect = effect; }
+ void setType(short type)
+ { mType = type; }
- const std::string&
- getEffect() const { return mEffect; }
+ short getType() const
+ { return mType; }
+
+ void setWeight(short weight)
+ { mWeight = weight; }
+
+ short getWeight() const
+ { return mWeight; }
+
+ void setView(int view)
+ { mView = view; }
+
+ void setSlot(char slot)
+ { mSlot = slot; }
- void
- setType(short type) { mType = type; }
+ char getSlot() const
+ { return mSlot; }
- short
- getType() const { return mType; }
+ void setSprite(const std::string &animationFile, int gender)
+ { mAnimationFiles[gender] = animationFile; }
- void
- setWeight(short weight) { mWeight = weight; }
+ const std::string& getSprite(int gender) const;
- short
- getWeight() const { return mWeight; }
+ void setAttackType(const std::string &attackType);
- void
- setSlot(char slot) { mSlot = slot; }
+ const SpriteAction getAttackType() const
+ { return mAttackType; }
- char
- getSlot() const { return mSlot; }
+ void addSound(EquipmentSoundEvent event, const std::string &filename);
+
+ const std::string& getSound(EquipmentSoundEvent event) const;
protected:
- std::string mImageName;
+ std::string mImageName; /**< The filename of the icon image. */
/* TODO (BL): I do not think the item info should keep a reference to
* the item icon. It would probably be better if this was kept in the
* Item class, so that the images can be lazily instantiated and also
* unloaded when no longer used.
*/
- Image *mImage;
- short mArt;
+ Image *mImage; /**< The loaded icon image. */
std::string mName;
- std::string mDescription;
- std::string mEffect;
- short mType;
- short mWeight;
- char mSlot;
+ std::string mDescription; /**< Short description. */
+ std::string mEffect; /**< Description of effects. */
+ short mType; /**< Item type (never used). */
+ short mWeight; /**< Weight in grams. */
+ int mView; /**< Item ID of how this item looks. */
+
+ // Equipment related members
+ char mSlot; /**< Equipment slot. */
+ SpriteAction mAttackType; /**< Attack type, in case of weapon. */
+
+ /** Maps gender to sprite filenames. */
+ std::map<int, std::string> mAnimationFiles;
+
+ /** Stores the names of sounds to be played at certain event. */
+ std::map<EquipmentSoundEvent, std::vector<std::string>* > mSounds;
};
#endif
diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp
index 260d5aa9..940ded36 100644
--- a/src/resources/mapreader.cpp
+++ b/src/resources/mapreader.cpp
@@ -156,7 +156,7 @@ MapReader::readMap(const std::string &filename)
if (buffer == NULL)
{
- logger->log("Map file not found (%s)\n", filename.c_str());
+ logger->log("Map file not found (%s)", filename.c_str());
return NULL;
}
diff --git a/src/resources/monsterdb.cpp b/src/resources/monsterdb.cpp
index 339ed6ba..f4864eea 100644
--- a/src/resources/monsterdb.cpp
+++ b/src/resources/monsterdb.cpp
@@ -120,19 +120,19 @@ MonsterDB::load()
if (event == "hit")
{
- currentInfo->addSound(EVENT_HIT, filename);
+ currentInfo->addSound(MONSTER_EVENT_HIT, filename);
}
else if (event == "miss")
{
- currentInfo->addSound(EVENT_MISS, filename);
+ currentInfo->addSound(MONSTER_EVENT_MISS, filename);
}
else if (event == "hurt")
{
- currentInfo->addSound(EVENT_HURT, filename);
+ currentInfo->addSound(MONSTER_EVENT_HURT, filename);
}
else if (event == "die")
{
- currentInfo->addSound(EVENT_DIE, filename);
+ currentInfo->addSound(MONSTER_EVENT_DIE, filename);
}
else
{
diff --git a/src/resources/monsterinfo.cpp b/src/resources/monsterinfo.cpp
index 2a59419e..2e896237 100644
--- a/src/resources/monsterinfo.cpp
+++ b/src/resources/monsterinfo.cpp
@@ -33,15 +33,15 @@ MonsterInfo::MonsterInfo():
MonsterInfo::~MonsterInfo()
{
- //kill vectors in mSoundEffects
- for_each ( mSounds.begin(), mSounds.end(),
- make_dtor(mSounds));
+ // kill vectors in mSoundEffects
+ for_each (mSounds.begin(), mSounds.end(),
+ make_dtor(mSounds));
mSounds.clear();
}
void
-MonsterInfo::addSound (SoundEvent event, std::string filename)
+MonsterInfo::addSound(MonsterSoundEvent event, std::string filename)
{
if (mSounds.find(event) == mSounds.end())
{
@@ -53,9 +53,9 @@ MonsterInfo::addSound (SoundEvent event, std::string filename)
std::string
-MonsterInfo::getSound (SoundEvent event) const
+MonsterInfo::getSound(MonsterSoundEvent event) const
{
- std::map<SoundEvent, std::vector<std::string>* >::const_iterator i;
+ std::map<MonsterSoundEvent, std::vector<std::string>* >::const_iterator i;
i = mSounds.find(event);
diff --git a/src/resources/monsterinfo.h b/src/resources/monsterinfo.h
index aa7db9f0..c9fbd4c9 100644
--- a/src/resources/monsterinfo.h
+++ b/src/resources/monsterinfo.h
@@ -31,12 +31,12 @@
#include "../being.h"
-enum SoundEvent
+enum MonsterSoundEvent
{
- EVENT_HIT,
- EVENT_MISS,
- EVENT_HURT,
- EVENT_DIE
+ MONSTER_EVENT_HIT,
+ MONSTER_EVENT_MISS,
+ MONSTER_EVENT_HURT,
+ MONSTER_EVENT_DIE
};
/**
@@ -69,7 +69,7 @@ class MonsterInfo
{ mTargetCursorSize = targetCursorSize; }
void
- addSound(SoundEvent event, std::string filename);
+ addSound(MonsterSoundEvent event, std::string filename);
const std::string&
getName () const { return mName; };
@@ -81,13 +81,13 @@ class MonsterInfo
getTargetCursorSize() const { return mTargetCursorSize; }
std::string
- getSound (SoundEvent event) const;
+ getSound(MonsterSoundEvent event) const;
private:
std::string mName;
std::string mSprite;
Being::TargetCursorSize mTargetCursorSize;
- std::map<SoundEvent, std::vector<std::string>* > mSounds;
+ std::map<MonsterSoundEvent, std::vector<std::string>* > mSounds;
};
#endif
diff --git a/src/resources/spritedef.h b/src/resources/spritedef.h
index 6d335b02..55d7f459 100644
--- a/src/resources/spritedef.h
+++ b/src/resources/spritedef.h
@@ -24,11 +24,11 @@
#ifndef _TMW_SPRITEDEF_H
#define _TMW_SPRITEDEF_H
-#include "resource.h"
-
#include <map>
#include <string>
+#include "resource.h"
+
#include <libxml/tree.h>
class Action;
diff --git a/src/textparticle.cpp b/src/textparticle.cpp
index dd01d2fe..4bc859cd 100644
--- a/src/textparticle.cpp
+++ b/src/textparticle.cpp
@@ -26,7 +26,8 @@
#include "graphics.h"
TextParticle::TextParticle(Map *map, const std::string &text,
- int colorR, int colorG, int colorB, gcn::Font *font):
+ int colorR, int colorG, int colorB,
+ gcn::Font *font):
Particle(map),
mText(text),
mTextFont(font),
@@ -41,8 +42,8 @@ void TextParticle::draw(Graphics *graphics, int offsetX, int offsetY) const
if (!mAlive)
return;
- int screenX = (int)mPosX + offsetX;
- int screenY = (int)mPosY - int(mPosZ) + offsetY;
+ int screenX = (int) mPos.x + offsetX;
+ int screenY = (int) mPos.y - (int) mPos.z + offsetY;
int alpha = 255;
@@ -50,7 +51,7 @@ void TextParticle::draw(Graphics *graphics, int offsetX, int offsetY) const
{
alpha *= mLifetimeLeft;
alpha /= mFadeOut;
- };
+ }
if (mLifetimePast < mFadeIn)
{
@@ -59,6 +60,6 @@ void TextParticle::draw(Graphics *graphics, int offsetX, int offsetY) const
}
graphics->setFont(mTextFont);
- graphics->setColor(gcn::Color (mColorR, mColorG, mColorB, alpha));
+ graphics->setColor(gcn::Color(mColorR, mColorG, mColorB, alpha));
graphics->drawText(mText, screenX, screenY, gcn::Graphics::CENTER);
}
diff --git a/src/textparticle.h b/src/textparticle.h
index b365c885..34badb57 100644
--- a/src/textparticle.h
+++ b/src/textparticle.h
@@ -33,21 +33,26 @@
class TextParticle : public Particle
{
public:
+ /**
+ * Constructor.
+ */
TextParticle(Map *map, const std::string &text,
- int colorR, int colorG, int colorB, gcn::Font *font);
+ int colorR, int colorG, int colorB,
+ gcn::Font *font);
/**
- * Draws the particle image
+ * Draws the particle image.
*/
virtual void
draw(Graphics *graphics, int offsetX, int offsetY) const;
// hack to improve text visibility
- virtual int getPixelY() const { return (int)(mPosY + mPosZ); }
+ virtual int getPixelY() const
+ { return (int) (mPos.y + mPos.z); }
private:
- std::string mText; /**< Text of the particle */
- gcn::Font *mTextFont; /**< Font used for drawing the text */
- int mColorR, mColorG, mColorB; /**< Color used for drawing the text */
+ std::string mText; /**< Text of the particle. */
+ gcn::Font *mTextFont; /**< Font used for drawing the text. */
+ int mColorR, mColorG, mColorB; /**< Color used for drawing the text. */
};
#endif
diff --git a/src/utils/fastsqrt.h b/src/utils/fastsqrt.h
index 78768149..b7b036e9 100644
--- a/src/utils/fastsqrt.h
+++ b/src/utils/fastsqrt.h
@@ -5,6 +5,8 @@
* http://www.math.purdue.edu/~clomont/Math/Papers/2003/InvSqrt.pdf
*
* Unfortunately the original creator of this function seems to be unknown.
+ *
+ * $Id$
*/
float fastInvSqrt(float x)
diff --git a/src/utils/minmax.h b/src/utils/minmax.h
index 27eb2565..ea6ad9e0 100644
--- a/src/utils/minmax.h
+++ b/src/utils/minmax.h
@@ -18,6 +18,7 @@
* along with The Mana World; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
+ * $Id$
*/
/**
diff --git a/src/resources/equipmentinfo.h b/src/utils/trim.h
index 75ed1b8a..1b5311e6 100644
--- a/src/resources/equipmentinfo.h
+++ b/src/utils/trim.h
@@ -1,6 +1,6 @@
/*
* The Mana World
- * Copyright 2006 The Mana World Development Team
+ * Copyright 2007 The Mana World Development Team
*
* This file is part of The Mana World.
*
@@ -18,35 +18,36 @@
* along with The Mana World; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id:
+ * $Id$
*/
-#ifndef _TMW_EQUIPMENTINFO_H_
-#define _TMW_EQUIPMENTINFO_H_
+#ifndef _TMW_UTILS_TRIM_H_
+#define _TMW_UTILS_TRIM_H_
#include <string>
-#include <map>
-class EquipmentInfo
+/**
+ * Trims spaces off the end and the beginning of the given string.
+ *
+ * @param str the string to trim spaces off
+ */
+static void trim(std::string &str)
{
- public:
- EquipmentInfo():
- mSlot (0)
+ std::string::size_type pos = str.find_last_not_of(' ');
+ if (pos != std::string::npos)
+ {
+ str.erase(pos + 1);
+ pos = str.find_first_not_of(' ');
+ if (pos != std::string::npos)
{
- };
-
- void
- setSlot (int slot) { mSlot = slot; };
-
- const std::string&
- getSprite(int gender) {return animationFiles[gender]; };
-
- void
- setSprite(std::string animationFile, int gender) {animationFiles[gender] = animationFile; };
-
- private:
- int mSlot; //not used at the moment but maybe useful on our own server
- std::map<int, std::string> animationFiles;
-};
+ str.erase(0, pos);
+ }
+ }
+ else
+ {
+ // There is nothing else but whitespace in the string
+ str.clear();
+ }
+}
#endif
diff --git a/src/vector.h b/src/vector.h
new file mode 100644
index 00000000..7a5da241
--- /dev/null
+++ b/src/vector.h
@@ -0,0 +1,134 @@
+/*
+ * The Mana World
+ * Copyright 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#ifndef _TMW_VECTOR_H_
+#define _TMW_VECTOR_H_
+
+/**
+ * Vector class. Represents either a 3D point in space, a velocity or a force.
+ * Provides several convenient operator overloads.
+ */
+class Vector
+{
+ public:
+ /**
+ * Constructor.
+ */
+ Vector():
+ x(0.0f),
+ y(0.0f),
+ z(0.0f)
+ {}
+
+ /**
+ * Constructor.
+ */
+ Vector(float x, float y, float z):
+ x(x),
+ y(y),
+ z(z)
+ {}
+
+ /**
+ * Copy constructor.
+ */
+ Vector(const Vector &v):
+ x(v.x),
+ y(v.y),
+ z(v.z)
+ {}
+
+ /**
+ * Scale vector operator.
+ */
+ Vector operator*(float c) const
+ {
+ return Vector(x * c,
+ y * c,
+ z * c);
+ }
+
+ /**
+ * In-place scale vector operator.
+ */
+ void operator*=(float c)
+ {
+ x *= c;
+ y *= c;
+ z *= c;
+ }
+
+ /**
+ * Scale vector operator.
+ */
+ Vector operator/(float c) const
+ {
+ return Vector(x / c,
+ y / c,
+ z / c);
+ }
+
+ /**
+ * Add vector operator.
+ */
+ Vector operator+(const Vector &v) const
+ {
+ return Vector(x + v.x,
+ y + v.y,
+ z + v.z);
+ }
+
+ /**
+ * In-place add vector operator.
+ */
+ void operator+=(const Vector &v)
+ {
+ x += v.x;
+ y += v.y;
+ z += v.z;
+ }
+
+ /**
+ * Substract vector operator.
+ */
+ Vector operator-(const Vector &v) const
+ {
+ return Vector(x - v.x,
+ y - v.y,
+ z - v.z);
+ }
+
+ /**
+ * In-place substract vector operator.
+ */
+ void operator-=(const Vector &v)
+ {
+ x -= v.x;
+ y -= v.y;
+ z -= v.z;
+ }
+
+ float x, y, z;
+};
+
+#endif