diff options
-rw-r--r-- | src/being.cpp | 58 | ||||
-rw-r--r-- | src/being.h | 38 | ||||
-rw-r--r-- | src/engine.cpp | 12 | ||||
-rw-r--r-- | src/game.cpp | 91 | ||||
-rw-r--r-- | src/gui/buy.cpp | 233 | ||||
-rw-r--r-- | src/gui/buy.h | 10 | ||||
-rw-r--r-- | src/gui/inventorywindow.cpp | 13 | ||||
-rw-r--r-- | src/gui/item_amount.cpp | 16 | ||||
-rw-r--r-- | src/gui/item_amount.h | 1 | ||||
-rw-r--r-- | src/gui/itemcontainer.cpp | 2 | ||||
-rw-r--r-- | src/gui/popupmenu.cpp | 86 | ||||
-rw-r--r-- | src/gui/popupmenu.h | 7 | ||||
-rw-r--r-- | src/gui/sell.cpp | 191 | ||||
-rw-r--r-- | src/gui/sell.h | 9 | ||||
-rw-r--r-- | src/gui/updatewindow.cpp | 25 | ||||
-rw-r--r-- | src/gui/updatewindow.h | 7 | ||||
-rw-r--r-- | src/net/protocol.cpp | 4 |
17 files changed, 624 insertions, 179 deletions
diff --git a/src/being.cpp b/src/being.cpp index a6d700ea..0d1933bb 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -22,6 +22,7 @@ */ #include <sstream> +#include <iostream> #include "being.h" #include "log.h" @@ -75,7 +76,7 @@ void remove_node(unsigned int id) std::list<Being *>::iterator i; for (i = beings.begin(); i != beings.end(); i++) { - if ((*i)->id == id) + if ((*i)->getId() == id) { if (autoTarget == (*i)) { @@ -96,7 +97,7 @@ unsigned int findNpc(unsigned short x, unsigned short y) // Check if is a NPC (only low job ids) if (being->isNpc() && being->x == x && being->y == y) { - return being->id; + return being->getId(); } } return 0; @@ -109,7 +110,7 @@ unsigned int findPlayer(unsigned short x, unsigned short y) Being *being = (*i); // Check if is a player if (being->isPlayer() && being->x == x && being->y == y) { - return being->id; + return being->getId(); } } return 0; @@ -124,7 +125,7 @@ unsigned int findMonster(unsigned short x, unsigned short y) if (being->isMonster() && being->x == x && being->y == y && being->action != MONSTER_DEAD) { - return being->id; + return being->getId(); } } return 0; @@ -133,9 +134,9 @@ unsigned int findMonster(unsigned short x, unsigned short y) Being *findNode(unsigned int id) { std::list<Being*>::iterator i; - for (i = beings.begin(); i != beings.end(); i++) { + for (i = beings.begin(); i != beings.end(); i++) { Being *being = (*i); - if (being->id == id) { + if (being->getId() == id) { return being; } } @@ -167,7 +168,7 @@ void sort() { } Being::Being(): - id(0), job(0), + job(0), x(0), y(0), destX(0), destY(0), direction(0), action(0), frame(0), speech_color(0), @@ -175,8 +176,9 @@ Being::Being(): speed(150), emotion(0), emotion_time(0), text_x(0), text_y(0), - weapon(0), aspd(350), + m_weapon(0), + m_id(0), hairStyle(1), hairColor(1), speech_time(0), damage_time(0), @@ -406,3 +408,43 @@ bool Being::isMonster() { return job >= 1000 && job < 1200; } + +void Being::setWeapon(unsigned short weapon) +{ + m_weapon = weapon; +} + +void Being::setWeaponById(unsigned short weapon) +{ + switch (weapon) + { + case 529: // iron arrows + case 1199: // arrows + break; + + case 1200: // bow + case 530: // short bow + case 545: // forest bow + setWeapon(2); + break; + + case 521: // sharp knife + case 522: // dagger + case 536: // short sword + case 1201: // knife + setWeapon(1); + break; + + case 0: // unequip + setWeapon(0); + break; + + default: + logger->log("unknown item equiped : %d", weapon); + } +} + +void Being::setId(unsigned int id) +{ + m_id = id; +} diff --git a/src/being.h b/src/being.h index 990a1e4a..16273bdd 100644 --- a/src/being.h +++ b/src/being.h @@ -43,7 +43,6 @@ struct PATH_NODE { class Being { public: - unsigned int id; /**< Unique id */ unsigned short job; /**< Job (player job, npc, monster, ) */ unsigned short x, y; /**< Tile coordinates */ unsigned short destX, destY; /**< Destination tile coordinates */ @@ -57,7 +56,6 @@ class Being unsigned char emotion_time; /**< Time until emotion disappears */ unsigned int text_x, text_y; // temp solution to fix speech position - unsigned short weapon; char name[24]; /**< Name of character */ unsigned short aspd; /**< Attack speed */ @@ -156,12 +154,48 @@ class Being */ bool isMonster(); + // ACCES METHODS + + /** + * get the weapon picture id. + */ + unsigned short getWeapon() {return m_weapon;} + + /** + * get the sprite id. + */ + unsigned int getId() {return m_id;} + + // MODIFICATION METHODS + + /** + * set the weapon picture id. + * + * @param weapon : the picture id + */ + void setWeapon(unsigned short weapon); + + /** + * set the weapon picture id with the weapon id. + * + * @param weapon : the weapon id + */ + void setWeaponById(unsigned short weapon); + + /** + * set the sprite id. + */ + void setId(unsigned int id); + private: /** * Sets the new path for this being. */ void setPath(std::list<PATH_NODE> path); + unsigned short m_weapon; + unsigned int m_id; /**< Unique id */ + std::list<PATH_NODE> path; std::string speech; std::string damage; diff --git a/src/engine.cpp b/src/engine.cpp index f0df72a8..f290747e 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -412,16 +412,20 @@ void Engine::draw() int pf = being->frame + being->action; if (being->action == ATTACK) { - if (being->weapon > 0) - pf += 4 * (being->weapon - 1); + if (being->getWeapon() > 0) + pf += 4 * (being->getWeapon() - 1); } guiGraphics->drawImage(playerset->spriteset[pf + 16 * dir], being->text_x - 16, being->text_y - 32); - if (being->weapon != 0 && being->action == ATTACK) { + //if (being->action == ATTACK) + //{ + // std::cout << being->name << " " << being->getWeapon() << std::endl; + //} + if (being->getWeapon() != 0 && being->action == ATTACK) { Image *image = weaponset->spriteset[ - 16 * (being->weapon - 1) + 4 * being->frame + dir]; + 16 * (being->getWeapon() - 1) + 4 * being->frame + dir]; guiGraphics->drawImage(image, being->text_x - 64, being->text_y - 80); diff --git a/src/game.cpp b/src/game.cpp index bbb9d918..3d963421 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -165,7 +165,7 @@ void do_init() // Initialize beings player_node = new Being(); - player_node->id = account_ID; + player_node->setId(account_ID); player_node->x = startX; player_node->y = startY; player_node->speed = 150; @@ -176,7 +176,7 @@ void do_init() char_info->weapon = 2; } - player_node->weapon = char_info->weapon; + player_node->setWeapon(char_info->weapon); add_node(player_node); @@ -510,10 +510,10 @@ void do_input() if ((target->isNpc()) && (current_npc == 0)) { WFIFOW(0) = net_w_value(0x0090); - WFIFOL(2) = net_l_value(target->id); + WFIFOL(2) = net_l_value(target->getId()); WFIFOB(6) = 0; WFIFOSET(7); - current_npc = target->id; + current_npc = target->getId(); } // Monster default: attack else if (target->isMonster()) @@ -537,7 +537,7 @@ void do_input() else if (target->isPlayer()) { WFIFOW(0) = net_w_value(0x00e4); - WFIFOL(2) = net_l_value(target->id); + WFIFOL(2) = net_l_value(target->getId()); WFIFOSET(6); } } @@ -797,6 +797,7 @@ void do_parse() fclose(file); #endif // Parse packet based on their id + // std::cout << "packet " << id << std::endl; switch (id) { case SMSG_LOGIN_SUCCESS: @@ -880,7 +881,7 @@ void do_parse() if (being == NULL) { being = new Being(); - being->id = beingId; + being->setId(beingId); being->speed = RFIFOW(6); if (being->speed == 0) { // Else division by 0 when calculating frame @@ -892,9 +893,7 @@ void do_parse() being->x = get_x(RFIFOP(46)); being->y = get_y(RFIFOP(46)); being->direction = get_direction(RFIFOP(46)); - being->weapon = RFIFOW(18); - if (being->isPlayer()) - std::cout << RFIFOW(18) << std::endl; + being->setWeapon(RFIFOW(18)); add_node(being); } else @@ -903,6 +902,7 @@ void do_parse() being->x = get_x(RFIFOP(46)); being->y = get_y(RFIFOP(46)); being->direction = get_direction(RFIFOP(46)); + //being->setWeapon(RFIFOW(18)); being->frame = 0; being->walk_time = tick_time; being->action = STAND; @@ -940,7 +940,7 @@ void do_parse() if (being == NULL) { being = new Being(); - being->id = RFIFOL(2); + being->setId(RFIFOL(2)); being->job = RFIFOW(14); add_node(being); } @@ -954,8 +954,8 @@ void do_parse() being->direction = get_direction(RFIFOP(46)); being->walk_time = tick_time; being->frame = 0; - - logger->log("0x01d8% i %i", RFIFOW(18), RFIFOW(20)); + being->setWeaponById(RFIFOW(18)); + //logger->log("0x01d8% i %i", RFIFOW(18), RFIFOW(20)); if (RFIFOB(51) == 2) { @@ -970,7 +970,7 @@ void do_parse() if (being == NULL) { being = new Being(); - being->id = RFIFOL(2); + being->setId(RFIFOL(2)); being->job = RFIFOW(14); add_node(being); } @@ -982,8 +982,8 @@ void do_parse() being->destY = get_dest_y(RFIFOP(50)); being->speed = RFIFOW(6); being->job = RFIFOW(14); - being->weapon = RFIFOW(18); - being->setDestination( + //being->setWeapon(RFIFOW(18)); + being->setDestination( get_dest_x(RFIFOP(50)), get_dest_y(RFIFOP(50))); break; @@ -995,7 +995,7 @@ void do_parse() if (being == NULL) { being = new Being(); - being->id = RFIFOL(2); + being->setId(RFIFOL(2)); being->job = RFIFOW(14); add_node(being); } @@ -1007,6 +1007,7 @@ void do_parse() being->destX = get_dest_x(RFIFOP(50)); being->destY = get_dest_y(RFIFOP(50)); being->setHairStyle(RFIFOW(16)); + being->setWeaponById(RFIFOW(18)); being->setHairColor(RFIFOW(32)); being->setDestination( @@ -1299,7 +1300,7 @@ void do_parse() // Stop walking case 0x0088: // Disabled because giving some problems //if (being = findNode(RFIFOL(2))) { - // if (being->id!=player_node->id) { + // if (being->getId()!=player_node->getId()) { // char ids[20]; // sprintf(ids,"%i",RFIFOL(2)); // alert(ids,"","","","",0,0); @@ -1326,7 +1327,7 @@ void do_parse() being->setDamage(ss.str(), SPEECH_TIME); } - if (RFIFOL(2) != player_node->id) { // buggy + if (RFIFOL(2) != player_node->getId()) { // buggy being = findNode(RFIFOL(2)); if (being != NULL) { if (being->isPlayer()) { @@ -1382,7 +1383,7 @@ void do_parse() // Level up case 0x019b: logger->log("Level up"); - if (RFIFOL(2) == player_node->id) { + if (RFIFOL(2) == player_node->getId()) { sound.playSfx("sfx/levelup.ogg"); } break; @@ -1553,8 +1554,8 @@ void do_parse() being->setHairStyle(RFIFOB(7)); break; case 2: - being->weapon = RFIFOB(7); - break; + being->setWeapon(RFIFOB(7)); + break; case 6: being->setHairColor(RFIFOB(7)); break; @@ -1583,44 +1584,21 @@ void do_parse() item = inventory->getItem(RFIFOW(2)); item->setEquipped(true); equipment->setEquipment(position - 1, item); - - // Trick to use the proper graphic until I find - // the right packet - switch (item->getId()) { - case 521: - case 522: - case 536: - case 1201: - player_node->weapon = 1; - break; - case 530: - case 1200: - player_node->weapon = 2; - break; - } + player_node->setWeaponById(item->getId()); } } break; // Equipment related case 0x01d7: being = findNode(RFIFOL(2)); - if (being != NULL) { - case 529: - case 1199: - break; - case 521: - case 522: - case 530: - case 536: - case 1200: - case 1201: - being->weapon = 0; - break; + if (being != NULL) + { + being->setWeaponById(RFIFOW(7)); } - - logger->log("1d7 %i %i %i %i", RFIFOL(2), RFIFOB(6), RFIFOW(7), RFIFOW(9)); + //logger->log("1d7 %i %i %i %i", RFIFOL(2), RFIFOB(6), RFIFOW(7), RFIFOW(9)); break; - // Answer to unequip item + + // Answer to unequip item case 0x00ac: if (RFIFOB(6) == 0) chatWindow->chat_log("Unable to unequip.", BY_SERVER); @@ -1646,8 +1624,8 @@ void do_parse() case 536: case 1200: case 1201: - player_node->weapon = 0; - break; + player_node->setWeapon(0); + break; // TODO : why this break ? shouldn't a weapon by unequiped in inventory too ? default: equipment->removeEquipment(position - 1); break; @@ -1749,11 +1727,16 @@ void do_parse() case 0x0095: being = findNode(RFIFOL(2)); if (being) + { + //std::cout << RFIFOL(2) << " is " << RFIFOP(6) << std::endl; strcpy(being->name, RFIFOP(6)); + } break; + // Change in players look case 0x0119: - std::cout << RFIFOL(2) << " " << RFIFOW(6) << " " << RFIFOW(8) << " " << RFIFOW(10) << " " << RFIFOB(12) << std::endl; + //std::cout << RFIFOL(2) << " " << RFIFOW(6) << " " << RFIFOW(8) << " " << RFIFOW(10) << " " << RFIFOW(12) + //<< " " << RFIFOW(14) << " " << RFIFOW(16) << " " << RFIFOW(18) << " " << RFIFOW(20) << " end" << std::endl; // Manage non implemented packets default: logger->log("Unhandled packet: %x", id); diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp index 8d1986d5..74a18cf1 100644 --- a/src/gui/buy.cpp +++ b/src/gui/buy.cpp @@ -34,16 +34,17 @@ BuyDialog::BuyDialog(): Window("Buy"), - money(0) + m_money(0) { itemList = new ListBox(this); scrollArea = new ScrollArea(itemList); slider = new Slider(1.0); quantityLabel = new gcn::Label("0"); - moneyLabel = new gcn::Label("350 G"); - okButton = new Button("OK"); - cancelButton = new Button("Cancel"); - okButton->setEnabled(false); + moneyLabel = new gcn::Label("price : 0 G"); + increaseButton = new Button("+"); + decreaseButton = new Button("-"); + buyButton = new Button("Buy"); + quitButton = new Button("Quit"); itemNameLabel = new gcn::Label("Name:"); itemDescLabel = new gcn::Label("Description:"); @@ -51,42 +52,68 @@ BuyDialog::BuyDialog(): scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); scrollArea->setDimension(gcn::Rectangle(5, 5, 250, 110)); itemList->setDimension(gcn::Rectangle(5, 5, 238, 110)); + slider->setDimension(gcn::Rectangle(5, 120, 200, 10)); + slider->setEnabled(false); + quantityLabel->setPosition(215, 120); moneyLabel->setPosition(5, 133); - okButton->setPosition(180, 174); - cancelButton->setPosition(208, 174); + + increaseButton->setPosition(40, 174); + increaseButton->setSize(20, 20); + increaseButton->setEnabled(false); + + decreaseButton->setPosition(10, 174); + decreaseButton->setSize(20, 20); + decreaseButton->setEnabled(false); + + buyButton->setPosition(180, 174); + buyButton->setEnabled(false); + + quitButton->setPosition(212, 174); itemNameLabel->setDimension(gcn::Rectangle(5, 145, 240, 14)); itemDescLabel->setDimension(gcn::Rectangle(5, 157, 240, 14)); itemList->setEventId("item"); slider->setEventId("slider"); - okButton->setEventId("ok"); - cancelButton->setEventId("cancel"); + increaseButton->setEventId("+"); + decreaseButton->setEventId("-"); + buyButton->setEventId("buy"); + quitButton->setEventId("quit"); itemList->addActionListener(this); slider->addActionListener(this); - okButton->addActionListener(this); - cancelButton->addActionListener(this); + increaseButton->addActionListener(this); + decreaseButton->addActionListener(this); + buyButton->addActionListener(this); + quitButton->addActionListener(this); add(scrollArea); add(slider); add(quantityLabel); add(moneyLabel); - add(okButton); - add(cancelButton); + add(buyButton); + add(quitButton); + add(increaseButton); + add(decreaseButton); add(itemNameLabel); add(itemDescLabel); setLocationRelativeTo(getParent()); + + m_amountItems = 0; + m_maxItems = 0; + m_money = 0; } BuyDialog::~BuyDialog() { - delete cancelButton; - delete okButton; + delete increaseButton; + delete decreaseButton; + delete quitButton; + delete buyButton; delete moneyLabel; delete slider; delete itemList; @@ -97,17 +124,17 @@ BuyDialog::~BuyDialog() void BuyDialog::setMoney(int amount) { - money = amount; - std::stringstream ss; - ss << money << " G"; - moneyLabel->setCaption(ss.str()); - moneyLabel->adjustSize(); + m_money = amount; + //std::stringstream ss; + //ss << m_money << " G"; + //moneyLabel->setCaption(ss.str()); + //moneyLabel->adjustSize(); } void BuyDialog::reset() { shopInventory.clear(); - money = 0; + m_money = 0; } void BuyDialog::addItem(short id, int price) @@ -127,40 +154,145 @@ void BuyDialog::action(const std::string& eventId) { int selectedItem = itemList->getSelected(); - if (eventId == "slider" || eventId == "item") { - if (selectedItem > -1) { - int maxItems = money / shopInventory[selectedItem].price; - int numItems = (int)(slider->getValue() * maxItems); - std::stringstream ss; + std::stringstream oss; + + if (eventId == "item") + { + if (selectedItem > -1) + { + slider->setEnabled(true); + increaseButton->setEnabled(true); + m_amountItems = 0; + m_maxItems = m_money / shopInventory[selectedItem].price; + } + else + { + slider->setValue(0); + slider->setEnabled(false); + increaseButton->setEnabled(false); + decreaseButton->setEnabled(false); + buyButton->setEnabled(false); + m_amountItems = 0; + m_maxItems = 0; + } + } + else if (eventId == "slider" && selectedItem > -1) + { + m_amountItems = (int)(slider->getValue() * m_maxItems); - ss << numItems; - quantityLabel->setCaption(ss.str()); - quantityLabel->adjustSize(); + oss << m_amountItems; + quantityLabel->setCaption(oss.str()); + quantityLabel->adjustSize(); - okButton->setEnabled(numItems > 0); + oss.str(""); + oss << "price : " << m_amountItems * shopInventory[selectedItem].price << " G"; + moneyLabel->setCaption(oss.str()); + moneyLabel->adjustSize(); + + if (m_amountItems > 0) + { + buyButton->setEnabled(true); + decreaseButton->setEnabled(true); + } + else + { + buyButton->setEnabled(false); + decreaseButton->setEnabled(false); + } + + if (m_amountItems == m_maxItems) + { + increaseButton->setEnabled(false); } - else { - okButton->setEnabled(false); + else + { + increaseButton->setEnabled(true); } } - else if (eventId == "ok") { - if (selectedItem > -1) { + else if (eventId == "+" && selectedItem > -1) + { + assert(m_amountItems < m_maxItems); + m_amountItems++; + slider->setValue(double(m_amountItems)/double(m_maxItems)); + + decreaseButton->setEnabled(true); + buyButton->setEnabled(true); + if (m_amountItems == m_maxItems) + { + increaseButton->setEnabled(false); + } + + oss << m_amountItems; + quantityLabel->setCaption(oss.str()); + quantityLabel->adjustSize(); + + oss.str(""); + oss << "price : " << m_amountItems * shopInventory[selectedItem].price << " G"; + moneyLabel->setCaption(oss.str()); + moneyLabel->adjustSize(); + } + else if (eventId == "-" && selectedItem > -1) + { + assert(m_amountItems > 0); + m_amountItems--; + + slider->setValue(double(m_amountItems)/double(m_maxItems)); + + increaseButton->setEnabled(true); + if (m_amountItems == 0) + { + decreaseButton->setEnabled(false); + buyButton->setEnabled(false); + } + + oss << m_amountItems; + quantityLabel->setCaption(oss.str()); + quantityLabel->adjustSize(); + + oss.str(""); + oss << "price : " << m_amountItems * shopInventory[selectedItem].price << " G"; + moneyLabel->setCaption(oss.str()); + moneyLabel->adjustSize(); + } + else if (eventId == "buy" && selectedItem > -1) + { // Attempt purchase - int maxItems = money / shopInventory[selectedItem].price; - int amount = (int)(slider->getValue() * maxItems); - - if (amount > 0) { - WFIFOW(0) = net_w_value(0x00c8); - WFIFOW(2) = net_w_value(8); - WFIFOW(4) = net_w_value(amount); - WFIFOW(6) = net_w_value(shopInventory[selectedItem].id); - WFIFOSET(8); - } + assert(m_amountItems > 0 && m_amountItems <= m_maxItems); + assert(selectedItem >= 0 && selectedItem < int(shopInventory.size())); + + WFIFOW(0) = net_w_value(0x00c8); + WFIFOW(2) = net_w_value(8); + WFIFOW(4) = net_w_value(m_amountItems); + WFIFOW(6) = net_w_value(shopInventory[selectedItem].id); + WFIFOSET(8); + + // update money ! + m_money -= m_amountItems * shopInventory[selectedItem].price; + + if (m_amountItems == m_maxItems) + { + m_maxItems = 0; + slider->setEnabled(false); + increaseButton->setEnabled(false); } - setVisible(false); - current_npc = 0; + else + { + m_maxItems = m_money / shopInventory[selectedItem].price; + } + + decreaseButton->setEnabled(false); + buyButton->setEnabled(false); + + m_amountItems = 0; + slider->setValue(0); + quantityLabel->setCaption("O"); + quantityLabel->adjustSize(); + + moneyLabel->setCaption("price : 0 G"); + moneyLabel->adjustSize(); } - else if (eventId == "cancel") { + else if (eventId == "quit") + { setVisible(false); current_npc = 0; } @@ -190,3 +322,10 @@ std::string BuyDialog::getElementAt(int i) { return shopInventory[i].name; } + +namespace gcn +{ + ListModel::~ListModel() + { + } +} diff --git a/src/gui/buy.h b/src/gui/buy.h index 6ca66c7a..50c92acd 100644 --- a/src/gui/buy.h +++ b/src/gui/buy.h @@ -86,8 +86,10 @@ class BuyDialog : public Window, public gcn::ActionListener, std::string getElementAt(int i); private: - gcn::Button *okButton; - gcn::Button *cancelButton; + gcn::Button *buyButton; + gcn::Button *quitButton; + gcn::Button *increaseButton; + gcn::Button *decreaseButton; gcn::ListBox *itemList; gcn::ScrollArea *scrollArea; gcn::Label *itemNameLabel; @@ -98,7 +100,9 @@ class BuyDialog : public Window, public gcn::ActionListener, std::vector<ITEM_SHOP> shopInventory; - int money; + int m_money; + int m_amountItems; + int m_maxItems; }; extern BuyDialog *buyDialog; diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp index 06eb8ce0..377acc1f 100644 --- a/src/gui/inventorywindow.cpp +++ b/src/gui/inventorywindow.cpp @@ -22,8 +22,10 @@ */ #include "inventorywindow.h" +#include "popupmenu.h" #include "../playerinfo.h" #include "../inventory.h" +#include "../engine.h" #include "button.h" #include "scrollarea.h" #include "item_amount.h" @@ -141,6 +143,17 @@ void InventoryWindow::mouseClick(int x, int y, int button, int count) SomeText = "Description: " + item->getInfo()->getDescription(); itemDescriptionLabel->setCaption(SomeText); itemDescriptionLabel->adjustSize(); + + if (button == gcn::MouseInput::RIGHT) + { + /* + * convert relative to the window coordinates to + * absolute tile coordinates + */ + int mx = (x + getX()) / 32 + camera_x; + int my = (y + getY()) / 32 + camera_y; + popupMenu->showPopup(mx, my, item); + } } void InventoryWindow::mouseMotion(int mx, int my) diff --git a/src/gui/item_amount.cpp b/src/gui/item_amount.cpp index eb3a4c5c..51b67e72 100644 --- a/src/gui/item_amount.cpp +++ b/src/gui/item_amount.cpp @@ -25,6 +25,7 @@ #include "inventorywindow.h" #include "trade.h" #include "button.h" +#include "slider.h" ItemAmountWindow::ItemAmountWindow(int usage, Window *parent): Window("Select amount of items to drop.", true, parent) @@ -35,14 +36,17 @@ ItemAmountWindow::ItemAmountWindow(int usage, Window *parent): // New buttons itemAmountMinusButton = new Button("-"); itemAmountPlusButton = new Button("+"); + itemAmountSlide = new Slider(1.0); itemAmountOkButton = new Button("Okay"); itemAmountCancelButton = new Button("Cancel"); itemAmountTextBox->setRange(1, inventoryWindow->getItem()->getQuantity()); + itemAmountSlide->setDimension(gcn::Rectangle(5, 120, 180, 10)); // Set button events Id itemAmountMinusButton->setEventId("Minus"); itemAmountPlusButton->setEventId("Plus"); + itemAmountSlide->setEventId("Slide"); itemAmountOkButton->setEventId("Drop"); itemAmountCancelButton->setEventId("Cancel"); @@ -51,18 +55,21 @@ ItemAmountWindow::ItemAmountWindow(int usage, Window *parent): itemAmountTextBox->setSize(24, 16); itemAmountPlusButton->setPosition(60, 5); itemAmountMinusButton->setPosition(10, 5); - itemAmountOkButton->setPosition(10, 40); - itemAmountCancelButton->setPosition(60, 40); + itemAmountSlide->setPosition(10, 35); + itemAmountOkButton->setPosition(10, 50); + itemAmountCancelButton->setPosition(60, 50); // Assemble add(itemAmountTextBox); add(itemAmountPlusButton); add(itemAmountMinusButton); + add(itemAmountSlide); add(itemAmountOkButton); add(itemAmountCancelButton); itemAmountPlusButton->addActionListener(this); itemAmountMinusButton->addActionListener(this); + itemAmountSlide->addActionListener(this); itemAmountOkButton->addActionListener(this); itemAmountCancelButton->addActionListener(this); @@ -90,6 +97,7 @@ ItemAmountWindow::~ItemAmountWindow() delete itemAmountTextBox; delete itemAmountPlusButton; delete itemAmountMinusButton; + delete itemAmountSlide; delete itemAmountOkButton; delete itemAmountCancelButton; } @@ -124,5 +132,9 @@ void ItemAmountWindow::action(const std::string& eventId) { itemAmountTextBox->setInt(itemAmountTextBox->getInt() - 1); } + else if (eventId == "Slide") + { + itemAmountTextBox->setInt(itemAmountSlide->getValue()*inventoryWindow->getItem()->getQuantity()); + } } diff --git a/src/gui/item_amount.h b/src/gui/item_amount.h index 0055ab04..add2a66c 100644 --- a/src/gui/item_amount.h +++ b/src/gui/item_amount.h @@ -68,6 +68,7 @@ class ItemAmountWindow : public Window, public gcn::ActionListener */ gcn::Button *itemAmountPlusButton; gcn::Button *itemAmountMinusButton; + gcn::Slider *itemAmountSlide; gcn::Button *itemAmountOkButton; gcn::Button *itemAmountCancelButton; }; diff --git a/src/gui/itemcontainer.cpp b/src/gui/itemcontainer.cpp index bda9f786..8fd3a23e 100644 --- a/src/gui/itemcontainer.cpp +++ b/src/gui/itemcontainer.cpp @@ -154,7 +154,7 @@ void ItemContainer::mousePress(int mx, int my, int button) int w = getWidth(); int columns = w / gridWidth; - if (button == gcn::MouseInput::LEFT) + if (button == gcn::MouseInput::LEFT || gcn::MouseInput::RIGHT) { int index = mx / gridWidth + ((my / gridHeight) * columns) + 2; diff --git a/src/gui/popupmenu.cpp b/src/gui/popupmenu.cpp index dbaa1e70..d47fe340 100644 --- a/src/gui/popupmenu.cpp +++ b/src/gui/popupmenu.cpp @@ -23,12 +23,16 @@ #include "popupmenu.h" #include "gui.h" +#include "inventorywindow.h" +#include "item_amount.h" #include "../graphics.h" #include "../game.h" #include "../engine.h" #include "../net/network.h" #include "../resources/itemmanager.h" -#include <iostream> +#include "../item.h" +#include "../inventory.h" + PopupMenu::PopupMenu(): Window() @@ -106,6 +110,7 @@ void PopupMenu::showPopup(int mx, int my) my -= (getHeight() + 50); setPosition(mx, my); setVisible(true); + requestMoveToTop(); } void PopupMenu::handleLink(const std::string& link) @@ -115,17 +120,17 @@ void PopupMenu::handleLink(const std::string& link) (current_npc == 0)) { WFIFOW(0) = net_w_value(0x0090); - WFIFOL(2) = net_l_value(being->id); + WFIFOL(2) = net_l_value(being->getId()); WFIFOB(6) = 0; WFIFOSET(7); - current_npc = being->id; + current_npc = being->getId(); } // Trade action else if ((link == "trade") && being && being->isPlayer()) { WFIFOW(0) = net_w_value(0x00e4); - WFIFOL(2) = net_l_value(being->id); + WFIFOL(2) = net_l_value(being->getId()); WFIFOSET(6); } /* @@ -157,6 +162,38 @@ void PopupMenu::handleLink(const std::string& link) { } + else if (link == "use") + { + assert(m_item); + if (m_item->isEquipment()) + { + if (m_item->isEquipped()) + { + inventory->unequipItem(m_item); + } + else + { + inventory->equipItem(m_item); + } + } + else + { + inventory->useItem(m_item); + } + } + + else if (link == "drop") + { + new ItemAmountWindow(AMOUNT_ITEM_DROP, inventoryWindow); + } + + else if (link == "description") + { + // do nothing for now, I need to write + // a window for the description first + ; + } + // Unknown actions else { @@ -165,8 +202,49 @@ 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(); + being = NULL; floorItem = NULL; + m_item = NULL; mX = -1; mY = -1; } + +void PopupMenu::showPopup(int mx, int my, Item *item) +{ + assert(item); + m_item = item; + browserBox->clearRows(); + + if (item->isEquipment()) + { + if (item->isEquipped()) + browserBox->addRow("@@use|Unequip@@"); + else + browserBox->addRow("@@use|Equip@@"); + } + else + browserBox->addRow("@@use|Use@@"); + + browserBox->addRow("@@drop|Drop@@"); + browserBox->addRow("@@description|Description@@"); + browserBox->addRow("##3---"); + browserBox->addRow("@@cancel|Cancel@@"); + + setContentSize(browserBox->getWidth() + 8, browserBox->getHeight() + 8); + mx = (mx - camera_x) * 32 + 25; + my = (my - camera_y) * 32 + 25; + if (guiGraphics->getWidth() < (mx + getWidth() + 5)) + mx -= (getWidth() + 50); + if (guiGraphics->getHeight() < (my + getHeight() + 5)) + my -= (getHeight() + 50); + setPosition(mx, my); + setVisible(true); + requestMoveToTop(); +} + diff --git a/src/gui/popupmenu.h b/src/gui/popupmenu.h index cfafc739..45c5c446 100644 --- a/src/gui/popupmenu.h +++ b/src/gui/popupmenu.h @@ -53,6 +53,11 @@ class PopupMenu : public Window, public LinkHandler void showPopup(int mx, int my); /** + * Shows the related popup menu when right click on the inventory + */ + void showPopup(int mx, int my, class Item *item); + + /** * Handles link action. */ void handleLink(const std::string& link); @@ -63,6 +68,8 @@ class PopupMenu : public Window, public LinkHandler Being* being; FloorItem* floorItem; + + class Item *m_item; }; extern PopupMenu *popupMenu; diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp index 26487b9a..bc1fe2e8 100644 --- a/src/gui/sell.cpp +++ b/src/gui/sell.cpp @@ -39,42 +39,69 @@ SellDialog::SellDialog(): scrollArea = new ScrollArea(itemList); slider = new Slider(1.0); quantityLabel = new gcn::Label("0"); - okButton = new Button("OK"); - cancelButton = new Button("Cancel"); - okButton->setEnabled(false); + increaseButton = new Button("+"); + decreaseButton = new Button("-"); + sellButton = new Button("Sell"); + quitButton = new Button("Quit"); + sellButton->setEnabled(false); setContentSize(260, 175); scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); scrollArea->setDimension(gcn::Rectangle(5, 5, 250, 110)); itemList->setDimension(gcn::Rectangle(5, 5, 238, 110)); + slider->setDimension(gcn::Rectangle(5, 120, 200, 10)); + slider->setEnabled(false); + quantityLabel->setPosition(215, 120); - okButton->setPosition(180, 145); - cancelButton->setPosition(208, 145); + + increaseButton->setPosition(40, 145); + increaseButton->setSize(20, 20); + increaseButton->setEnabled(false); + + decreaseButton->setPosition(10, 145); + decreaseButton->setSize(20, 20); + decreaseButton->setEnabled(false); + + sellButton->setPosition(175, 145); + sellButton->setEnabled(false); + + quitButton->setPosition(208, 145); itemList->setEventId("item"); slider->setEventId("slider"); - okButton->setEventId("ok"); - cancelButton->setEventId("cancel"); + increaseButton->setEventId("+"); + decreaseButton->setEventId("-"); + sellButton->setEventId("sell"); + quitButton->setEventId("quit"); itemList->addActionListener(this); slider->addActionListener(this); - okButton->addActionListener(this); - cancelButton->addActionListener(this); + increaseButton->addActionListener(this); + decreaseButton->addActionListener(this); + sellButton->addActionListener(this); + quitButton->addActionListener(this); add(scrollArea); add(slider); add(quantityLabel); - add(okButton); - add(cancelButton); + add(increaseButton); + add(decreaseButton); + add(sellButton); + add(quitButton); setLocationRelativeTo(getParent()); + + m_maxItems = 0; + m_amountItems = 0; } SellDialog::~SellDialog() { - delete cancelButton; - delete okButton; + delete increaseButton; + delete decreaseButton; + delete quitButton; + delete sellButton; delete slider; delete itemList; delete scrollArea; @@ -84,6 +111,7 @@ void SellDialog::reset() { shopInventory.clear(); slider->setValue(0.0); + m_amountItems = 0; quantityLabel->setCaption("0"); quantityLabel->adjustSize(); } @@ -111,41 +139,124 @@ void SellDialog::addItem(short index, int price) void SellDialog::action(const std::string& eventId) { int selectedItem = itemList->getSelected(); + std::stringstream oss; - if (eventId == "slider" || eventId == "item") { - if (selectedItem > -1) { - int maxItems = shopInventory[selectedItem].quantity; - int numItems = (int)(slider->getValue() * maxItems); - std::stringstream ss; + if (eventId == "item") + { + if (selectedItem > -1) + { + slider->setEnabled(true); + increaseButton->setEnabled(true); - ss << numItems; - quantityLabel->setCaption(ss.str()); - quantityLabel->adjustSize(); + m_maxItems = shopInventory[selectedItem].quantity; + m_amountItems = 0; + } + else + { + slider->setValue(0); + slider->setEnabled(false); + increaseButton->setEnabled(false); + decreaseButton->setEnabled(false); + sellButton->setEnabled(false); + m_amountItems = 0; + } + } + else if (eventId == "slider" && selectedItem > -1) + { + m_amountItems = (int)(slider->getValue() * m_maxItems); + + oss << m_amountItems; + quantityLabel->setCaption(oss.str()); + quantityLabel->adjustSize(); - okButton->setEnabled(numItems > 0); + if (m_amountItems > 0) + { + sellButton->setEnabled(true); + decreaseButton->setEnabled(true); } - else { - okButton->setEnabled(false); + else + { + sellButton->setEnabled(false); + decreaseButton->setEnabled(false); + } + + if (m_amountItems == m_maxItems) + { + increaseButton->setEnabled(false); + } + else + { + increaseButton->setEnabled(true); } } - else if (eventId == "ok") { - if (selectedItem > -1) { - // Attempt sell - int maxItems = shopInventory[selectedItem].quantity; - int amount = (int)(slider->getValue() * maxItems); - - if (amount > 0) { - WFIFOW(0) = net_w_value(0x00c9); - WFIFOW(2) = net_w_value(8); - WFIFOW(4) = net_w_value(shopInventory[selectedItem].index); - WFIFOW(6) = net_w_value(amount); - WFIFOSET(8); - } + else if (eventId == "+" && selectedItem > -1) + { + assert(m_amountItems < m_maxItems); + m_amountItems++; + slider->setValue(double(m_amountItems)/double(m_maxItems)); + + decreaseButton->setEnabled(true); + sellButton->setEnabled(true); + if (m_amountItems == m_maxItems) + { + increaseButton->setEnabled(false); } - setVisible(false); - current_npc = 0; + + oss << m_amountItems; + quantityLabel->setCaption(oss.str()); + quantityLabel->adjustSize(); + } + else if (eventId == "-" && selectedItem > -1) + { + assert(m_amountItems > 0); + m_amountItems--; + + slider->setValue(double(m_amountItems)/double(m_maxItems)); + + increaseButton->setEnabled(true); + if (m_amountItems == 0) + { + decreaseButton->setEnabled(false); + sellButton->setEnabled(false); + } + + oss << m_amountItems; + quantityLabel->setCaption(oss.str()); + quantityLabel->adjustSize(); + } + else if (eventId == "sell" && selectedItem > -1) + { + // Attempt sell + assert(m_amountItems > 0 && m_amountItems <= m_maxItems); + assert(selectedItem >= 0 && selectedItem < int(shopInventory.size())); + + WFIFOW(0) = net_w_value(0x00c9); + WFIFOW(2) = net_w_value(8); + WFIFOW(4) = net_w_value(shopInventory[selectedItem].index); + WFIFOW(6) = net_w_value(m_amountItems); + WFIFOSET(8); + + if (m_amountItems == m_maxItems) + { + slider->setEnabled(false); + increaseButton->setEnabled(false); + shopInventory.erase(shopInventory.begin() += selectedItem); + } + else + { + m_maxItems = shopInventory[selectedItem].quantity - m_amountItems; + } + + decreaseButton->setEnabled(false); + sellButton->setEnabled(false); + + m_amountItems = 0; + slider->setValue(0); + quantityLabel->setCaption("O"); + quantityLabel->adjustSize(); } - else if (eventId == "cancel") { + else if (eventId == "quit") + { setVisible(false); current_npc = 0; } diff --git a/src/gui/sell.h b/src/gui/sell.h index 48617d17..e96eb712 100644 --- a/src/gui/sell.h +++ b/src/gui/sell.h @@ -76,8 +76,10 @@ class SellDialog : public Window, public gcn::ActionListener, std::string getElementAt(int i); private: - gcn::Button *okButton; - gcn::Button *cancelButton; + gcn::Button *sellButton; + gcn::Button *quitButton; + gcn::Button *increaseButton; + gcn::Button *decreaseButton; gcn::ListBox *itemList; gcn::ScrollArea *scrollArea; gcn::Label *moneyLabel; @@ -86,7 +88,8 @@ class SellDialog : public Window, public gcn::ActionListener, std::vector<ITEM_SHOP> shopInventory; - int maxItems; + int m_maxItems; + int m_amountItems; }; extern SellDialog *sellDialog; diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index 14a0afa6..29ea8e8a 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -35,19 +35,21 @@ #include <SDL_mutex.h> -UpdaterWindow::UpdaterWindow(const std::string& updateHost): +UpdaterWindow::UpdaterWindow(): Window("Updating...") { m_thread = NULL; m_mutex = NULL; m_downloadStatus = UPDATE_NEWS; - m_updateHost = updateHost; + m_updateHost = ""; m_currentFile = "news.txt"; m_downloadComplete = true; m_basePath = ""; m_storeInMemory = true; m_downloadedBytes = 0; m_memoryBuffer = NULL; + m_curlError = new char[CURL_ERROR_SIZE]; + m_curlError[0] = 0; int h = 300; int w = 320; @@ -83,6 +85,7 @@ UpdaterWindow::UpdaterWindow(const std::string& updateHost): UpdaterWindow::~UpdaterWindow() { + delete m_curlError; delete label; delete progressBar; delete cancelButton; @@ -218,24 +221,29 @@ int UpdaterWindow::downloadThread(void *ptr) curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, UpdaterWindow::memoryWrite); curl_easy_setopt(curl, CURLOPT_WRITEDATA, ptr); } - else { + else + { outFilename = uw->m_basePath + "/data/download.temp"; outfile = fopen(outFilename.c_str(), "wb"); curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile); } + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, uw->m_curlError); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, UpdaterWindow::updateProgress); curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, ptr); - res = curl_easy_perform(curl); + if ((res = curl_easy_perform(curl)) != 0) + { + uw->m_downloadStatus = UPDATE_ERROR; + std::cerr << "curl error " << res << " : " << uw->m_curlError << std::endl; + } curl_easy_cleanup(curl); uw->m_downloadComplete = true; - if (res != 0) { - uw->m_downloadStatus = UPDATE_ERROR; - } - else if (!uw->m_storeInMemory) { + + if (!uw->m_storeInMemory) + { fclose(outfile); // If the download was successful give the file the proper name // else it will be deleted later @@ -304,6 +312,7 @@ void UpdaterWindow::updateData() addRow("##1 The update process is incomplete."); addRow("##1 It is strongly recommended that"); addRow("##1 you try again later"); + addRow(m_curlError); m_downloadStatus = UPDATE_COMPLETE; break; case UPDATE_NEWS: diff --git a/src/gui/updatewindow.h b/src/gui/updatewindow.h index e48a1063..805d55df 100644 --- a/src/gui/updatewindow.h +++ b/src/gui/updatewindow.h @@ -42,7 +42,7 @@ class UpdaterWindow : public Window, public gcn::ActionListener /** * Constructor */ - UpdaterWindow(const std::string& updateHost = "themanaworld.org/files"); + UpdaterWindow(); /** * Destructor @@ -162,6 +162,11 @@ class UpdaterWindow : public Window, public gcn::ActionListener */ char *m_memoryBuffer; + /* + * buffer to handler human readable error provided by curl + */ + char *m_curlError; + std::string labelText; /**< Text for caption label */ gcn::Label *label; /**< Progress bar caption */ diff --git a/src/net/protocol.cpp b/src/net/protocol.cpp index fac6b11d..5a3fd487 100644 --- a/src/net/protocol.cpp +++ b/src/net/protocol.cpp @@ -272,9 +272,9 @@ void attack(Being *target) char_info->lastAttackTime = 0; player_node->action = ATTACK; - action(0, target->id); + action(0, target->getId()); player_node->walk_time = tick_time; - if (player_node->weapon == 2) + if (player_node->getWeapon() == 2) sound.playSfx("sfx/bow_shoot_1.ogg"); else sound.playSfx("sfx/fist-swish.ogg"); |