diff options
author | Jared Adams <jaxad0127@gmail.com> | 2010-02-13 15:04:58 -0700 |
---|---|---|
committer | Jared Adams <jaxad0127@gmail.com> | 2010-02-13 15:08:54 -0700 |
commit | 8bc425ff48b7a874ca0fb9d2285044c75f3010ab (patch) | |
tree | 5904c7f53cde9ffbe7df2a63f088561141e06b66 /src/net | |
parent | 28c9cec5d39c9a1b98694eba9a28281cf111e34a (diff) | |
download | mana-8bc425ff48b7a874ca0fb9d2285044c75f3010ab.tar.gz mana-8bc425ff48b7a874ca0fb9d2285044c75f3010ab.tar.bz2 mana-8bc425ff48b7a874ca0fb9d2285044c75f3010ab.tar.xz mana-8bc425ff48b7a874ca0fb9d2285044c75f3010ab.zip |
Make NPC dialogs instance instead of global
This change allows players to talk to multiple NPCs at a time (if the server agrees). Manaserv's netcode allows multiple commerce instances too. eAthena's is limited to one commerce instance, due to protocol limitations.
Diffstat (limited to 'src/net')
-rw-r--r-- | src/net/ea/buysellhandler.cpp | 30 | ||||
-rw-r--r-- | src/net/ea/buysellhandler.h | 6 | ||||
-rw-r--r-- | src/net/ea/npchandler.cpp | 97 | ||||
-rw-r--r-- | src/net/ea/npchandler.h | 11 | ||||
-rw-r--r-- | src/net/ea/playerhandler.cpp | 10 | ||||
-rw-r--r-- | src/net/manaserv/buysellhandler.cpp | 35 | ||||
-rw-r--r-- | src/net/manaserv/npchandler.cpp | 52 | ||||
-rw-r--r-- | src/net/manaserv/npchandler.h | 11 | ||||
-rw-r--r-- | src/net/manaserv/playerhandler.cpp | 43 |
9 files changed, 151 insertions, 144 deletions
diff --git a/src/net/ea/buysellhandler.cpp b/src/net/ea/buysellhandler.cpp index 9d1aac78..db282e61 100644 --- a/src/net/ea/buysellhandler.cpp +++ b/src/net/ea/buysellhandler.cpp @@ -51,29 +51,29 @@ BuySellHandler::BuySellHandler() SMSG_NPC_SELL_RESPONSE, 0 }; + mNpcId = 0; handledMessages = _messages; } void BuySellHandler::handleMessage(Net::MessageIn &msg) { int n_items; + switch (msg.getId()) { case SMSG_NPC_BUY_SELL_CHOICE: - buyDialog->setVisible(false); - buyDialog->reset(); - sellDialog->setVisible(false); - sellDialog->reset(); - current_npc = msg.readInt32(); - buySellDialog->setVisible(true); + if (!BuySellDialog::isActive()) + { + mNpcId = msg.readInt32(); + new BuySellDialog(mNpcId); + } break; case SMSG_NPC_BUY: msg.readInt16(); // length n_items = (msg.getLength() - 4) / 11; - buyDialog->reset(); - buyDialog->setMoney(player_node->getMoney()); - buyDialog->setVisible(true); + mBuyDialog = new BuyDialog(mNpcId); + mBuyDialog->setMoney(player_node->getMoney()); for (int k = 0; k < n_items; k++) { @@ -81,7 +81,7 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg) msg.readInt32(); // DCvalue msg.readInt8(); // type int itemId = msg.readInt16(); - buyDialog->addItem(itemId, 0, value); + mBuyDialog->addItem(itemId, 0, value); } break; @@ -90,9 +90,8 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg) n_items = (msg.getLength() - 4) / 10; if (n_items > 0) { - sellDialog->setMoney(player_node->getMoney()); - sellDialog->reset(); - sellDialog->setVisible(true); + SellDialog *dialog = new SellDialog(mNpcId); + dialog->setMoney(player_node->getMoney()); for (int k = 0; k < n_items; k++) { @@ -103,13 +102,12 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg) Item *item = player_node->getInventory()->getItem(index); if (item && !(item->isEquipped())) - sellDialog->addItem(item, value); + dialog->addItem(item, value); } } else { localChatTab->chatLog(_("Nothing to sell."), BY_SERVER); - current_npc = 0; } break; @@ -122,7 +120,7 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg) { // Reset player money since buy dialog already assumed purchase // would go fine - buyDialog->setMoney(player_node->getMoney()); + mBuyDialog->setMoney(player_node->getMoney()); localChatTab->chatLog(_("Unable to buy."), BY_SERVER); } break; diff --git a/src/net/ea/buysellhandler.h b/src/net/ea/buysellhandler.h index 61736024..1d17905d 100644 --- a/src/net/ea/buysellhandler.h +++ b/src/net/ea/buysellhandler.h @@ -24,6 +24,8 @@ #include "net/ea/messagehandler.h" +class BuyDialog; + namespace EAthena { class BuySellHandler : public MessageHandler @@ -32,6 +34,10 @@ class BuySellHandler : public MessageHandler BuySellHandler(); virtual void handleMessage(Net::MessageIn &msg); + + private: + int mNpcId; + BuyDialog *mBuyDialog; }; } // namespace EAthena diff --git a/src/net/ea/npchandler.cpp b/src/net/ea/npchandler.cpp index 48cc6125..6fb719a1 100644 --- a/src/net/ea/npchandler.cpp +++ b/src/net/ea/npchandler.cpp @@ -57,72 +57,70 @@ NpcHandler::NpcHandler() void NpcHandler::handleMessage(Net::MessageIn &msg) { - int id; - bool resetPlayer = false; + bool resetPlayer = true; + + if (msg.getId() == SMSG_NPC_CHOICE || msg.getId() == SMSG_NPC_MESSAGE) + { + msg.readInt16(); // length + } + + int npcId = msg.readInt32(); + NpcDialogs::iterator diag = mNpcDialogs.find(npcId); + NpcDialog *dialog; + + if (diag == mNpcDialogs.end()) + { + // Empty dialogs don't help + if (msg.getId() == SMSG_NPC_CLOSE) + { + closeDialog(npcId); + } + else if (msg.getId() == SMSG_NPC_NEXT) + { + nextDialog(npcId); + } + else + { + dialog = new NpcDialog(npcId); + Wrapper wrap; + wrap.dialog = dialog; + mNpcDialogs[npcId] = wrap; + } + } + else + { + dialog = diag->second.dialog; + } switch (msg.getId()) { case SMSG_NPC_CHOICE: - msg.readInt16(); // length - current_npc = msg.readInt32(); - npcDialog->setNpc(current_npc); - npcDialog->choiceRequest(); - npcDialog->parseListItems(msg.readString(msg.getLength() - 8)); - npcDialog->setVisible(true); - resetPlayer = true; + dialog->choiceRequest(); + dialog->parseListItems(msg.readString(msg.getLength() - 8)); break; case SMSG_NPC_MESSAGE: - msg.readInt16(); // length - current_npc = msg.readInt32(); - npcDialog->setNpc(current_npc); - npcDialog->addText(msg.readString(msg.getLength() - 8)); - npcDialog->setVisible(true); - resetPlayer = true; + dialog->addText(msg.readString(msg.getLength() - 8)); break; case SMSG_NPC_CLOSE: - id = msg.readInt32(); - // If we're talking to that NPC, show the close button - if (id == current_npc) - { - npcDialog->showCloseButton(); - resetPlayer = true; - } - // Otherwise, move on as an empty dialog doesn't help - else - closeDialog(id); + // Show the close button + dialog->showCloseButton(); break; case SMSG_NPC_NEXT: - id = msg.readInt32(); - // If we're talking to that NPC, show the next button - if (id == current_npc) - { - npcDialog->showNextButton(); - resetPlayer = true; - } - // Otherwise, move on as an empty dialog doesn't help - else - nextDialog(id); + // Show the next button + dialog->showNextButton(); break; case SMSG_NPC_INT_INPUT: // Request for an integer - current_npc = msg.readInt32(); - npcDialog->setNpc(current_npc); - npcDialog->integerRequest(0); - npcDialog->setVisible(true); - resetPlayer = true; + dialog->integerRequest(0); break; case SMSG_NPC_STR_INPUT: // Request for a string - current_npc = msg.readInt32(); - npcDialog->setNpc(current_npc); - npcDialog->textRequest(""); - npcDialog->setVisible(true); - resetPlayer = true; + dialog->textRequest(""); break; } @@ -147,8 +145,13 @@ void NpcHandler::closeDialog(int npcId) { MessageOut outMsg(CMSG_NPC_CLOSE); outMsg.writeInt32(npcId); - npcDialog->setText(""); - npcDialog->setVisible(false); + + NpcDialogs::iterator it = mNpcDialogs.find(npcId); + if (it != mNpcDialogs.end()) + { + (*it).second.dialog->close(); + mNpcDialogs.erase(it); + } } void NpcHandler::listInput(int npcId, int value) diff --git a/src/net/ea/npchandler.h b/src/net/ea/npchandler.h index a42b88c5..072c97e3 100644 --- a/src/net/ea/npchandler.h +++ b/src/net/ea/npchandler.h @@ -27,6 +27,10 @@ #include "net/ea/messagehandler.h" +#include <map> + +class NpcDialog; + namespace EAthena { class NpcHandler : public MessageHandler, public Net::NpcHandler @@ -62,6 +66,13 @@ class NpcHandler : public MessageHandler, public Net::NpcHandler void sellItem(int beingId, int itemId, int amount); void endShopping(int beingId); + + private: + typedef struct { + NpcDialog* dialog; + } Wrapper; + typedef std::map<int, Wrapper> NpcDialogs; + NpcDialogs mNpcDialogs; }; } // namespace EAthena diff --git a/src/net/ea/playerhandler.cpp b/src/net/ea/playerhandler.cpp index 7fb4dab9..34e0daf4 100644 --- a/src/net/ea/playerhandler.cpp +++ b/src/net/ea/playerhandler.cpp @@ -80,15 +80,15 @@ namespace { { Net::getPlayerHandler()->respawn(); deathNotice = NULL; - buyDialog->setVisible(false); - sellDialog->setVisible(false); - buySellDialog->setVisible(false); + + BuyDialog::closeAll(); + BuySellDialog::closeAll(); + NpcDialog::closeAll(); + SellDialog::closeAll(); if (storageWindow->isVisible()) storageWindow->close(); viewport->closePopupMenu(); - npcDialog->closeDialog(); - current_npc = 0; } } deathListener; diff --git a/src/net/manaserv/buysellhandler.cpp b/src/net/manaserv/buysellhandler.cpp index e98dce98..9b7c0863 100644 --- a/src/net/manaserv/buysellhandler.cpp +++ b/src/net/manaserv/buysellhandler.cpp @@ -26,17 +26,14 @@ #include "localplayer.h" #include "npc.h" -#include "net/messagein.h" - -#include "net/manaserv/protocol.h" - #include "gui/buy.h" #include "gui/chat.h" #include "gui/sell.h" -extern BuyDialog *buyDialog; -extern SellDialog *sellDialog; -extern Window *buySellDialog; +#include "net/messagein.h" + +#include "net/manaserv/protocol.h" + namespace ManaServ { @@ -58,37 +55,43 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg) return; } - current_npc = being->getId(); + int npcId = being->getId(); switch (msg.getId()) { case GPMSG_NPC_BUY: - buyDialog->reset(); - buyDialog->setMoney(player_node->getMoney()); - buyDialog->setVisible(true); + { + BuyDialog* dialog = new BuyDialog(npcId); + + dialog->reset(); + dialog->setMoney(player_node->getMoney()); while (msg.getUnreadLength()) { int itemId = msg.readInt16(); int amount = msg.readInt16(); int value = msg.readInt16(); - buyDialog->addItem(itemId, amount, value); + dialog->addItem(itemId, amount, value); } break; + } case GPMSG_NPC_SELL: - sellDialog->setMoney(player_node->getMoney()); - sellDialog->reset(); - sellDialog->setVisible(true); + { + SellDialog* dialog = new SellDialog(npcId); + + dialog->reset(); + dialog->setMoney(player_node->getMoney()); while (msg.getUnreadLength()) { int itemId = msg.readInt16(); int amount = msg.readInt16(); int value = msg.readInt16(); - sellDialog->addItem(new Item(itemId, amount, false), value); + dialog->addItem(new Item(itemId, amount, false), value); } break; + } } } diff --git a/src/net/manaserv/npchandler.cpp b/src/net/manaserv/npchandler.cpp index 4e1a4f95..00f3a338 100644 --- a/src/net/manaserv/npchandler.cpp +++ b/src/net/manaserv/npchandler.cpp @@ -62,16 +62,29 @@ void NpcHandler::handleMessage(Net::MessageIn &msg) return; } - current_npc = being->getId(); - npcDialog->setNpc(current_npc); + int npcId = being->getId(); + NpcDialogs::iterator diag = mNpcDialogs.find(npcId); + NpcDialog *dialog; + + if (diag == mNpcDialogs.end()) + { + dialog = new NpcDialog(npcId); + Wrapper wrap; + wrap.dialog = dialog; + mNpcDialogs[npcId] = wrap; + } + else + { + dialog = diag->second.dialog; + } switch (msg.getId()) { case GPMSG_NPC_CHOICE: - npcDialog->choiceRequest(); + dialog->choiceRequest(); while (msg.getUnreadLength()) { - npcDialog->addChoice(msg.readString()); + dialog->addChoice(msg.readString()); } break; @@ -79,32 +92,35 @@ void NpcHandler::handleMessage(Net::MessageIn &msg) { int min_num = msg.readInt32(); int max_num = msg.readInt32(); - npcDialog->integerRequest(msg.readInt32(), min_num, max_num); + dialog->integerRequest(msg.readInt32(), min_num, max_num); break; } case GPMSG_NPC_STRING: - npcDialog->textRequest(""); + dialog->textRequest(""); break; case GPMSG_NPC_POST: - npcDialog->setVisible(false); - npcPostDialog->clear(); - npcPostDialog->setVisible(true); + { + new NpcPostDialog(npcId); break; + } case GPMSG_NPC_ERROR: - current_npc = NULL; + dialog->close(); + if (diag != mNpcDialogs.end()) + { + mNpcDialogs.erase(diag); + } break; case GPMSG_NPC_MESSAGE: - npcDialog->addText(msg.readString(msg.getUnreadLength())); - npcDialog->showNextButton(); - npcDialog->setVisible(true); + dialog->addText(msg.readString(msg.getUnreadLength())); + dialog->showNextButton(); break; case GPMSG_NPC_CLOSE: - npcDialog->showCloseButton(); + dialog->showCloseButton(); break; } } @@ -129,8 +145,12 @@ void NpcHandler::closeDialog(int npcId) msg.writeInt16(npcId); gameServerConnection->send(msg); - npcDialog->setVisible(false); - npcDialog->setText(""); + NpcDialogs::iterator it = mNpcDialogs.find(npcId); + if (it != mNpcDialogs.end()) + { + (*it).second.dialog->close(); + mNpcDialogs.erase(it); + } } void NpcHandler::listInput(int npcId, int value) diff --git a/src/net/manaserv/npchandler.h b/src/net/manaserv/npchandler.h index 8f353e5d..4b18487c 100644 --- a/src/net/manaserv/npchandler.h +++ b/src/net/manaserv/npchandler.h @@ -26,7 +26,9 @@ #include "net/manaserv/messagehandler.h" -#include <list> +#include <map> + +class NpcDialog; namespace ManaServ { @@ -63,6 +65,13 @@ class NpcHandler : public MessageHandler, public Net::NpcHandler void sellItem(int beingId, int itemId, int amount); void endShopping(int beingId); + + private: + typedef struct { + NpcDialog* dialog; + } Wrapper; + typedef std::map<int, Wrapper> NpcDialogs; + NpcDialogs mNpcDialogs; }; } // namespace ManaServ diff --git a/src/net/manaserv/playerhandler.cpp b/src/net/manaserv/playerhandler.cpp index 23158cc5..bff9512e 100644 --- a/src/net/manaserv/playerhandler.cpp +++ b/src/net/manaserv/playerhandler.cpp @@ -29,11 +29,9 @@ #include "particle.h" #include "npc.h" -#include "gui/buy.h" #include "gui/chat.h" #include "gui/gui.h" #include "gui/okdialog.h" -#include "gui/sell.h" #include "gui/viewport.h" #include "net/net.h" @@ -43,13 +41,6 @@ #include "net/manaserv/messageout.h" #include "net/manaserv/protocol.h" -extern OkDialog *weightNotice; -extern OkDialog *deathNotice; - -extern BuyDialog *buyDialog; -extern SellDialog *sellDialog; -extern Window *buySellDialog; - /** @see in game.cpp */ extern const int MILLISECONDS_IN_A_TICK; @@ -61,38 +52,6 @@ extern const int MILLISECONDS_IN_A_TICK; */ static const int MAP_TELEPORT_SCROLL_DISTANCE = 8 * 32; -/** - * Listener used for handling the overweigth message. - */ -// TODO Move somewhere else -namespace { - struct WeightListener : public gcn::ActionListener - { - void action(const gcn::ActionEvent &event) - { - weightNotice = NULL; - } - } weightListener; -} - -/** - * Listener used for handling death message. - */ -// TODO Move somewhere else -namespace { - struct DeathListener : public gcn::ActionListener - { - void action(const gcn::ActionEvent &event) - { - Net::getPlayerHandler()->respawn(); - deathNotice = NULL; - buyDialog->setVisible(false); - sellDialog->setVisible(false); - current_npc = 0; - } - } deathListener; -} - extern Net::PlayerHandler *playerHandler; namespace ManaServ { @@ -313,8 +272,6 @@ void PlayerHandler::handleMapChangeMessage(Net::MessageIn &msg) // Switch the actual map, deleting the previous one game->changeMap(mapName); - current_npc = 0; - const Vector &playerPos = player_node->getPosition(); float scrollOffsetX = 0.0f; float scrollOffsetY = 0.0f; |