From d8bc3a6418c5027d7f6c42ce8f8dceca8dee8971 Mon Sep 17 00:00:00 2001 From: Ira Rice Date: Wed, 25 Feb 2009 00:50:33 -0700 Subject: Fixed up NPC list dialogs to be navigatable by keyboard (scrolling through the list requires the use of the mouse wheel at the moment), fixed wrapping behavior for wrapping around lists to actually wrap around lists properly, and placed a few checks for current_npc where they were assumed before which could cause the client to hang or crash in case the NPC is no longer around. Signed-off-by: Ira Rice --- src/gui/npcstringdialog.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/gui/npcstringdialog.cpp') diff --git a/src/gui/npcstringdialog.cpp b/src/gui/npcstringdialog.cpp index ef2de73a..140ca40f 100644 --- a/src/gui/npcstringdialog.cpp +++ b/src/gui/npcstringdialog.cpp @@ -64,7 +64,10 @@ void NpcStringDialog::action(const gcn::ActionEvent &event) } setVisible(false); - current_npc->stringInput(mValueField->getText()); + + if (current_npc) + current_npc->stringInput(mValueField->getText()); + current_npc = NULL; mValueField->setText(""); } -- cgit v1.2.3-70-g09d2 From 0dde31c3db09113639fa443142995b6efcff6646 Mon Sep 17 00:00:00 2001 From: Ira Rice Date: Wed, 25 Feb 2009 19:04:39 -0700 Subject: Fix NPC handling to not need a handle on the NPC Loosely based on TMW commit f04a8713ffc83db8b3dc4a472b28aad25a2b2bd1 Signed-off-by: Ira Rice --- src/beingmanager.cpp | 10 +++++++ src/beingmanager.h | 10 ++++++- src/game.cpp | 10 +++---- src/gui/buysell.cpp | 34 +++++++++++++++++------ src/gui/buysell.h | 7 ++++- src/gui/npc_text.cpp | 18 +++++++++--- src/gui/npc_text.h | 9 ++++-- src/gui/npcintegerdialog.cpp | 16 +++++++---- src/gui/npcintegerdialog.h | 4 ++- src/gui/npclistdialog.cpp | 16 +++++++---- src/gui/npclistdialog.h | 5 +++- src/gui/npcstringdialog.cpp | 22 +++++++++++---- src/gui/npcstringdialog.h | 5 +++- src/net/beinghandler.cpp | 13 ++++----- src/net/buysellhandler.cpp | 25 ++++++++++------- src/net/npchandler.cpp | 22 +++++++-------- src/net/playerhandler.cpp | 2 +- src/npc.cpp | 65 ++------------------------------------------ src/npc.h | 13 +++------ 19 files changed, 165 insertions(+), 141 deletions(-) (limited to 'src/gui/npcstringdialog.cpp') diff --git a/src/beingmanager.cpp b/src/beingmanager.cpp index b4ffa76c..d63e0dc5 100644 --- a/src/beingmanager.cpp +++ b/src/beingmanager.cpp @@ -253,3 +253,13 @@ Being* BeingManager::findNearestLivingBeing(Being *aroundBeing, int maxdist, return (maxdist >= dist) ? closestBeing : NULL; } + +bool BeingManager::hasBeing(Being *being) +{ + for (BeingIterator i = mBeings.begin(); i != mBeings.end(); i++) + { + if (being == *i) return true; + } + + return false; +} diff --git a/src/beingmanager.h b/src/beingmanager.h index 59a7c76a..32ba6242 100644 --- a/src/beingmanager.h +++ b/src/beingmanager.h @@ -99,13 +99,21 @@ class BeingManager */ Beings& getAll(); + /** + * Returns true if the given being is in the manager's list, false + * otherwise. + * + * \param being the being to search for + */ + bool hasBeing(Being *being); + /** * Logic. */ void logic(); /** - * Destroys all beings except the local player + * Destroys all beings except the local player and current NPC (if any) */ void clear(); diff --git a/src/game.cpp b/src/game.cpp index 16790cac..110b75cc 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -195,13 +195,13 @@ void createGuiWindows(Network *network) miniStatusWindow = new MiniStatusWindow(); buyDialog = new BuyDialog(network); sellDialog = new SellDialog(network); - buySellDialog = new BuySellDialog(); + buySellDialog = new BuySellDialog(network); inventoryWindow = new InventoryWindow(); emoteWindow = new EmoteWindow(); - npcTextDialog = new NpcTextDialog(); - npcIntegerDialog = new NpcIntegerDialog(); - npcListDialog = new NpcListDialog(); - npcStringDialog = new NpcStringDialog(); + npcTextDialog = new NpcTextDialog(network); + npcIntegerDialog = new NpcIntegerDialog(network); + npcListDialog = new NpcListDialog(network); + npcStringDialog = new NpcStringDialog(network); skillDialog = new SkillDialog(); setupWindow = new Setup(); minimap = new Minimap(); diff --git a/src/gui/buysell.cpp b/src/gui/buysell.cpp index 7d63f184..dc7deef6 100644 --- a/src/gui/buysell.cpp +++ b/src/gui/buysell.cpp @@ -25,10 +25,13 @@ #include "../npc.h" +#include "../net/messageout.h" +#include "../net/protocol.h" + #include "../utils/gettext.h" -BuySellDialog::BuySellDialog(): - Window(_("Shop")) +BuySellDialog::BuySellDialog(Network *network): + Window(_("Shop")), mNetwork(network) { Button *buyButton = 0; static const char *buttonNames[] = { @@ -54,12 +57,27 @@ BuySellDialog::BuySellDialog(): void BuySellDialog::action(const gcn::ActionEvent &event) { - if (event.getId() == "Buy") { - current_npc->buy(); - } else if (event.getId() == "Sell") { - current_npc->sell(); - } else if (event.getId() == "Cancel") { + setVisible(false); + int action = 0; + + NPC::mTalking = false; + + if (event.getId() == "Buy") + { + action = 0; + } + else if (event.getId() == "Sell") + { + action = 1; + } + else if (event.getId() == "Cancel") + { current_npc = 0; + return; } - setVisible(false); + + MessageOut outMsg(mNetwork); + outMsg.writeInt16(CMSG_NPC_BUY_SELL_REQUEST); + outMsg.writeInt32(current_npc); + outMsg.writeInt8(action); } diff --git a/src/gui/buysell.h b/src/gui/buysell.h index c12e3c9b..747066a7 100644 --- a/src/gui/buysell.h +++ b/src/gui/buysell.h @@ -27,6 +27,8 @@ #include "window.h" +class Network; + /** * A dialog to choose between buying or selling at a shop. * @@ -41,12 +43,15 @@ class BuySellDialog : public Window, public gcn::ActionListener * * @see Window::Window */ - BuySellDialog(); + BuySellDialog(Network *network); /** * Called when receiving actions from the widgets. */ void action(const gcn::ActionEvent &event); + + private: + Network *mNetwork; }; #endif diff --git a/src/gui/npc_text.cpp b/src/gui/npc_text.cpp index c28f1403..b94e8aa4 100644 --- a/src/gui/npc_text.cpp +++ b/src/gui/npc_text.cpp @@ -29,10 +29,13 @@ #include "../npc.h" +#include "../net/messageout.h" +#include "../net/protocol.h" + #include "../utils/gettext.h" -NpcTextDialog::NpcTextDialog(): - Window(_("NPC")) +NpcTextDialog::NpcTextDialog(Network *network): + Window(_("NPC")), mNetwork(network) { setResizable(true); @@ -87,12 +90,19 @@ void NpcTextDialog::action(const gcn::ActionEvent &event) setVisible(false); if (current_npc) - current_npc->nextDialog(); + nextDialog(); - current_npc = NULL; + current_npc = 0; } } +void NpcTextDialog::nextDialog(int npcID) +{ + MessageOut outMsg(mNetwork); + outMsg.writeInt16(CMSG_NPC_NEXT_REQUEST); + outMsg.writeInt32(npcID); +} + void NpcTextDialog::widgetResized(const gcn::Event &event) { Window::widgetResized(event); diff --git a/src/gui/npc_text.h b/src/gui/npc_text.h index 63d41cd6..a72de5d0 100644 --- a/src/gui/npc_text.h +++ b/src/gui/npc_text.h @@ -29,6 +29,9 @@ #include "window.h" +#include "../npc.h" + +class Network; class TextBox; /** @@ -44,7 +47,7 @@ class NpcTextDialog : public Window, public gcn::ActionListener * * @see Window::Window */ - NpcTextDialog(); + NpcTextDialog(Network *network); /** * Called when receiving actions from the widgets. @@ -71,6 +74,8 @@ class NpcTextDialog : public Window, public gcn::ActionListener */ void addText(const std::string &string); + void nextDialog(int npcID = current_npc); + /** * Called when resizing the window. * @@ -79,7 +84,7 @@ class NpcTextDialog : public Window, public gcn::ActionListener void widgetResized(const gcn::Event &event); private: - gcn::Button *okButton; + Network *mNetwork; gcn::ScrollArea *mScrollArea; TextBox *mTextBox; gcn::Button *mButton; diff --git a/src/gui/npcintegerdialog.cpp b/src/gui/npcintegerdialog.cpp index 9c49a630..132a7608 100644 --- a/src/gui/npcintegerdialog.cpp +++ b/src/gui/npcintegerdialog.cpp @@ -28,10 +28,13 @@ #include "../npc.h" +#include "../net/messageout.h" +#include "../net/protocol.h" + #include "../utils/gettext.h" -NpcIntegerDialog::NpcIntegerDialog(): - Window(_("NPC Number Request")) +NpcIntegerDialog::NpcIntegerDialog(Network *network): + Window(_("NPC Number Request")), mNetwork(network) { mValueField = new IntTextField(); @@ -104,11 +107,14 @@ void NpcIntegerDialog::action(const gcn::ActionEvent &event) if (finish) { setVisible(false); + NPC::mTalking = false; - if (current_npc) - current_npc->integerInput(mValueField->getValue()); + MessageOut outMsg(mNetwork); + outMsg.writeInt16(CMSG_NPC_INT_RESPONSE); + outMsg.writeInt32(current_npc); + outMsg.writeInt32(mValueField->getValue()); - current_npc = NULL; + current_npc = 0; mValueField->reset(); } } diff --git a/src/gui/npcintegerdialog.h b/src/gui/npcintegerdialog.h index cca8cb32..15bdee48 100644 --- a/src/gui/npcintegerdialog.h +++ b/src/gui/npcintegerdialog.h @@ -27,6 +27,7 @@ #include "window.h" +class Network; class IntTextField; /** @@ -42,7 +43,7 @@ class NpcIntegerDialog : public Window, public gcn::ActionListener * * @see Window::Window */ - NpcIntegerDialog(); + NpcIntegerDialog(Network *network); /** * Called when receiving actions from the widgets. @@ -78,6 +79,7 @@ class NpcIntegerDialog : public Window, public gcn::ActionListener void requestFocus(); private: + Network *mNetwork; gcn::Button *mDecButton; gcn::Button *mIncButton; IntTextField *mValueField; diff --git a/src/gui/npclistdialog.cpp b/src/gui/npclistdialog.cpp index 2c4dfc04..73b00239 100644 --- a/src/gui/npclistdialog.cpp +++ b/src/gui/npclistdialog.cpp @@ -31,10 +31,13 @@ #include "../npc.h" +#include "../net/messageout.h" +#include "../net/protocol.h" + #include "../utils/gettext.h" -NpcListDialog::NpcListDialog(): - Window(_("NPC")) +NpcListDialog::NpcListDialog(Network *network): + Window(_("NPC")), mNetwork(network) { setResizable(true); @@ -86,6 +89,7 @@ void NpcListDialog::parseItems(const std::string &itemString) void NpcListDialog::reset() { + NPC::mTalking = false; mItemList->setSelected(-1); mItems.clear(); } @@ -112,10 +116,12 @@ void NpcListDialog::action(const gcn::ActionEvent &event) setVisible(false); reset(); - if (current_npc) - current_npc->dialogChoice(choice); + MessageOut outMsg(mNetwork); + outMsg.writeInt16(CMSG_NPC_LIST_CHOICE); + outMsg.writeInt32(current_npc); + outMsg.writeInt8(choice); - current_npc = NULL; + current_npc = 0; } } diff --git a/src/gui/npclistdialog.h b/src/gui/npclistdialog.h index de3a7a77..0a0e9813 100644 --- a/src/gui/npclistdialog.h +++ b/src/gui/npclistdialog.h @@ -30,6 +30,8 @@ #include "window.h" +class Network; + /** * The npc list dialog. * @@ -44,7 +46,7 @@ class NpcListDialog : public Window, public gcn::ActionListener, * * @see Window::Window */ - NpcListDialog(); + NpcListDialog(Network *network); /** * Called when receiving actions from the widgets. @@ -79,6 +81,7 @@ class NpcListDialog : public Window, public gcn::ActionListener, void requestFocus(); private: + Network *mNetwork; gcn::ListBox *mItemList; gcn::ScrollArea *scrollArea; gcn::Button *okButton; diff --git a/src/gui/npcstringdialog.cpp b/src/gui/npcstringdialog.cpp index 140ca40f..f2c7434c 100644 --- a/src/gui/npcstringdialog.cpp +++ b/src/gui/npcstringdialog.cpp @@ -28,10 +28,13 @@ #include "../npc.h" +#include "../net/messageout.h" +#include "../net/protocol.h" + #include "../utils/gettext.h" -NpcStringDialog::NpcStringDialog(): - Window(_("NPC Text Request")) +NpcStringDialog::NpcStringDialog(Network *network): + Window(_("NPC Text Request")), mNetwork(network) { mValueField = new TextField(""); @@ -64,12 +67,19 @@ void NpcStringDialog::action(const gcn::ActionEvent &event) } setVisible(false); + NPC::mTalking = false; - if (current_npc) - current_npc->stringInput(mValueField->getText()); - - current_npc = NULL; + std::string text = mValueField->getText(); mValueField->setText(""); + + MessageOut outMsg(mNetwork); + outMsg.writeInt16(CMSG_NPC_STR_RESPONSE); + outMsg.writeInt16(text.length() + 9); + outMsg.writeInt32(current_npc); + outMsg.writeString(text, text.length()); + outMsg.writeInt8(0); + + current_npc = 0; } bool NpcStringDialog::isInputFocused() diff --git a/src/gui/npcstringdialog.h b/src/gui/npcstringdialog.h index c8871184..ee620daf 100644 --- a/src/gui/npcstringdialog.h +++ b/src/gui/npcstringdialog.h @@ -27,6 +27,8 @@ #include "window.h" +class Network; + /** * The npc integer input dialog. * @@ -40,7 +42,7 @@ class NpcStringDialog : public Window, public gcn::ActionListener * * @see Window::Window */ - NpcStringDialog(); + NpcStringDialog(Network *network); /** * Called when receiving actions from the widgets. @@ -70,6 +72,7 @@ class NpcStringDialog : public Window, public gcn::ActionListener void requestFocus(); private: + Network *mNetwork; gcn::TextField *mValueField; gcn::Button *okButton; gcn::Button *cancelButton; diff --git a/src/net/beinghandler.cpp b/src/net/beinghandler.cpp index c11d22e7..bae14a05 100644 --- a/src/net/beinghandler.cpp +++ b/src/net/beinghandler.cpp @@ -196,7 +196,11 @@ void BeingHandler::handleMessage(MessageIn *msg) case SMSG_BEING_REMOVE: // A being should be removed or has died - dstBeing = beingManager->findBeing(msg->readInt32()); + id = msg->readInt32(); + dstBeing = beingManager->findBeing(id); + + if (id == current_npc) + current_npc = 0; if (!dstBeing) break; @@ -205,12 +209,7 @@ void BeingHandler::handleMessage(MessageIn *msg) if (dstBeing == player_node->getTarget()) player_node->stopAttack(); - if (dstBeing == current_npc) - current_npc = NULL; - - if (msg->readInt8() == 1) - dstBeing->setAction(Being::DEAD); - else + if (!(msg->readInt8() == 1)) beingManager->destroyBeing(dstBeing); break; diff --git a/src/net/buysellhandler.cpp b/src/net/buysellhandler.cpp index 245b8a50..e9255540 100644 --- a/src/net/buysellhandler.cpp +++ b/src/net/buysellhandler.cpp @@ -66,7 +66,7 @@ void BuySellHandler::handleMessage(MessageIn *msg) sellDialog->setVisible(false); sellDialog->reset(); buySellDialog->setVisible(true); - current_npc = dynamic_cast(beingManager->findBeing(msg->readInt32())); + current_npc = msg->readInt32(); break; case SMSG_NPC_BUY: @@ -89,7 +89,8 @@ void BuySellHandler::handleMessage(MessageIn *msg) case SMSG_NPC_SELL: msg->readInt16(); // length n_items = (msg->getLength() - 4) / 10; - if (n_items > 0) { + if (n_items > 0) + { sellDialog->setMoney(player_node->mGp); sellDialog->reset(); sellDialog->setVisible(true); @@ -101,21 +102,25 @@ void BuySellHandler::handleMessage(MessageIn *msg) msg->readInt32(); // OCvalue Item *item = player_node->getInventory()->getItem(index); - if (item && !(item->isEquipped())) { + + if (item && !(item->isEquipped())) sellDialog->addItem(item, value); - } } } - else { + else + { chatWindow->chatLog(_("Nothing to sell"), BY_SERVER); current_npc = 0; } break; case SMSG_NPC_BUY_RESPONSE: - if (msg->readInt8() == 0) { + if (msg->readInt8() == 0) + { chatWindow->chatLog(_("Thanks for buying"), BY_SERVER); - } else { + } + else + { // Reset player money since buy dialog already assumed purchase // would go fine buyDialog->setMoney(player_node->mGp); @@ -124,11 +129,11 @@ void BuySellHandler::handleMessage(MessageIn *msg) break; case SMSG_NPC_SELL_RESPONSE: - if (msg->readInt8() == 0) { + if (msg->readInt8() == 0) chatWindow->chatLog(_("Thanks for selling"), BY_SERVER); - } else { + else chatWindow->chatLog(_("Unable to sell"), BY_SERVER); - } + break; } } diff --git a/src/net/npchandler.cpp b/src/net/npchandler.cpp index a59ee814..1067a57e 100644 --- a/src/net/npchandler.cpp +++ b/src/net/npchandler.cpp @@ -20,6 +20,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include + #include "messagein.h" #include "npchandler.h" #include "protocol.h" @@ -49,15 +51,14 @@ NPCHandler::NPCHandler() void NPCHandler::handleMessage(MessageIn *msg) { - int id; + Uint32 id; switch (msg->getId()) { case SMSG_NPC_CHOICE: msg->readInt16(); // length - id = msg->readInt32(); + current_npc = msg->readInt32(); player_node->setAction(LocalPlayer::STAND); - current_npc = dynamic_cast(beingManager->findBeing(id)); npcListDialog->parseItems(msg->readString(msg->getLength() - 8)); npcListDialog->setVisible(true); npcListDialog->requestFocus(); @@ -65,17 +66,16 @@ void NPCHandler::handleMessage(MessageIn *msg) case SMSG_NPC_MESSAGE: msg->readInt16(); // length - id = msg->readInt32(); + current_npc = msg->readInt32(); player_node->setAction(LocalPlayer::STAND); - current_npc = dynamic_cast(beingManager->findBeing(id)); npcTextDialog->addText(msg->readString(msg->getLength() - 8)); npcTextDialog->setVisible(true); break; case SMSG_NPC_CLOSE: id = msg->readInt32(); - if (current_npc == dynamic_cast(beingManager->findBeing(id))) - current_npc = NULL; + if (current_npc == id) + current_npc = 0; break; case SMSG_NPC_NEXT: @@ -84,8 +84,8 @@ void NPCHandler::handleMessage(MessageIn *msg) case SMSG_NPC_INT_INPUT: // Request for an integer - id = msg->readInt32(); - current_npc = dynamic_cast(beingManager->findBeing(id)); + current_npc = msg->readInt32(); + player_node->setAction(LocalPlayer::STAND); npcIntegerDialog->setRange(0, 2147483647); npcIntegerDialog->setVisible(true); npcIntegerDialog->requestFocus(); @@ -93,8 +93,8 @@ void NPCHandler::handleMessage(MessageIn *msg) case SMSG_NPC_STR_INPUT: // Request for a string - id = msg->readInt32(); - current_npc = dynamic_cast(beingManager->findBeing(id)); + current_npc = msg->readInt32(); + player_node->setAction(LocalPlayer::STAND); npcStringDialog->setValue(""); npcStringDialog->setVisible(true); npcStringDialog->requestFocus(); diff --git a/src/net/playerhandler.cpp b/src/net/playerhandler.cpp index f18c5d82..ffeb3fab 100644 --- a/src/net/playerhandler.cpp +++ b/src/net/playerhandler.cpp @@ -92,7 +92,7 @@ namespace { buyDialog->setVisible(false); sellDialog->setVisible(false); buySellDialog->setVisible(false); - current_npc = NULL; + current_npc = 0; } } deathListener; } diff --git a/src/npc.cpp b/src/npc.cpp index 832e6926..92ef4d82 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -21,6 +21,7 @@ */ #include "animatedsprite.h" +#include "beingmanager.h" #include "npc.h" #include "particle.h" #include "text.h" @@ -32,8 +33,8 @@ #include "resources/npcdb.h" -NPC *current_npc = 0; bool NPC::mTalking = false; +Uint32 current_npc = 0; static const int NAME_X_OFFSET = 15; static const int NAME_Y_OFFSET = 30; @@ -117,68 +118,6 @@ void NPC::talk() outMsg.writeInt8(0); } -void NPC::nextDialog() -{ - if (!mNetwork) - return; - - MessageOut outMsg(mNetwork); - outMsg.writeInt16(CMSG_NPC_NEXT_REQUEST); - outMsg.writeInt32(mId); -} - -void NPC::dialogChoice(char choice) -{ - MessageOut outMsg(mNetwork); - outMsg.writeInt16(CMSG_NPC_LIST_CHOICE); - outMsg.writeInt32(mId); - outMsg.writeInt8(choice); -} - -void NPC::integerInput(int value) -{ - MessageOut outMsg(mNetwork); - outMsg.writeInt16(CMSG_NPC_INT_RESPONSE); - outMsg.writeInt32(mId); - outMsg.writeInt32(value); -} - -void NPC::stringInput(const std::string &value) -{ - MessageOut outMsg(mNetwork); - outMsg.writeInt16(CMSG_NPC_STR_RESPONSE); - outMsg.writeInt16(value.length() + 9); - outMsg.writeInt32(mId); - outMsg.writeString(value, value.length()); - outMsg.writeInt8(0); -} - -/* - * TODO Unify the buy() and sell() methods, without sacrificing readability of - * the code calling the method. buy(bool buySell) would be bad... - */ -void NPC::buy() -{ - if (!mNetwork) - return; - - MessageOut outMsg(mNetwork); - outMsg.writeInt16(CMSG_NPC_BUY_SELL_REQUEST); - outMsg.writeInt32(mId); - outMsg.writeInt8(0); -} - -void NPC::sell() -{ - if (!mNetwork) - return; - - MessageOut outMsg(mNetwork); - outMsg.writeInt16(CMSG_NPC_BUY_SELL_REQUEST); - outMsg.writeInt32(mId); - outMsg.writeInt8(1); -} - void NPC::updateCoords() { if (mName) diff --git a/src/npc.h b/src/npc.h index 0dc9c742..e1bf9737 100644 --- a/src/npc.h +++ b/src/npc.h @@ -23,6 +23,8 @@ #ifndef NPC_H #define NPC_H +#include + #include "player.h" class Network; @@ -42,14 +44,7 @@ class NPC : public Player virtual Type getType() const; - void talk(); - void nextDialog(); - void dialogChoice(char choice); - void integerInput(int value); - void stringInput(const std::string &value); - - void buy(); - void sell(); + void talk();; static bool mTalking; @@ -60,6 +55,6 @@ class NPC : public Player Text *mName; }; -extern NPC *current_npc; +extern Uint32 current_npc; #endif -- cgit v1.2.3-70-g09d2