summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/being.cpp58
-rw-r--r--src/being.h38
-rw-r--r--src/engine.cpp12
-rw-r--r--src/game.cpp91
-rw-r--r--src/gui/buy.cpp233
-rw-r--r--src/gui/buy.h10
-rw-r--r--src/gui/inventorywindow.cpp13
-rw-r--r--src/gui/item_amount.cpp16
-rw-r--r--src/gui/item_amount.h1
-rw-r--r--src/gui/itemcontainer.cpp2
-rw-r--r--src/gui/popupmenu.cpp86
-rw-r--r--src/gui/popupmenu.h7
-rw-r--r--src/gui/sell.cpp191
-rw-r--r--src/gui/sell.h9
-rw-r--r--src/gui/updatewindow.cpp25
-rw-r--r--src/gui/updatewindow.h7
-rw-r--r--src/net/protocol.cpp4
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");