diff options
author | Andrei Karas <akaras@inbox.ru> | 2011-03-03 02:50:03 +0200 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2011-03-03 02:50:03 +0200 |
commit | de51eaa43e05c2126fc1eef2a7e115843f972547 (patch) | |
tree | 286a05a069e048247f90c7595f1b8939be784608 | |
parent | d4c08d3bf69410a35a50875de50cc6fe74b3bf3e (diff) | |
parent | 8627c7745f47492ab349da6a74e98e3d5813418f (diff) | |
download | manaplus-de51eaa43e05c2126fc1eef2a7e115843f972547.tar.gz manaplus-de51eaa43e05c2126fc1eef2a7e115843f972547.tar.bz2 manaplus-de51eaa43e05c2126fc1eef2a7e115843f972547.tar.xz manaplus-de51eaa43e05c2126fc1eef2a7e115843f972547.zip |
Merge branch 'coloritems'
41 files changed, 498 insertions, 147 deletions
diff --git a/src/actorsprite.cpp b/src/actorsprite.cpp index fc648741c..686c871e7 100644 --- a/src/actorsprite.cpp +++ b/src/actorsprite.cpp @@ -301,7 +301,8 @@ void ActorSprite::handleStatusEffect(StatusEffect *effect, int effectId) } void ActorSprite::setupSpriteDisplay(const SpriteDisplay &display, - bool forceDisplay, int imageType) + bool forceDisplay, int imageType, + std::string color) { clear(); @@ -310,7 +311,9 @@ void ActorSprite::setupSpriteDisplay(const SpriteDisplay &display, for (it = display.sprites.begin(), it_end = display.sprites.end(); it != it_end; ++it) { - std::string file = "graphics/sprites/" + (*it)->sprite; + std::string file = "graphics/sprites/" + + combineDye2((*it)->sprite, color); + int variant = (*it)->variant; addSprite(AnimatedSprite::load(file, variant)); } @@ -336,6 +339,8 @@ void ActorSprite::setupSpriteDisplay(const SpriteDisplay &display, imagePath = "graphics/items/" + display.floor; break; } + imagePath = combineDye2(imagePath, color); + Image *img = resman->getImage(imagePath); if (!img) diff --git a/src/actorsprite.h b/src/actorsprite.h index 00b694e26..7ec5cc391 100644 --- a/src/actorsprite.h +++ b/src/actorsprite.h @@ -211,7 +211,8 @@ protected: virtual void handleStatusEffect(StatusEffect *effect, int effectId); void setupSpriteDisplay(const SpriteDisplay &display, - bool forceDisplay = true, int imageType = 0); + bool forceDisplay = true, int imageType = 0, + std::string color = ""); int mId; Uint16 mStunMode; /**< Stun mode; zero if not stunned */ diff --git a/src/actorspritemanager.cpp b/src/actorspritemanager.cpp index 0c5cfe04d..03ed09835 100644 --- a/src/actorspritemanager.cpp +++ b/src/actorspritemanager.cpp @@ -190,10 +190,10 @@ Being *ActorSpriteManager::createBeing(int id, ActorSprite::Type type, return being; } -FloorItem *ActorSpriteManager::createItem(int id, int itemId, - int x, int y, int amount) +FloorItem *ActorSpriteManager::createItem(int id, int itemId, int x, int y, + int amount, unsigned char color) { - FloorItem *floorItem = new FloorItem(id, itemId, x, y, mMap, amount); + FloorItem *floorItem = new FloorItem(id, itemId, x, y, mMap, amount, color); mActors.insert(floorItem); return floorItem; diff --git a/src/actorspritemanager.h b/src/actorspritemanager.h index 3af157f17..c7deba867 100644 --- a/src/actorspritemanager.h +++ b/src/actorspritemanager.h @@ -68,7 +68,8 @@ class ActorSpriteManager: public ConfigListener /** * Create a FloorItem and add it to the list of ActorSprites. */ - FloorItem *createItem(int id, int itemId, int x, int y, int amount); + FloorItem *createItem(int id, int itemId, int x, int y, + int amount, unsigned char color); /** * Destroys the given ActorSprite at the end of diff --git a/src/being.cpp b/src/being.cpp index 7265aa337..2f2e69d16 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -1483,8 +1483,8 @@ void Being::updateColors() } } -void Being::setSprite(unsigned int slot, int id, const std::string &color, - bool isWeapon, bool isTempSprite) +void Being::setSprite(unsigned int slot, int id, std::string color, + unsigned char colorId, bool isWeapon, bool isTempSprite) { if (slot >= Net::getCharHandler()->maxSprite()) return; @@ -1508,13 +1508,15 @@ void Being::setSprite(unsigned int slot, int id, const std::string &color, } else { - std::string filename = ItemDB::get(id).getSprite(mGender); + ItemInfo info = ItemDB::get(id); + std::string filename = info.getSprite(mGender); AnimatedSprite *equipmentSprite = NULL; if (!filename.empty()) { - if (!color.empty()) - filename += "|" + color; + if (color.empty()) + color = info.getDyeColorsString(colorId); + filename = combineDye(filename, color); equipmentSprite = AnimatedSprite::load( paths.getStringValue("sprites") + filename); @@ -1931,7 +1933,7 @@ void Being::recalcSpritesOrder() if (repIt->second != 1) { setSprite(removeSprite, repIt->second, - mSpriteColors[removeSprite], false, true); + mSpriteColors[removeSprite], 1, false, true); } } } @@ -2066,7 +2068,7 @@ void Being::recalcSpritesOrder() if (!id) continue; - setSprite(slot, id, mSpriteColors[slot], false, true); + setSprite(slot, id, mSpriteColors[slot], 1, false, true); } // logger->log("slot %d = %d", slot, mSpriteRemap[slot]); } diff --git a/src/being.h b/src/being.h index 49127629f..1d5ca7c19 100644 --- a/src/being.h +++ b/src/being.h @@ -333,7 +333,8 @@ class Being : public ActorSprite, public ConfigListener * Sets visible equipments for this being. */ void setSprite(unsigned int slot, int id, - const std::string &color = "", bool isWeapon = false, + std::string color = "", + unsigned char colorId = 1, bool isWeapon = false, bool isTempSprite = false); void setSpriteID(unsigned int slot, int id); diff --git a/src/client.cpp b/src/client.cpp index 4eaad4234..e1753753e 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -151,6 +151,7 @@ volatile int frame_count = 0; /**< Counts the frames during one second */ volatile int cur_time; volatile bool runCounters; bool isSafeMode = false; +int serverVersion; /** * Advances game logic counter. diff --git a/src/client.h b/src/client.h index 3ed9482dd..e3f596c1a 100644 --- a/src/client.h +++ b/src/client.h @@ -59,6 +59,7 @@ extern volatile int fps; extern volatile int tick_time; extern volatile int cur_time; extern bool isSafeMode; +extern int serverVersion; class ErrorListener : public gcn::ActionListener { diff --git a/src/flooritem.cpp b/src/flooritem.cpp index 619be25ea..740daf387 100644 --- a/src/flooritem.cpp +++ b/src/flooritem.cpp @@ -41,7 +41,8 @@ FloorItem::FloorItem(int id, int x, int y, Map *map, - int amount): + int amount, + unsigned char color): ActorSprite(id), mItemId(itemId), mX(x), @@ -49,7 +50,8 @@ FloorItem::FloorItem(int id, mMap(map), // mAlpha(1.0f), mAmount(amount), - mPickupCount(0) + mPickupCount(0), + mColor(color) { mDropTime = cur_time; @@ -69,7 +71,8 @@ FloorItem::FloorItem(int id, mPos.y = 0; } - setupSpriteDisplay(ItemDB::get(itemId).getDisplay(), true, 1); + ItemInfo info = ItemDB::get(itemId); + setupSpriteDisplay(info.getDisplay(), true, 1, info.getDyeColorsString(mColor)); } const ItemInfo &FloorItem::getInfo() const diff --git a/src/flooritem.h b/src/flooritem.h index deff05bc8..f1d19b89f 100644 --- a/src/flooritem.h +++ b/src/flooritem.h @@ -48,7 +48,8 @@ class FloorItem : public ActorSprite int x, int y, Map *map, - int amount); + int amount, + unsigned char color); Type getType() const { return FLOOR_ITEM; } @@ -88,6 +89,7 @@ class FloorItem : public ActorSprite int mDropTime; int mAmount; unsigned mPickupCount; + unsigned char mColor; }; #endif diff --git a/src/gui/charcreatedialog.cpp b/src/gui/charcreatedialog.cpp index dff591dd9..ae4401572 100644 --- a/src/gui/charcreatedialog.cpp +++ b/src/gui/charcreatedialog.cpp @@ -58,7 +58,7 @@ CharCreateDialog::CharCreateDialog(CharSelectDialog *parent, int slot): mPlayer = new Being(0, ActorSprite::PLAYER, 0, NULL); mPlayer->setGender(GENDER_MALE); - int numberOfHairColors = ColorDB::size(); + int numberOfHairColors = ColorDB::getHairSize(); mHairStyle = rand() % mPlayer->getNumOfHairstyles(); mHairColor = rand() % numberOfHairColors; @@ -364,10 +364,10 @@ void CharCreateDialog::updateHair() if (mHairStyle < 0) mHairStyle += Being::getNumOfHairstyles(); - mHairColor %= ColorDB::size(); + mHairColor %= ColorDB::getHairSize(); if (mHairColor < 0) - mHairColor += ColorDB::size(); + mHairColor += ColorDB::getHairSize(); mPlayer->setSprite(Net::getCharHandler()->hairSprite(), - mHairStyle * -1, ColorDB::get(mHairColor)); + mHairStyle * -1, ColorDB::getHairColor(mHairColor)); } diff --git a/src/gui/outfitwindow.cpp b/src/gui/outfitwindow.cpp index 2796e13c8..ea2b7980c 100644 --- a/src/gui/outfitwindow.cpp +++ b/src/gui/outfitwindow.cpp @@ -292,7 +292,8 @@ void OutfitWindow::draw(gcn::Graphics *graphics) } if (!foundItem) { - Image *image = Item::getImage(mItems[mCurrentOutfit][i]); + //+++ need use colors in outfits + Image *image = Item::getImage(mItems[mCurrentOutfit][i], 1); if (image) g->drawImage(image, itemX, itemY); } diff --git a/src/gui/trade.cpp b/src/gui/trade.cpp index f7b16d6ae..be4891103 100644 --- a/src/gui/trade.cpp +++ b/src/gui/trade.cpp @@ -151,21 +151,22 @@ void TradeWindow::setMoney(int amount) mMoneyLabel->adjustSize(); } -void TradeWindow::addItem(int id, bool own, int quantity, int refine) +void TradeWindow::addItem(int id, bool own, int quantity, + int refine, unsigned char color) { if (own) - mMyInventory->addItem(id, quantity, refine); + mMyInventory->addItem(id, quantity, refine, color); else - mPartnerInventory->addItem(id, quantity, refine); + mPartnerInventory->addItem(id, quantity, refine, color); } void TradeWindow::addItem(int id, bool own, int quantity, - int refine, bool equipment) + int refine, unsigned char color, bool equipment) { if (own) - mMyInventory->addItem(id, quantity, refine, equipment); + mMyInventory->addItem(id, quantity, refine, color, equipment); else - mPartnerInventory->addItem(id, quantity, refine, equipment); + mPartnerInventory->addItem(id, quantity, refine, color, equipment); } void TradeWindow::changeQuantity(int index, bool own, int quantity) diff --git a/src/gui/trade.h b/src/gui/trade.h index c316e2354..fcaa2f6ac 100644 --- a/src/gui/trade.h +++ b/src/gui/trade.h @@ -63,7 +63,8 @@ class TradeWindow : public Window, gcn::ActionListener, gcn::SelectionListener /** * Add an item to the trade window. */ - void addItem(int id, bool own, int quantity, int refine); + void addItem(int id, bool own, int quantity, + int refine, unsigned char color); /** * Reset both item containers @@ -73,8 +74,8 @@ class TradeWindow : public Window, gcn::ActionListener, gcn::SelectionListener /** * Add an item to the trade window. */ - void addItem(int id, bool own, int quantity, - int refine, bool equipment); + void addItem(int id, bool own, int quantity, int refine, + unsigned char color, bool equipment); /** * Change quantity of an item. diff --git a/src/inventory.cpp b/src/inventory.cpp index 04a8a8962..705ae9329 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -83,13 +83,14 @@ Item *Inventory::findItem(int itemId) const return 0; } -void Inventory::addItem(int id, int quantity, int refine, bool equipment) +void Inventory::addItem(int id, int quantity, int refine, + unsigned char color, bool equipment) { - setItem(getFreeSlot(), id, quantity, refine, equipment); + setItem(getFreeSlot(), id, quantity, refine, color, equipment); } void Inventory::setItem(int index, int id, int quantity, - int refine, bool equipment) + int refine, unsigned char color, bool equipment) { if (index < 0 || index >= static_cast<int>(mSize)) { @@ -99,7 +100,7 @@ void Inventory::setItem(int index, int id, int quantity, if (!mItems[index] && id > 0) { - Item *item = new Item(id, quantity, refine, equipment); + Item *item = new Item(id, quantity, refine, color, equipment); item->setInvIndex(index); mItems[index] = item; mUsed++; @@ -107,7 +108,7 @@ void Inventory::setItem(int index, int id, int quantity, } else if (id > 0 && mItems[index]) { - mItems[index]->setId(id); + mItems[index]->setId(id, color); mItems[index]->setQuantity(quantity); mItems[index]->setRefine(refine); mItems[index]->setEquipment(equipment); diff --git a/src/inventory.h b/src/inventory.h index e53052f2b..1e2d8a2bc 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -91,13 +91,14 @@ class Inventory /** * Adds a new item in a free slot. */ - void addItem(int id, int quantity, int refine, bool equipment = false); + void addItem(int id, int quantity, int refine, unsigned char color, + bool equipment = false); /** * Sets the item at the given position. */ void setItem(int index, int id, int quantity, int refine, - bool equipment = false); + unsigned char color, bool equipment = false); /** * Remove a item from the inventory. diff --git a/src/item.cpp b/src/item.cpp index 79540334a..ed0685a9d 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -29,7 +29,8 @@ #include "resources/resourcemanager.h" #include "configuration.h" -Item::Item(int id, int quantity, int refine, bool equipment, bool equipped): +Item::Item(int id, int quantity, int refine, unsigned char color, + bool equipment, bool equipped): mImage(0), mDrawImage(0), mQuantity(quantity), @@ -39,7 +40,7 @@ Item::Item(int id, int quantity, int refine, bool equipment, bool equipped): mRefine(refine), mInvIndex(0) { - setId(id); + setId(id, color); } Item::~Item() @@ -48,9 +49,10 @@ Item::~Item() mImage->decRef(); } -void Item::setId(int id) +void Item::setId(int id, unsigned char color) { mId = id; + mColor = color; // Types 0 and 1 are not equippable items. mEquipment = id && getInfo().getType() >= 2; @@ -73,8 +75,9 @@ void Item::setId(int id) SpriteDisplay display = info.getDisplay(); std::string imagePath = paths.getStringValue("itemIcons") + display.image; - mImage = resman->getImage(imagePath); - mDrawImage = resman->getImage(imagePath); + std::string dye = combineDye2(imagePath, info.getDyeColorsString(color)); + mImage = resman->getImage(dye); + mDrawImage = resman->getImage(dye); if (!mImage) { @@ -96,12 +99,14 @@ bool Item::isHaveTag(int tagId) return mTags[tagId] > 0; } -Image *Item::getImage(int id) +Image *Item::getImage(int id, unsigned char color) { ResourceManager *resman = ResourceManager::getInstance(); - SpriteDisplay display = ItemDB::get(id).getDisplay(); + ItemInfo info = ItemDB::get(id); + SpriteDisplay display = info.getDisplay(); std::string imagePath = "graphics/items/" + display.image; - Image *image = resman->getImage(imagePath); + Image *image; + image = resman->getImage(combineDye2(imagePath, info.getDyeColorsString(color))); if (!image) image = Theme::getImageFromTheme("unknown-item.png"); diff --git a/src/item.h b/src/item.h index bc21a437a..ae2cc9dfb 100644 --- a/src/item.h +++ b/src/item.h @@ -39,7 +39,8 @@ class Item * Constructor. */ Item(int id = -1, int quantity = 0, int refine = 0, - bool equipment = false, bool equipped = false); + unsigned char color = 1, bool equipment = false, + bool equipped = false); /** * Destructor. @@ -49,7 +50,7 @@ class Item /** * Sets the item id, identifying the item type. */ - void setId(int id); + void setId(int id, unsigned char color); /** * Returns the item id. @@ -153,10 +154,13 @@ class Item const ItemInfo &getInfo() const { return ItemDB::get(mId); } - static Image *getImage(int id); + static Image *getImage(int id, unsigned char color); bool isHaveTag(int tagId); + unsigned char getColor() + { return mColor; } + protected: int mId; /**< Item type id. */ Image *mImage; /**< Item image. */ @@ -167,6 +171,7 @@ class Item bool mInEquipment; /**< Item is in equipment */ int mRefine; /**< Item refine level. */ int mInvIndex; /**< Inventory index. */ + unsigned char mColor; std::map <int, int> mTags; }; diff --git a/src/net/manaserv/beinghandler.cpp b/src/net/manaserv/beinghandler.cpp index f5fa7d26c..b726bc52e 100644 --- a/src/net/manaserv/beinghandler.cpp +++ b/src/net/manaserv/beinghandler.cpp @@ -155,7 +155,7 @@ static void handleLooks(Being *being, Net::MessageIn &msg) { if (!(mask & (1 << i))) continue; int id = msg.readInt16(); - being->setSprite(slots[i], id, "", (slots[i] == SPRITE_WEAPON)); + being->setSprite(slots[i], id, "", 1, (slots[i] == SPRITE_WEAPON)); } } @@ -185,7 +185,7 @@ void BeingHandler::handleBeingEnterMessage(Net::MessageIn &msg) being->setName(name); } int hs = msg.readInt8(), hc = msg.readInt8(); - being->setSprite(SPRITE_HAIR, hs * -1, ColorDB::get(hc)); + being->setSprite(SPRITE_HAIR, hs * -1, ColorDB::getHairColor(hc)); being->setGender(msg.readInt8() == GENDER_MALE ? GENDER_MALE : GENDER_FEMALE); handleLooks(being, msg); @@ -350,7 +350,7 @@ void BeingHandler::handleBeingLooksChangeMessage(Net::MessageIn &msg) { int style = msg.readInt16(); int color = msg.readInt16(); - being->setSprite(SPRITE_HAIR, style * -1, ColorDB::get(color)); + being->setSprite(SPRITE_HAIR, style * -1, ColorDB::getHairColor(color)); } } diff --git a/src/net/manaserv/buysellhandler.cpp b/src/net/manaserv/buysellhandler.cpp index 7334fe928..07737e20b 100644 --- a/src/net/manaserv/buysellhandler.cpp +++ b/src/net/manaserv/buysellhandler.cpp @@ -96,7 +96,7 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg) int itemId = msg.readInt16(); int amount = msg.readInt16(); int value = msg.readInt16(); - dialog->addItem(new Item(itemId, amount, false), value); + dialog->addItem(new Item(itemId, amount, 1, false), value); } break; } diff --git a/src/net/manaserv/charhandler.cpp b/src/net/manaserv/charhandler.cpp index 20dda5b70..163aad988 100644 --- a/src/net/manaserv/charhandler.cpp +++ b/src/net/manaserv/charhandler.cpp @@ -377,7 +377,7 @@ void CharHandler::updateCharacters() player->setName(info.name); player->setGender(info.gender); player->setSprite(SPRITE_HAIR, info.hairStyle * -1, - ColorDB::get(info.hairColor)); + ColorDB::getHairColor(info.hairColor)); character->data.mAttributes[LEVEL] = info.level; character->data.mAttributes[CHAR_POINTS] = info.characterPoints; character->data.mAttributes[CORR_POINTS] = info.correctionPoints; diff --git a/src/net/manaserv/itemhandler.cpp b/src/net/manaserv/itemhandler.cpp index ce1d0965a..0afd12d21 100644 --- a/src/net/manaserv/itemhandler.cpp +++ b/src/net/manaserv/itemhandler.cpp @@ -68,7 +68,7 @@ void ItemHandler::handleMessage(Net::MessageIn &msg) actorSpriteManager->createItem(id, itemId, x / map->getTileWidth(), y / map->getTileHeight(), - 0); + 0, 1); } else { diff --git a/src/net/manaserv/tradehandler.cpp b/src/net/manaserv/tradehandler.cpp index 18a60a424..cd3a21aca 100644 --- a/src/net/manaserv/tradehandler.cpp +++ b/src/net/manaserv/tradehandler.cpp @@ -134,7 +134,7 @@ void TradeHandler::handleMessage(Net::MessageIn &msg) { int type = msg.readInt16(); int amount = msg.readInt8(); - tradeWindow->addItem(type, false, amount, 0); + tradeWindow->addItem(type, false, amount, 0, 1); } break; case GPMSG_TRADE_SET_MONEY: @@ -201,7 +201,7 @@ void TradeHandler::addItem(Item *item, int amount) msg.writeInt8(amount); gameServerConnection->send(msg); - tradeWindow->addItem(item->getId(), true, amount, 0); + tradeWindow->addItem(item->getId(), true, amount, 0, 1); item->increaseQuantity(-amount); } diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index 436b40d13..000941c30 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -167,6 +167,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) Being *srcBeing, *dstBeing; int hairStyle, hairColor, flag; int hp, maxHP, oldHP; + unsigned char colors[9]; switch (msg.getId()) { @@ -289,7 +290,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) ? GENDER_FEMALE : GENDER_MALE); // Set these after the gender, as the sprites may be gender-specific dstBeing->setSprite(SPRITE_HAIR, hairStyle * -1, - ColorDB::get(hairColor)); + ColorDB::getHairColor(hairColor)); dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, headBottom); dstBeing->setSprite(SPRITE_TOPCLOTHES, headMid); dstBeing->setSprite(SPRITE_HAT, headTop); @@ -620,15 +621,21 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) int type = msg.readInt8(); int id = 0; int id2 = 0; + std::string color; if (msg.getId() == SMSG_BEING_CHANGE_LOOKS) { id = msg.readInt8(); + id2 = 1; // default color } else { // SMSG_BEING_CHANGE_LOOKS2 id = msg.readInt16(); - id2 = msg.readInt16(); + if (type == 2 || serverVersion > 0) + id2 = msg.readInt16(); + else + id2 = 1; + color = ""; } if (dstBeing->getType() == Being::PLAYER) @@ -646,57 +653,57 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) dstBeing->setSpriteID(SPRITE_HAIR, id *-1); break; case 2: // Weapon ID in id, Shield ID in id2 - dstBeing->setSprite(SPRITE_WEAPON, id, "", true); + dstBeing->setSprite(SPRITE_WEAPON, id, "", 1, true); if (!config.getBoolValue("hideShield")) dstBeing->setSprite(SPRITE_SHIELD, id2); player_node->imitateOutfit(dstBeing, SPRITE_SHIELD); break; case 3: // Change lower headgear for eAthena, pants for us - dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, id); + dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, id, color, id2); player_node->imitateOutfit(dstBeing, SPRITE_BOTTOMCLOTHES); break; case 4: // Change upper headgear for eAthena, hat for us - dstBeing->setSprite(SPRITE_HAT, id); + dstBeing->setSprite(SPRITE_HAT, id, color, id2); player_node->imitateOutfit(dstBeing, SPRITE_HAT); break; case 5: // Change middle headgear for eathena, armor for us - dstBeing->setSprite(SPRITE_TOPCLOTHES, id); + dstBeing->setSprite(SPRITE_TOPCLOTHES, id, color, id2); player_node->imitateOutfit(dstBeing, SPRITE_TOPCLOTHES); break; case 6: // eAthena LOOK_HAIR_COLOR - dstBeing->setSpriteColor(SPRITE_HAIR, ColorDB::get(id)); + dstBeing->setSpriteColor(SPRITE_HAIR, ColorDB::getHairColor(id)); break; case 8: // eAthena LOOK_SHIELD if (!config.getBoolValue("hideShield")) - dstBeing->setSprite(SPRITE_SHIELD, id); + dstBeing->setSprite(SPRITE_SHIELD, id, color, id2); player_node->imitateOutfit(dstBeing, SPRITE_SHIELD); break; case 9: // eAthena LOOK_SHOES - dstBeing->setSprite(SPRITE_SHOE, id); + dstBeing->setSprite(SPRITE_SHOE, id, color, id2); player_node->imitateOutfit(dstBeing, SPRITE_SHOE); break; case 10: // LOOK_GLOVES - dstBeing->setSprite(SPRITE_GLOVES, id); + dstBeing->setSprite(SPRITE_GLOVES, id, color, id2); player_node->imitateOutfit(dstBeing, SPRITE_GLOVES); break; case 11: // LOOK_CAPE - dstBeing->setSprite(SPRITE_CAPE, id); + dstBeing->setSprite(SPRITE_CAPE, id, color, id2); player_node->imitateOutfit(dstBeing, SPRITE_CAPE); break; case 12: - dstBeing->setSprite(SPRITE_MISC1, id); + dstBeing->setSprite(SPRITE_MISC1, id, color, id2); player_node->imitateOutfit(dstBeing, SPRITE_MISC1); break; case 13: - dstBeing->setSprite(SPRITE_MISC2, id); + dstBeing->setSprite(SPRITE_MISC2, id, color, id2); player_node->imitateOutfit(dstBeing, SPRITE_MISC2); break; case 14: - dstBeing->setSprite(SPRITE_EVOL1, id); + dstBeing->setSprite(SPRITE_EVOL1, id, color, id2); player_node->imitateOutfit(dstBeing, SPRITE_EVOL1); break; case 15: - dstBeing->setSprite(SPRITE_EVOL2, id); + dstBeing->setSprite(SPRITE_EVOL2, id, color, id2); player_node->imitateOutfit(dstBeing, SPRITE_EVOL2); break; default: @@ -870,8 +877,17 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) headTop = msg.readInt16(); headMid = msg.readInt16(); hairColor = msg.readInt16(); - shoes = msg.readInt16(); - gloves = msg.readInt16(); //sd->head_dir + + colors[0] = msg.readInt8(); + colors[1] = msg.readInt8(); + colors[2] = msg.readInt8(); + logger->log("msg: %x", msg.getId()); + logger->log("colors: %d, %d, %d", colors[0], colors[1], colors[2]); + + msg.readInt8(); //unused +// shoes = msg.readInt16(); +// gloves = msg.readInt16(); //sd->head_dir + guild = msg.readInt32(); // guild if (guild == 0) @@ -887,19 +903,28 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) ? GENDER_FEMALE : GENDER_MALE); // Set these after the gender, as the sprites may be gender-specific - dstBeing->setSprite(SPRITE_WEAPON, weapon, "", true); + dstBeing->setSprite(SPRITE_WEAPON, weapon, "", 1, true); if (!config.getBoolValue("hideShield")) dstBeing->setSprite(SPRITE_SHIELD, shield); //dstBeing->setSprite(SPRITE_SHOE, shoes); - dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, headBottom); - dstBeing->setSprite(SPRITE_TOPCLOTHES, headMid); - dstBeing->setSprite(SPRITE_HAT, headTop); + if (serverVersion > 0) + { + dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, headBottom, "", colors[0]); + dstBeing->setSprite(SPRITE_TOPCLOTHES, headMid, "", colors[2]); + dstBeing->setSprite(SPRITE_HAT, headTop, "", colors[1]); + } + else + { + dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, headBottom); + dstBeing->setSprite(SPRITE_TOPCLOTHES, headMid); + dstBeing->setSprite(SPRITE_HAT, headTop); + } //dstBeing->setSprite(SPRITE_GLOVES, gloves); //dstBeing->setSprite(SPRITE_CAPE, cape); //dstBeing->setSprite(SPRITE_MISC1, misc1); //dstBeing->setSprite(SPRITE_MISC2, misc2); dstBeing->setSprite(SPRITE_HAIR, hairStyle * -1, - ColorDB::get(hairColor)); + ColorDB::getHairColor(hairColor)); player_node->imitateOutfit(dstBeing); diff --git a/src/net/tmwa/charserverhandler.cpp b/src/net/tmwa/charserverhandler.cpp index 5e2efbdd5..daf531f04 100644 --- a/src/net/tmwa/charserverhandler.cpp +++ b/src/net/tmwa/charserverhandler.cpp @@ -61,6 +61,7 @@ CharServerHandler::CharServerHandler() SMSG_CHAR_LOGIN, SMSG_CHAR_LOGIN_ERROR, SMSG_CHAR_CREATE_SUCCEEDED, + SMSG_CHAR_CREATE_SUCCEEDED2, SMSG_CHAR_CREATE_FAILED, SMSG_CHAR_DELETE_SUCCEEDED, SMSG_CHAR_DELETE_FAILED, @@ -82,18 +83,23 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg) int slots = msg.readInt16(); if (slots > 0 && slots < 30) loginData.characterSlots = slots; - msg.skip(18); // Unused + bool version = msg.readInt8() == 1 && serverVersion > 0; + msg.skip(17); // Unused delete_all(mCharacters); mCharacters.clear(); // Derive number of characters from message length - const int count = (msg.getLength() - 24) / 106; + int count = (msg.getLength() - 24); + if (version) + count /= 120; + else + count /= 106; for (int i = 0; i < count; ++i) { Net::Character *character = new Net::Character; - readPlayerData(msg, character); + readPlayerData(msg, character, version); mCharacters.push_back(character); logger->log("CharServer: Player: %s (%d)", character->dummy->getName().c_str(), character->slot); @@ -123,7 +129,24 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg) case SMSG_CHAR_CREATE_SUCCEEDED: { Net::Character *character = new Net::Character; - readPlayerData(msg, character); + readPlayerData(msg, character, false); + mCharacters.push_back(character); + + updateCharSelectDialog(); + + // Close the character create dialog + if (mCharCreateDialog) + { + mCharCreateDialog->scheduleDelete(); + mCharCreateDialog = 0; + } + } + break; + + case SMSG_CHAR_CREATE_SUCCEEDED2: + { + Net::Character *character = new Net::Character; + readPlayerData(msg, character, true); mCharacters.push_back(character); updateCharSelectDialog(); @@ -238,7 +261,8 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg) } void CharServerHandler::readPlayerData(Net::MessageIn &msg, - Net::Character *character) + Net::Character *character, + bool withColors) { const Token &token = static_cast<LoginHandler*>(Net::getLoginHandler())->getToken(); @@ -254,10 +278,10 @@ void CharServerHandler::readPlayerData(Net::MessageIn &msg, character->data.mStats[JOB].base = temp; character->data.mStats[JOB].mod = temp; - tempPlayer->setSprite(SPRITE_SHOE, msg.readInt16()); - tempPlayer->setSprite(SPRITE_GLOVES, msg.readInt16()); - tempPlayer->setSprite(SPRITE_CAPE, msg.readInt16()); - tempPlayer->setSprite(SPRITE_MISC1, msg.readInt16()); + int shoes = msg.readInt16(); + int gloves = msg.readInt16(); + int cape = msg.readInt16(); + int misc1 = msg.readInt16(); msg.readInt32(); // option msg.readInt32(); // karma @@ -272,24 +296,22 @@ void CharServerHandler::readPlayerData(Net::MessageIn &msg, msg.readInt16(); // speed tempPlayer->setSubtype(msg.readInt16()); // class (used for race) int hairStyle = msg.readInt16(); - Uint16 weapon = msg.readInt16(); - tempPlayer->setSprite(SPRITE_WEAPON, weapon, "", true); + Uint16 weapon = msg.readInt16(); // server not used it. may be need use? + tempPlayer->setSprite(SPRITE_WEAPON, weapon, "", 1, true); character->data.mAttributes[LEVEL] = msg.readInt16(); msg.readInt16(); // skill point - tempPlayer->setSprite(SPRITE_BOTTOMCLOTHES, msg.readInt16()); - //to avoid show error (error.xml) need remove this sprite - if (!config.getBoolValue("hideShield")) - tempPlayer->setSprite(SPRITE_SHIELD, msg.readInt16()); - else - msg.readInt16(); + int bottomClothes = msg.readInt16(); + int shield = msg.readInt16(); + + int hat = msg.readInt16(); // head option top + int topClothes = msg.readInt16(); - tempPlayer->setSprite(SPRITE_HAT, msg.readInt16()); // head option top - tempPlayer->setSprite(SPRITE_TOPCLOTHES, msg.readInt16()); tempPlayer->setSprite(SPRITE_HAIR, hairStyle * -1, - ColorDB::get(msg.readInt16())); - tempPlayer->setSprite(SPRITE_MISC2, msg.readInt16()); + ColorDB::getHairColor(msg.readInt16())); + + int misc2 = msg.readInt16(); tempPlayer->setName(msg.readString(24)); character->dummy = tempPlayer; @@ -297,7 +319,42 @@ void CharServerHandler::readPlayerData(Net::MessageIn &msg, for (int i = 0; i < 6; i++) character->data.mStats[i + STR].base = msg.readInt8(); - character->slot = msg.readInt8(); // character slot + if (withColors) + { + tempPlayer->setSprite(SPRITE_SHOE, shoes, "", msg.readInt8()); + tempPlayer->setSprite(SPRITE_GLOVES, gloves, "", msg.readInt8()); + tempPlayer->setSprite(SPRITE_CAPE, cape, "", msg.readInt8()); + tempPlayer->setSprite(SPRITE_MISC1, misc1, "", msg.readInt8()); + tempPlayer->setSprite(SPRITE_BOTTOMCLOTHES, bottomClothes, "", msg.readInt8()); + //to avoid show error (error.xml) need remove this sprite + if (!config.getBoolValue("hideShield")) + tempPlayer->setSprite(SPRITE_SHIELD, shield, "", msg.readInt8()); + else + msg.readInt8(); + + tempPlayer->setSprite(SPRITE_HAT, hat, "", msg.readInt8()); // head option top + tempPlayer->setSprite(SPRITE_TOPCLOTHES, topClothes, "", msg.readInt8()); + tempPlayer->setSprite(SPRITE_MISC2, misc2, "", msg.readInt8()); + msg.skip(5); + character->slot = msg.readInt8(); // character slot + } + else + { + tempPlayer->setSprite(SPRITE_SHOE, shoes); + tempPlayer->setSprite(SPRITE_GLOVES, gloves); + tempPlayer->setSprite(SPRITE_CAPE, cape); + tempPlayer->setSprite(SPRITE_MISC1, misc1); + tempPlayer->setSprite(SPRITE_BOTTOMCLOTHES, bottomClothes); + //to avoid show error (error.xml) need remove this sprite + if (!config.getBoolValue("hideShield")) + tempPlayer->setSprite(SPRITE_SHIELD, shield); + + tempPlayer->setSprite(SPRITE_HAT, hat); // head option top + tempPlayer->setSprite(SPRITE_TOPCLOTHES, topClothes); + tempPlayer->setSprite(SPRITE_MISC2, misc2); + character->slot = msg.readInt8(); // character slot + } + msg.readInt8(); // unknown } diff --git a/src/net/tmwa/charserverhandler.h b/src/net/tmwa/charserverhandler.h index 77c726566..9d65639b9 100644 --- a/src/net/tmwa/charserverhandler.h +++ b/src/net/tmwa/charserverhandler.h @@ -80,7 +80,8 @@ class CharServerHandler : public MessageHandler, public Net::CharHandler void connect(); private: - void readPlayerData(Net::MessageIn &msg, Net::Character *character); + void readPlayerData(Net::MessageIn &msg, Net::Character *character, + bool withColors); }; } // namespace TmwAthena diff --git a/src/net/tmwa/inventoryhandler.cpp b/src/net/tmwa/inventoryhandler.cpp index 9828fb957..7113cddb3 100644 --- a/src/net/tmwa/inventoryhandler.cpp +++ b/src/net/tmwa/inventoryhandler.cpp @@ -209,6 +209,9 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) cards[0], cards[1], cards[2], cards[3]); } + if (serverVersion < 1 && identified > 1) + identified = 1; + if (msg.getId() == SMSG_PLAYER_INVENTORY) { // Trick because arrows are not considered equipment @@ -217,13 +220,13 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) if (inventory) { inventory->setItem(index, itemId, amount, - 0, isEquipment); + 0, identified, isEquipment); } } else { mInventoryItems.push_back(InventoryItem(index, itemId, - amount, 0, false)); + amount, 0, identified, false)); } } break; @@ -255,8 +258,11 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) refine); } + if (serverVersion < 1 && identified > 1) + identified = 1; + mInventoryItems.push_back(InventoryItem(index, itemId, amount, - refine, false)); + refine, identified, false)); } break; @@ -299,8 +305,11 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) if (item && item->getId() == itemId) amount += inventory->getItem(index)->getQuantity(); + if (serverVersion < 1 && identified > 1) + identified = 1; + inventory->setItem(index, itemId, amount, refine, - equipType != 0); + identified, equipType != 0); } } } break; @@ -381,7 +390,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) for (; it != it_end; ++it) { mStorage->setItem((*it).slot, (*it).id, (*it).quantity, - (*it).equip); + (*it).refine, (*it).color, (*it).equip); } mInventoryItems.clear(); @@ -403,13 +412,19 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) if (Item *item = mStorage->getItem(index)) { - item->setId(itemId); + item->setId(itemId, identified); item->increaseQuantity(amount); } else { if (mStorage) - mStorage->setItem(index, itemId, amount, false); + { + if (serverVersion < 1 && identified > 1) + identified = 1; + + mStorage->setItem(index, itemId, amount, refine, + identified, false); + } } break; @@ -455,19 +470,31 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) { index = msg.readInt16() - INVENTORY_OFFSET; itemId = msg.readInt16(); - msg.readInt8(); // type - msg.readInt8(); // identify flag + int itemType = msg.readInt8(); // type + identified = msg.readInt8(); // identify flag + msg.readInt16(); // equip type equipType = msg.readInt16(); msg.readInt8(); // attribute refine = msg.readInt8(); msg.skip(8); // card + + if (debugInventory) + { + logger->log("Index: %d, ID: %d, Type: %d, Identified: %d", + index, itemId, itemType, identified); + } + + if (serverVersion < 1 && identified > 1) + identified = 1; + if (inventory) - inventory->setItem(index, itemId, 1, refine, true); + inventory->setItem(index, itemId, 1, refine, identified, true); if (equipType) mEquips.setEquipment(getSlot(equipType), index); + } break; diff --git a/src/net/tmwa/inventoryhandler.h b/src/net/tmwa/inventoryhandler.h index cc2286f2f..8dd39a781 100644 --- a/src/net/tmwa/inventoryhandler.h +++ b/src/net/tmwa/inventoryhandler.h @@ -109,15 +109,18 @@ class InventoryItem int slot; int id; int quantity; + unsigned char color; int refine; bool equip; - InventoryItem(int slot, int id, int quantity, int refine, bool equip) + InventoryItem(int slot, int id, int quantity, int refine, + unsigned char color, bool equip) { this->slot = slot; this->id = id; this->quantity = quantity; this->refine = refine; + this->color = color; this->equip = equip; } }; diff --git a/src/net/tmwa/itemhandler.cpp b/src/net/tmwa/itemhandler.cpp index 5840d99b2..897ed1fb5 100644 --- a/src/net/tmwa/itemhandler.cpp +++ b/src/net/tmwa/itemhandler.cpp @@ -52,7 +52,7 @@ void ItemHandler::handleMessage(Net::MessageIn &msg) { int id = msg.readInt32(); int itemId = msg.readInt16(); - msg.readInt8(); // identify flag + unsigned char identify = msg.readInt8(); // identify flag int x = msg.readInt16(); int y = msg.readInt16(); // msg.skip(4); // amount,subX,subY / subX,subY,amount @@ -64,12 +64,12 @@ void ItemHandler::handleMessage(Net::MessageIn &msg) if (msg.getId() == SMSG_ITEM_VISIBLE) { actorSpriteManager->createItem(id, itemId, - x, y, amount1); + x, y, amount1, identify); } else { actorSpriteManager->createItem(id, itemId, - x, y, amount2); + x, y, amount2, identify); } } } diff --git a/src/net/tmwa/loginhandler.cpp b/src/net/tmwa/loginhandler.cpp index a1b3c0f95..810d97056 100644 --- a/src/net/tmwa/loginhandler.cpp +++ b/src/net/tmwa/loginhandler.cpp @@ -198,15 +198,23 @@ void LoginHandler::handleMessage(Net::MessageIn &msg) { // TODO: verify these! - msg.readInt8(); // -1 - msg.readInt8(); // T - msg.readInt8(); // M - msg.readInt8(); // W - - unsigned int options = msg.readInt32(); - - mRegistrationEnabled = options; -// mRegistrationEnabled = (options & 1); + char b1 = msg.readInt8(); // -1 + char b2 = msg.readInt8(); // T + char b3 = msg.readInt8(); // M + char b4 = msg.readInt8(); // W + if (b1 == -1 && b2 == 'E' && b3 == 'V' && b4 == 'L') + { + unsigned int options = msg.readInt8(); + mRegistrationEnabled = options; + msg.skip(2); + serverVersion = msg.readInt8(); + } + else + { + unsigned int options = msg.readInt32(); + mRegistrationEnabled = options; + serverVersion = 0; + } // Leave this last mVersionResponse = true; diff --git a/src/net/tmwa/network.cpp b/src/net/tmwa/network.cpp index a19957ae7..ad8be300c 100644 --- a/src/net/tmwa/network.cpp +++ b/src/net/tmwa/network.cpp @@ -79,10 +79,10 @@ short packet_lengths[] = 8, 14, 10, 35, 6, 8, 4, 11, 54, 53, 60, 2, -1, 47, 33, 6, 30, 8, 34, 14, 2, 6, 26, 2, 28, 81, 6, 10, 26, 2, -1, -1, -1, -1, 20, 10, 32, 9, 34, 14, 2, 6, 48, 56, -1, 4, 5, 10, -// #0x2000 +// #0x0200 26, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 19, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -1,122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; const unsigned int BUFFER_SIZE = 655360; diff --git a/src/net/tmwa/network.h b/src/net/tmwa/network.h index 3202282ae..45f3cfac6 100644 --- a/src/net/tmwa/network.h +++ b/src/net/tmwa/network.h @@ -39,7 +39,7 @@ * Protocol version, reported to the eAthena char and mapserver who can adjust * the protocol accordingly. */ -#define CLIENT_PROTOCOL_VERSION 2 +#define CLIENT_PROTOCOL_VERSION 3 namespace TmwAthena { diff --git a/src/net/tmwa/protocol.h b/src/net/tmwa/protocol.h index 3f7f65d4e..696f83646 100644 --- a/src/net/tmwa/protocol.h +++ b/src/net/tmwa/protocol.h @@ -83,6 +83,8 @@ static const int STORAGE_OFFSET = 1; #define SMSG_CHAR_LOGIN 0x006b #define SMSG_CHAR_LOGIN_ERROR 0x006c #define SMSG_CHAR_CREATE_SUCCEEDED 0x006d +#define SMSG_CHAR_CREATE_SUCCEEDED2 0x0221 + #define SMSG_CHAR_CREATE_FAILED 0x006e #define SMSG_CHAR_DELETE_SUCCEEDED 0x006f #define SMSG_CHAR_DELETE_FAILED 0x0070 diff --git a/src/net/tmwa/tradehandler.cpp b/src/net/tmwa/tradehandler.cpp index 3fb05399d..815c8f54d 100644 --- a/src/net/tmwa/tradehandler.cpp +++ b/src/net/tmwa/tradehandler.cpp @@ -193,18 +193,23 @@ void TradeHandler::handleMessage(Net::MessageIn &msg) { int amount = msg.readInt32(); int type = msg.readInt16(); - msg.readInt8(); // identified flag + int identify = msg.readInt8(); // identified flag msg.readInt8(); // attribute - msg.readInt8(); // refine + int refine = msg.readInt8(); // refine msg.skip(8); // card (4 shorts) // TODO: handle also identified, etc if (tradeWindow) { if (type == 0) + { tradeWindow->setMoney(amount); + } else - tradeWindow->addItem(type, false, amount, false); + { + tradeWindow->addItem(type, false, amount, refine, + identify, false); + } } } break; @@ -233,7 +238,8 @@ void TradeHandler::handleMessage(Net::MessageIn &msg) if (tradeWindow) { tradeWindow->addItem(item->getId(), true, quantity, - item->isEquipment()); + item->getRefine(), item->getColor(), + item->isEquipment()); } item->increaseQuantity(-quantity); break; diff --git a/src/resources/colordb.cpp b/src/resources/colordb.cpp index c35cec95e..dce051403 100644 --- a/src/resources/colordb.cpp +++ b/src/resources/colordb.cpp @@ -20,6 +20,7 @@ #include "resources/colordb.h" +#include "client.h" #include "log.h" #include "utils/xml.h" @@ -28,9 +29,10 @@ namespace { - ColorDB::Colors mColors; + ColorDB::Colors mHairColors; bool mLoaded = false; std::string mFail = "#ffffff"; + ColorDB::ColorLists mColorLists; } void ColorDB::load() @@ -38,6 +40,13 @@ void ColorDB::load() if (mLoaded) unload(); + loadHair(); + if (serverVersion >= 1) + loadColorLists(); +} + +void ColorDB::loadHair() +{ XML::Document *doc = new XML::Document("hair.xml"); xmlNodePtr root = doc->rootNode(); bool hairXml = true; @@ -55,7 +64,7 @@ void ColorDB::load() if (!root || !xmlStrEqual(root->name, BAD_CAST "colors")) { logger->log1("ColorDB: Failed to find any color files."); - mColors[0] = mFail; + mHairColors[0] = mFail; mLoaded = true; delete doc; @@ -69,10 +78,10 @@ void ColorDB::load() { int id = XML::getProperty(node, "id", 0); - if (mColors.find(id) != mColors.end()) + if (mHairColors.find(id) != mHairColors.end()) logger->log("ColorDB: Redefinition of dye ID %d", id); - mColors[id] = hairXml ? + mHairColors[id] = hairXml ? XML::getProperty(node, "value", "#FFFFFF") : XML::getProperty(node, "dye", "#FFFFFF"); } @@ -83,22 +92,60 @@ void ColorDB::load() mLoaded = true; } +void ColorDB::loadColorLists() +{ + XML::Document *doc = new XML::Document("itemcolors.xml"); + xmlNodePtr root = doc->rootNode(); + if (!root) + return; + + for_each_xml_child_node(node, root) + { + if (xmlStrEqual(node->name, BAD_CAST "list")) + { + std::string name = XML::getProperty(node, "name", ""); + if (name.empty()) + continue; + + std::map <int, ItemColor> colors; + ColorListsIterator it = mColorLists.find(name); + + if (it != mColorLists.end()) + colors = it->second; + + for_each_xml_child_node(colorNode, node) + { + if (xmlStrEqual(colorNode->name, BAD_CAST "color")) + { + ItemColor c(XML::getProperty(colorNode, "id", -1), + XML::getProperty(colorNode, "name", ""), + XML::getProperty(colorNode, "value", "")); + if (c.id > -1) + colors[c.id] = c; + } + } + mColorLists[name] = colors; + } + } +} + void ColorDB::unload() { logger->log1("Unloading color database..."); - mColors.clear(); + mHairColors.clear(); + mColorLists.clear(); mLoaded = false; } -std::string &ColorDB::get(int id) +std::string &ColorDB::getHairColor(int id) { if (!mLoaded) load(); - ColorIterator i = mColors.find(id); + ColorIterator i = mHairColors.find(id); - if (i == mColors.end()) + if (i == mHairColors.end()) { logger->log("ColorDB: Error, unknown dye ID# %d", id); return mFail; @@ -109,7 +156,17 @@ std::string &ColorDB::get(int id) } } -int ColorDB::size() +int ColorDB::getHairSize() { - return static_cast<int>(mColors.size()); + return static_cast<int>(mHairColors.size()); +} + +std::map <int, ColorDB::ItemColor> *ColorDB::getColorsList(std::string name) +{ + std::map <int, ItemColor> colors; + ColorListsIterator it = mColorLists.find(name); + + if (it != mColorLists.end()) + return &it->second; + return 0; } diff --git a/src/resources/colordb.h b/src/resources/colordb.h index 72d34afe8..fb0da0036 100644 --- a/src/resources/colordb.h +++ b/src/resources/colordb.h @@ -29,23 +29,51 @@ */ namespace ColorDB { + class ItemColor + { + public: + ItemColor() + { } + ItemColor(int id, std::string name, std::string color) + { + this->id = id; + this->name = name; + this->color = color; + } + + int id; + std::string name; + std::string color; + }; + /** * Loads the color data from <code>colors.xml</code>. */ void load(); /** + * Loads the color data from <code>colors.xml</code>. + */ + void loadHair(); + + void loadColorLists(); + + /** * Clear the color data */ void unload(); - std::string &get(int id); + std::string &getHairColor(int id); + + int getHairSize(); - int size(); + std::map <int, ItemColor> *getColorsList(std::string name); // Color DB typedef std::map<int, std::string> Colors; typedef Colors::iterator ColorIterator; + typedef std::map <std::string, std::map <int, ItemColor> > ColorLists; + typedef ColorLists::iterator ColorListsIterator; } #endif diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp index 418bfb848..4ba254cf3 100644 --- a/src/resources/itemdb.cpp +++ b/src/resources/itemdb.cpp @@ -22,6 +22,7 @@ #include "resources/itemdb.h" +#include "client.h" #include "log.h" #include "resources/iteminfo.h" @@ -207,6 +208,11 @@ void ItemDB::load() std::string drawBefore = XML::getProperty(node, "drawBefore", ""); std::string drawAfter = XML::getProperty(node, "drawAfter", ""); std::string removeSprite = XML::getProperty(node, "removeSprite", ""); + std::string colors; + if (serverVersion >= 1) + colors = XML::getProperty(node, "colors", ""); + else + colors = ""; std::string tags[3]; tags[0] = XML::getProperty(node, "tag", @@ -266,6 +272,7 @@ void ItemDB::load() itemInfo->setDrawBefore(parseSpriteName(drawBefore)); itemInfo->setDrawAfter(parseSpriteName(drawAfter)); itemInfo->setDrawPriority(drawPriority); + itemInfo->setColorsList(colors); std::string effect; for (int i = 0; i < int(sizeof(fields) / sizeof(fields[0])); ++i) diff --git a/src/resources/iteminfo.cpp b/src/resources/iteminfo.cpp index 255a9a7b3..990c78f45 100644 --- a/src/resources/iteminfo.cpp +++ b/src/resources/iteminfo.cpp @@ -81,3 +81,29 @@ std::map<int, int> &ItemInfo::addReplaceSprite(int sprite) } return it->second; } + +void ItemInfo::setColorsList(std::string name) +{ + if (name.empty()) + { + mColors = 0; + mColorList = ""; + } + else + { + mColors = ColorDB::getColorsList(name); + mColorList = name; + } +} + +std::string ItemInfo::getDyeColorsString(int color) const +{ + if (!mColors || mColorList.empty()) + return ""; + + std::map <int, ColorDB::ItemColor>::iterator it = mColors->find(color); + if (it == mColors->end()) + return ""; + + return it->second.color; +}
\ No newline at end of file diff --git a/src/resources/iteminfo.h b/src/resources/iteminfo.h index 5ea537fae..297c1b036 100644 --- a/src/resources/iteminfo.h +++ b/src/resources/iteminfo.h @@ -25,6 +25,7 @@ #include "being.h" +#include "resources/colordb.h" #include "resources/spritedef.h" #include <map> @@ -111,7 +112,9 @@ class ItemInfo mDrawPriority(0), mIsRemoveSprites(false), mAttackAction(SpriteAction::INVALID), - mAttackRange(0) + mAttackRange(0), + mColors(0), + mColorList("") { } @@ -231,6 +234,15 @@ class ItemInfo std::map<int, std::map<int, int> > getSpriteToItemReplaceMap() const { return mSpriteToItemReplaceMap; } + std::string getDyeString(int color) const; + + std::string getDyeColorsString(int color) const; + + void setColorsList(std::string name); + + bool isHaveColors() + { return !mColorList.empty(); } + protected: SpriteDisplay mDisplay; /**< Display info (like icon) */ std::string mName; @@ -265,6 +277,8 @@ class ItemInfo /** Stores the names of sounds to be played at certain event. */ std::map < EquipmentSoundEvent, std::vector<std::string> > mSounds; std::map <int, int> mTags; + std::map <int, ColorDB::ItemColor> *mColors; + std::string mColorList; }; #endif diff --git a/src/utils/stringutils.cpp b/src/utils/stringutils.cpp index d914efe30..63924eb78 100644 --- a/src/utils/stringutils.cpp +++ b/src/utils/stringutils.cpp @@ -387,3 +387,54 @@ std::list<int> splitToIntList(const std::string &text, char separator) return tokens; } + + +std::list<std::string> splitToStringList(const std::string &text, + char separator) +{ + std::list<std::string> tokens; + std::stringstream ss(text); + std::string item; + while(std::getline(ss, item, separator)) + tokens.push_back(item); + + return tokens; +} + +std::string combineDye(std::string file, std::string dye) +{ + if (dye.empty()) + return file; + size_t pos = file.find_last_of("|"); + if (pos != std::string::npos) + return file.substr(0, pos) + "|" + dye; + return file + "|" + dye; +} + +std::string combineDye2(std::string file, std::string dye) +{ + if (dye.empty()) + return file; + + size_t pos = file.find_last_of("|"); + if (pos != std::string::npos) + { + std::string dye1 = file.substr(pos + 1); + std::string str = ""; + file = file.substr(0, pos); + std::list<std::string> list1 = splitToStringList(dye1, ';'); + std::list<std::string> list2 = splitToStringList(dye, ';'); + std::list<std::string>::iterator it1, it1_end = list1.end(); + std::list<std::string>::iterator it2, it2_end = list2.end(); + for (it1 = list1.begin(), it2 = list2.begin(); + it1 != it1_end && it2 != it2_end; ++it1, ++it2) + { + str += (*it1) + ":" + (*it2) + ";"; + } + return file + "|" + str; + } + else + { + return file; + } +} diff --git a/src/utils/stringutils.h b/src/utils/stringutils.h index ab16bb64b..02c25eddb 100644 --- a/src/utils/stringutils.h +++ b/src/utils/stringutils.h @@ -170,4 +170,11 @@ std::set<int> splitToIntSet(const std::string &text, char separator); std::list<int> splitToIntList(const std::string &text, char separator); +std::list<std::string> splitToStringList(const std::string &text, + char separator); + +std::string combineDye(std::string file, std::string dye); + +std::string combineDye2(std::string file, std::string dye); + #endif // UTILS_STRINGUTILS_H |