summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/game.cpp135
-rw-r--r--src/gui/gui.cpp130
-rw-r--r--src/gui/gui.h25
-rw-r--r--src/gui/inventorywindow.cpp4
-rw-r--r--src/gui/popupmenu.h2
-rw-r--r--src/net/protocol.cpp18
-rw-r--r--src/net/protocol.h8
7 files changed, 164 insertions, 158 deletions
diff --git a/src/game.cpp b/src/game.cpp
index e7f7beb7..ab0e73d9 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -58,7 +58,6 @@
#include "gui/npc.h"
#include "gui/npc_text.h"
#include "gui/ok_dialog.h"
-#include "gui/popupmenu.h"
#include "gui/requesttrade.h"
#include "gui/sell.h"
#include "gui/setup.h"
@@ -116,7 +115,6 @@ ChargeDialog *chargeDialog;
TradeWindow *tradeWindow;
//BuddyWindow *buddyWindow;
HelpWindow *helpWindow;
-PopupMenu *popupMenu;
DebugWindow *debugWindow;
Inventory *inventory = NULL;
@@ -217,7 +215,6 @@ void createGuiWindows()
tradeWindow = new TradeWindow();
//buddyWindow = new BuddyWindow();
helpWindow = new HelpWindow();
- popupMenu = new PopupMenu();
debugWindow = new DebugWindow();
// Initialize window positions
@@ -252,7 +249,6 @@ void createGuiWindows()
tradeWindow->setVisible(false);
//buddyWindow->setVisible(false);
helpWindow->setVisible(false);
- popupMenu->setVisible(false);
debugWindow->setVisible(false);
// Do not focus any text field
@@ -283,7 +279,6 @@ void destroyGuiWindows()
delete tradeWindow;
//delete buddyWindow;
delete helpWindow;
- delete popupMenu;
delete debugWindow;
}
@@ -671,136 +666,6 @@ void do_input()
}
}
- // Mouse events
- else if (event.type == SDL_MOUSEBUTTONDOWN)
- {
- int mx = event.button.x / 32 + camera_x;
- int my = event.button.y / 32 + camera_y;
-
- // Mouse button left
- if (event.button.button == SDL_BUTTON_LEFT)
- {
- // Don't move when shift is pressed
- // XXX Is this too hackish? I'm not sure if making the Gui
- // class a KeyListener is a good idea and works as expected
- // at all...
- if (keys[SDLK_LSHIFT] || keys[SDLK_RSHIFT]) {
- used = true;
- }
-
- // Check for default actions for NPC/Monster/Players
- Being *target = findNode(mx, my);
- Uint32 floorItemId = find_floor_item_by_cor(mx, my);
-
- if (target)
- {
- switch (target->getType())
- {
- case Being::NPC:
- // NPC default: talk
- if (!current_npc)
- {
- MessageOut outMsg;
- outMsg.writeInt16(CMSG_NPC_TALK);
- outMsg.writeInt32(target->getId());
- outMsg.writeInt8(0);
- current_npc = target->getId();
- }
- break;
-
- case Being::MONSTER:
- case Being::PLAYER:
- // Monster and player default: attack
- /**
- * TODO: Move player to mouse click position before
- * attack the monster (maybe using follow mode).
- */
- if (target->action != Being::MONSTER_DEAD &&
- player_node->action == Being::STAND &&
- target != player_node)
- {
- // Autotarget by default with mouse
- autoTarget = target;
-
- attack(target);
- }
- break;
-
- default:
- break;
- }
- }
- // Check for default action to items on the floor
- else if (floorItemId != 0)
- {
- /**
- * TODO: Move player to mouse click position before
- * pick up the items on the floor.
- *
- * Provisory: pick up only items near of player.
- */
- int dx = mx - player_node->x;
- int dy = my - player_node->y;
- // "sqrt(dx*dx + dy*dy) < 2" is equal to "dx*dx + dy*dy < 4"
- if ((dx*dx + dy*dy) < 4)
- {
- MessageOut outMsg;
- outMsg.writeInt16(0x009f);
- outMsg.writeInt32(floorItemId);
- }
- }
-
- // Just cancel the popup menu if shown, and don't make the
- // character walk
- if (popupMenu->isVisible() == true)
- {
- // If we click elsewhere than in the window, do not use
- // the event
- // The user wanted to close the popup.
- // Still buggy : Wonder if the x, y, width, and height
- // aren't reported partially with these functions.
- if (event.button.x >=
- (popupMenu->getX() + popupMenu->getWidth()) ||
- event.button.x < popupMenu->getX() ||
- event.button.y >=
- (popupMenu->getY() + popupMenu->getHeight()) ||
- event.button.y < popupMenu->getY())
- {
- used = true;
- popupMenu->setVisible(false);
- }
- }
-
- } // End Mouse left button
-
- // Mouse button middle
- else if (event.button.button == SDL_BUTTON_MIDDLE)
- {
- /*
- * Some people haven't a mouse with three buttons,
- * right Usiu??? ;-)
- */
- }
-
- // Mouse button right
- else if (event.button.button == SDL_BUTTON_RIGHT)
- {
- Being *being;
- FloorItem *floorItem;
-
- if ((being = findNode(mx, my)) && being != player_node) {
- popupMenu->showPopup(event.button.x, event.button.y,
- being);
- } else if ((floorItem = find_floor_item_by_id(
- find_floor_item_by_cor(mx, my)))) {
- popupMenu->showPopup(event.button.x, event.button.y,
- floorItem);
- } else {
- popupMenu->setVisible(false);
- }
- }
- }
-
// Quit event
else if (event.type == SDL_QUIT)
{
diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp
index bf35e3ec..25b794ec 100644
--- a/src/gui/gui.cpp
+++ b/src/gui/gui.cpp
@@ -34,6 +34,7 @@
#include <guichan/sdl/sdlinput.hpp>
#include "focushandler.h"
+#include "popupmenu.h"
#include "window.h"
#include "windowcontainer.h"
@@ -41,6 +42,7 @@
#include "../configlistener.h"
#include "../configuration.h"
#include "../engine.h"
+#include "../floor_item.h"
#include "../game.h"
#include "../graphics.h"
#include "../log.h"
@@ -87,7 +89,8 @@ class GuiConfigListener : public ConfigListener
Gui::Gui(Graphics *graphics):
mHostImageLoader(NULL),
mMouseCursor(NULL),
- mCustomCursor(false)
+ mCustomCursor(false),
+ mPopupActive(false)
{
// Set graphics
setGraphics(graphics);
@@ -168,10 +171,14 @@ Gui::Gui(Graphics *graphics):
setUseCustomCursor(config.getValue("customcursor", 1) == 1);
mConfigListener = new GuiConfigListener(this);
config.addListener("customcursor", mConfigListener);
+
+ mPopup = new PopupMenu();
}
Gui::~Gui()
{
+ delete mPopup;
+
config.removeListener("customcursor", mConfigListener);
delete mConfigListener;
@@ -231,21 +238,100 @@ Gui::mousePress(int mx, int my, int button)
{
// Mouse pressed on window container (basically, the map)
- // When conditions for walking are met, set new player destination
- if (player_node &&
- player_node->action != Being::DEAD &&
- current_npc == 0 &&
- button == gcn::MouseInput::LEFT)
+ // Are we in-game yet?
+ if (state != GAME_STATE)
+ return;
+
+ // Check if we are alive and kickin'
+ if (!player_node || player_node->action == Being::DEAD)
+ return;
+
+ // Check if we are busy
+ if (current_npc)
+ return;
+
+ int tilex = mx / 32 + camera_x;
+ int tiley = my / 32 + camera_y;
+
+ // Right click might open a popup
+ if (button == gcn::MouseInput::RIGHT)
{
- Map *tiledMap = engine->getCurrentMap();
- int tilex = mx / 32 + camera_x;
- int tiley = my / 32 + camera_y;
+ Being *being;
+ FloorItem *floorItem;
- if (state == GAME_STATE && tiledMap->getWalk(tilex, tiley)) {
- walk(tilex, tiley, 0);
- player_node->setDestination(tilex, tiley);
+ if ((being = findNode(tilex, tiley)) && being != player_node)
+ {
+ showPopup(mx, my, being);
+ return;
+ }
+ else if(floorItem = find_floor_item_by_id(
+ find_floor_item_by_cor(mx, my)))
+ {
+ showPopup(mx, my, floorItem);
+ return;
+ }
+ }
+
+ // If a popup is active, just remove it
+ if (mPopupActive)
+ {
+ mPopup->setVisible(false);
+ mPopupActive = false;
+ return;
+ }
+
+ // Left click can cause different actions
+ if (button == gcn::MouseInput::LEFT)
+ {
+ Being *being;
+ Uint32 floorItemId;
- autoTarget = NULL;
+ // Interact with some being
+ if (being = findNode(tilex, tiley))
+ {
+ switch (being->getType())
+ {
+ case Being::NPC:
+ talk(being);
+ current_npc = being->getId();
+ break;
+
+ case Being::MONSTER:
+ case Being::PLAYER:
+ if (being->action == Being::MONSTER_DEAD ||
+ player_node->action != Being::STAND ||
+ being == player_node)
+ break;
+
+ autoTarget = being;
+ attack(being);
+ break;
+
+ default:
+ break;
+ }
+ }
+ // Pick up some item
+ else if (floorItemId = find_floor_item_by_cor(tilex, tiley))
+ {
+ int dx = tilex - player_node->x;
+ int dy = tiley - player_node->y;
+
+ if ((dx * dx + dy * dy) < 4)
+ pickUp(floorItemId);
+ }
+ // Just walk around
+ else if (engine->getCurrentMap()->getWalk(tilex, tiley))
+ {
+ // XXX XXX XXX REALLY UGLY!
+ Uint8 *keys = SDL_GetKeyState(NULL);
+ if (!(keys[SDLK_LSHIFT] || keys[SDLK_RSHIFT]))
+ {
+ walk(tilex, tiley, 0);
+ player_node->setDestination(tilex, tiley);
+
+ autoTarget = NULL;
+ }
}
}
}
@@ -282,3 +368,21 @@ Gui::setUseCustomCursor(bool customCursor)
}
}
}
+
+void Gui::showPopup(int x, int y, Item *item)
+{
+ mPopup->showPopup(x, y, item);
+ mPopupActive = true;
+}
+
+void Gui::showPopup(int x, int y, FloorItem *floorItem)
+{
+ mPopup->showPopup(x, y, floorItem);
+ mPopupActive = true;
+}
+
+void Gui::showPopup(int x, int y, Being *being)
+{
+ mPopup->showPopup(x, y, being);
+ mPopupActive = true;
+}
diff --git a/src/gui/gui.h b/src/gui/gui.h
index 238ee38e..83f731db 100644
--- a/src/gui/gui.h
+++ b/src/gui/gui.h
@@ -29,9 +29,13 @@
#include "../guichanfwd.h"
+class Being;
+class FloorItem;
class GuiConfigListener;
class Graphics;
class Image;
+class Item;
+class PopupMenu;
class WindowContainer;
/**
@@ -92,10 +96,22 @@ class Gui : public gcn::Gui, public gcn::MouseListener
setUseCustomCursor(bool customCursor);
/**
- * ConfigListener method.
+ * Shows a popup for an item
+ * TODO Find some way to get rid of Item here
*/
- void
- optionChanged(const std::string &name);
+ void showPopup(int x, int y, Item *item);
+
+ /**
+ * 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);
private:
GuiConfigListener *mConfigListener;
@@ -104,6 +120,9 @@ class Gui : public gcn::Gui, public gcn::MouseListener
gcn::Font *mGuiFont; /**< The global GUI font */
Image *mMouseCursor; /**< Mouse cursor image */
bool mCustomCursor; /**< Show custom cursor */
+
+ PopupMenu *mPopup; /**< Popup window */
+ bool mPopupActive;
};
extern Gui *gui; /**< The GUI system */
diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp
index 35809bdd..0b8a37a7 100644
--- a/src/gui/inventorywindow.cpp
+++ b/src/gui/inventorywindow.cpp
@@ -31,9 +31,9 @@
#include <guichan/widgets/label.hpp>
#include "button.h"
+#include "gui.h"
#include "item_amount.h"
#include "itemcontainer.h"
-#include "popupmenu.h"
#include "scrollarea.h"
#include "../inventory.h"
@@ -162,7 +162,7 @@ void InventoryWindow::mouseClick(int x, int y, int button, int count)
*/
int mx = x + getX();
int my = y + getY();
- popupMenu->showPopup(mx, my, item);
+ gui->showPopup(mx, my, item);
}
}
diff --git a/src/gui/popupmenu.h b/src/gui/popupmenu.h
index 97cadf38..dfbb2e92 100644
--- a/src/gui/popupmenu.h
+++ b/src/gui/popupmenu.h
@@ -79,6 +79,4 @@ class PopupMenu : public Window, public LinkHandler
void showPopup(int x, int y);
};
-extern PopupMenu *popupMenu;
-
#endif
diff --git a/src/net/protocol.cpp b/src/net/protocol.cpp
index e57be110..7a98ffb6 100644
--- a/src/net/protocol.cpp
+++ b/src/net/protocol.cpp
@@ -23,13 +23,10 @@
#include "protocol.h"
-#include "messagein.h"
#include "messageout.h"
-#include "network.h"
#include "../being.h"
#include "../game.h"
-#include "../log.h"
#include "../main.h"
#include "../playerinfo.h"
#include "../sound.h"
@@ -85,6 +82,21 @@ void action(char type, int id)
outMsg.writeInt8(type);
}
+void talk(Being *being)
+{
+ MessageOut outMsg;
+ outMsg.writeInt16(CMSG_NPC_TALK);
+ outMsg.writeInt32(being->getId());
+ outMsg.writeInt8(0);
+}
+
+void pickUp(Uint32 floorItemId)
+{
+ MessageOut outMsg;
+ outMsg.writeInt16(0x009f);
+ outMsg.writeInt32(floorItemId);
+}
+
Being* attack(unsigned short x, unsigned short y, unsigned char direction)
{
Being *target = NULL;
diff --git a/src/net/protocol.h b/src/net/protocol.h
index c6e118d4..8ac0f16d 100644
--- a/src/net/protocol.h
+++ b/src/net/protocol.h
@@ -24,6 +24,8 @@
#ifndef _TMW_PROTOCOL_
#define _TMW_PROTOCOL_
+#include <SDL_types.h>
+
class Being;
// Packets from server to client
@@ -127,4 +129,10 @@ void attack(Being *target);
/** Request action */
void action(char type, int id);
+/** Talk to a being */
+void talk(Being *being);
+
+/** Pick up an item */
+void pickUp(Uint32 floorItemId);
+
#endif