From df5c7ae83a80db63ab90142df9e3a93f5ee630d0 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Sun, 27 Feb 2011 18:08:34 +0200 Subject: First part of implimintation item colors. --- src/net/tmwa/charserverhandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/net/tmwa/charserverhandler.cpp') diff --git a/src/net/tmwa/charserverhandler.cpp b/src/net/tmwa/charserverhandler.cpp index 5e2efbdd5..ec61b4be2 100644 --- a/src/net/tmwa/charserverhandler.cpp +++ b/src/net/tmwa/charserverhandler.cpp @@ -273,7 +273,7 @@ void CharServerHandler::readPlayerData(Net::MessageIn &msg, tempPlayer->setSubtype(msg.readInt16()); // class (used for race) int hairStyle = msg.readInt16(); Uint16 weapon = msg.readInt16(); - tempPlayer->setSprite(SPRITE_WEAPON, weapon, "", true); + tempPlayer->setSprite(SPRITE_WEAPON, weapon, "", 1, true); character->data.mAttributes[LEVEL] = msg.readInt16(); -- cgit v1.2.3-70-g09d2 From 1373ea47dc7d6a2afd1ce118d5f9e307326beb02 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Mon, 28 Feb 2011 22:43:06 +0200 Subject: Add support for reading item colors for char list and created char (for extended servers) --- src/net/tmwa/charserverhandler.cpp | 91 ++++++++++++++++++++++++++++++-------- src/net/tmwa/charserverhandler.h | 3 +- src/net/tmwa/network.cpp | 4 +- src/net/tmwa/protocol.h | 2 + 4 files changed, 78 insertions(+), 22 deletions(-) (limited to 'src/net/tmwa/charserverhandler.cpp') diff --git a/src/net/tmwa/charserverhandler.cpp b/src/net/tmwa/charserverhandler.cpp index ec61b4be2..686b67a0e 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,7 +83,8 @@ 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; + msg.skip(17); // Unused delete_all(mCharacters); mCharacters.clear(); @@ -93,7 +95,7 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg) 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 +125,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 +257,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(Net::getLoginHandler())->getToken(); @@ -254,10 +274,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 +292,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(); + 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()); + + int misc2 = msg.readInt16(); tempPlayer->setName(msg.readString(24)); character->dummy = tempPlayer; @@ -297,7 +315,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/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/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 -- cgit v1.2.3-70-g09d2 From 218dbbd7ce5415fe8c26857f06c5907c7cc6d175 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Tue, 1 Mar 2011 19:44:49 +0200 Subject: Fix char slots number calculation. --- src/net/tmwa/charserverhandler.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/net/tmwa/charserverhandler.cpp') diff --git a/src/net/tmwa/charserverhandler.cpp b/src/net/tmwa/charserverhandler.cpp index 686b67a0e..a1b7c83b8 100644 --- a/src/net/tmwa/charserverhandler.cpp +++ b/src/net/tmwa/charserverhandler.cpp @@ -90,7 +90,11 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg) 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) { -- cgit v1.2.3-70-g09d2 From 582428edf9e40db0d1ed7b78222562a7a5031fe4 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Wed, 2 Mar 2011 01:51:25 +0200 Subject: Add serverversion checks. And disable some advanced features in old servers. --- src/client.cpp | 1 + src/client.h | 1 + src/net/tmwa/beinghandler.cpp | 21 ++++++++++++++++----- src/net/tmwa/charserverhandler.cpp | 2 +- src/net/tmwa/inventoryhandler.cpp | 32 +++++++++++++++++++++++--------- src/net/tmwa/loginhandler.cpp | 26 +++++++++++++++++--------- 6 files changed, 59 insertions(+), 24 deletions(-) (limited to 'src/net/tmwa/charserverhandler.cpp') 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/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index 9c5c45185..0548a2715 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -631,7 +631,10 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) else { // SMSG_BEING_CHANGE_LOOKS2 id = msg.readInt16(); - id2 = msg.readInt16(); + if (type == 2 || serverVersion > 0) + id2 = msg.readInt16(); + else + id2 = 1; color = ""; } @@ -907,10 +910,18 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) if (!config.getBoolValue("hideShield")) dstBeing->setSprite(SPRITE_SHIELD, shield); //dstBeing->setSprite(SPRITE_SHOE, shoes); - logger->log("bmt: %d, %d, %d", colors[0], colors[2], colors[1]); - dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, headBottom, "", colors[0]); - dstBeing->setSprite(SPRITE_TOPCLOTHES, headMid, "", colors[2]); - dstBeing->setSprite(SPRITE_HAT, headTop, "", colors[1]); + 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); diff --git a/src/net/tmwa/charserverhandler.cpp b/src/net/tmwa/charserverhandler.cpp index a1b7c83b8..35cca6f07 100644 --- a/src/net/tmwa/charserverhandler.cpp +++ b/src/net/tmwa/charserverhandler.cpp @@ -83,7 +83,7 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg) int slots = msg.readInt16(); if (slots > 0 && slots < 30) loginData.characterSlots = slots; - bool version = msg.readInt8() == 1; + bool version = msg.readInt8() == 1 && serverVersion > 0; msg.skip(17); // Unused delete_all(mCharacters); diff --git a/src/net/tmwa/inventoryhandler.cpp b/src/net/tmwa/inventoryhandler.cpp index fc32c3ec3..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 @@ -255,6 +258,9 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) refine); } + if (serverVersion < 1 && identified > 1) + identified = 1; + mInventoryItems.push_back(InventoryItem(index, itemId, amount, refine, identified, false)); } @@ -299,6 +305,9 @@ 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, identified, equipType != 0); } @@ -410,6 +419,9 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) { if (mStorage) { + if (serverVersion < 1 && identified > 1) + identified = 1; + mStorage->setItem(index, itemId, amount, refine, identified, false); } @@ -458,29 +470,31 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) { index = msg.readInt16() - INVENTORY_OFFSET; itemId = msg.readInt16(); - if (itemId == 1172) - logger->log("step1"); 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 (itemId == 1172) - logger->log("step2"); - if (inventory) - inventory->setItem(index, itemId, 1, refine, identified, true); - - if (equipType) - mEquips.setEquipment(getSlot(equipType), index); 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, identified, true); + + if (equipType) + mEquips.setEquipment(getSlot(equipType), index); + } break; 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; -- cgit v1.2.3-70-g09d2 From 22f79fd0d623c8e11994905534f53da267e22935 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Thu, 3 Mar 2011 01:25:21 +0200 Subject: Dehardcode item colors. Now reading all from configs. --- src/actorsprite.cpp | 4 +-- src/flooritem.cpp | 2 +- src/gui/charcreatedialog.cpp | 8 ++--- src/item.cpp | 4 +-- src/net/manaserv/beinghandler.cpp | 4 +-- src/net/manaserv/charhandler.cpp | 2 +- src/net/tmwa/beinghandler.cpp | 6 ++-- src/net/tmwa/charserverhandler.cpp | 2 +- src/resources/colordb.cpp | 74 ++++++++++++++++++++++++++++++++------ src/resources/colordb.h | 32 +++++++++++++++-- src/resources/itemdb.cpp | 2 ++ src/resources/iteminfo.cpp | 36 +++++++++---------- src/resources/iteminfo.h | 12 ++++++- src/utils/stringutils.cpp | 41 +++++++++++++++++++++ src/utils/stringutils.h | 5 +++ 15 files changed, 186 insertions(+), 48 deletions(-) (limited to 'src/net/tmwa/charserverhandler.cpp') diff --git a/src/actorsprite.cpp b/src/actorsprite.cpp index 4188ff224..686c871e7 100644 --- a/src/actorsprite.cpp +++ b/src/actorsprite.cpp @@ -312,7 +312,7 @@ void ActorSprite::setupSpriteDisplay(const SpriteDisplay &display, it != it_end; ++it) { std::string file = "graphics/sprites/" - + combineDye((*it)->sprite, color); + + combineDye2((*it)->sprite, color); int variant = (*it)->variant; addSprite(AnimatedSprite::load(file, variant)); @@ -339,7 +339,7 @@ void ActorSprite::setupSpriteDisplay(const SpriteDisplay &display, imagePath = "graphics/items/" + display.floor; break; } - imagePath = combineDye(imagePath, color); + imagePath = combineDye2(imagePath, color); Image *img = resman->getImage(imagePath); diff --git a/src/flooritem.cpp b/src/flooritem.cpp index 700d9ed25..740daf387 100644 --- a/src/flooritem.cpp +++ b/src/flooritem.cpp @@ -72,7 +72,7 @@ FloorItem::FloorItem(int id, } ItemInfo info = ItemDB::get(itemId); - setupSpriteDisplay(info.getDisplay(), true, 1, info.getDyeString(mColor)); + setupSpriteDisplay(info.getDisplay(), true, 1, info.getDyeColorsString(mColor)); } const ItemInfo &FloorItem::getInfo() const 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/item.cpp b/src/item.cpp index 02f775834..ed0685a9d 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -75,7 +75,7 @@ void Item::setId(int id, unsigned char color) SpriteDisplay display = info.getDisplay(); std::string imagePath = paths.getStringValue("itemIcons") + display.image; - std::string dye = combineDye(imagePath, info.getDyeString(color)); + std::string dye = combineDye2(imagePath, info.getDyeColorsString(color)); mImage = resman->getImage(dye); mDrawImage = resman->getImage(dye); @@ -106,7 +106,7 @@ Image *Item::getImage(int id, unsigned char color) SpriteDisplay display = info.getDisplay(); std::string imagePath = "graphics/items/" + display.image; Image *image; - image = resman->getImage(combineDye(imagePath, info.getDyeString(color))); + image = resman->getImage(combineDye2(imagePath, info.getDyeColorsString(color))); if (!image) image = Theme::getImageFromTheme("unknown-item.png"); diff --git a/src/net/manaserv/beinghandler.cpp b/src/net/manaserv/beinghandler.cpp index 8ba2e5967..b726bc52e 100644 --- a/src/net/manaserv/beinghandler.cpp +++ b/src/net/manaserv/beinghandler.cpp @@ -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/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/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index 0548a2715..b1c173df6 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -290,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); @@ -671,7 +671,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) 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")) @@ -927,7 +927,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) //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 35cca6f07..daf531f04 100644 --- a/src/net/tmwa/charserverhandler.cpp +++ b/src/net/tmwa/charserverhandler.cpp @@ -309,7 +309,7 @@ void CharServerHandler::readPlayerData(Net::MessageIn &msg, int topClothes = msg.readInt16(); tempPlayer->setSprite(SPRITE_HAIR, hairStyle * -1, - ColorDB::get(msg.readInt16())); + ColorDB::getHairColor(msg.readInt16())); int misc2 = msg.readInt16(); tempPlayer->setName(msg.readString(24)); diff --git a/src/resources/colordb.cpp b/src/resources/colordb.cpp index c35cec95e..79622e8ed 100644 --- a/src/resources/colordb.cpp +++ b/src/resources/colordb.cpp @@ -28,9 +28,10 @@ namespace { - ColorDB::Colors mColors; + ColorDB::Colors mHairColors; bool mLoaded = false; std::string mFail = "#ffffff"; + ColorDB::ColorLists mColorLists; } void ColorDB::load() @@ -38,6 +39,12 @@ void ColorDB::load() if (mLoaded) unload(); + loadHair(); + loadColorLists(); +} + +void ColorDB::loadHair() +{ XML::Document *doc = new XML::Document("hair.xml"); xmlNodePtr root = doc->rootNode(); bool hairXml = true; @@ -55,7 +62,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 +76,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 +90,59 @@ 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 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(); 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 +153,17 @@ std::string &ColorDB::get(int id) } } -int ColorDB::size() +int ColorDB::getHairSize() { - return static_cast(mColors.size()); + return static_cast(mHairColors.size()); +} + +std::map *ColorDB::getColorsList(std::string name) +{ + std::map 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 colors.xml. */ void load(); + /** + * Loads the color data from colors.xml. + */ + 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 *getColorsList(std::string name); // Color DB typedef std::map Colors; typedef Colors::iterator ColorIterator; + typedef std::map > ColorLists; + typedef ColorLists::iterator ColorListsIterator; } #endif diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp index 418bfb848..d515495de 100644 --- a/src/resources/itemdb.cpp +++ b/src/resources/itemdb.cpp @@ -207,6 +207,7 @@ 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 = XML::getProperty(node, "colors", ""); std::string tags[3]; tags[0] = XML::getProperty(node, "tag", @@ -266,6 +267,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 49aadc23d..990c78f45 100644 --- a/src/resources/iteminfo.cpp +++ b/src/resources/iteminfo.cpp @@ -82,30 +82,28 @@ std::map &ItemInfo::addReplaceSprite(int sprite) return it->second; } -std::string ItemInfo::getDyeString(int color) const +void ItemInfo::setColorsList(std::string name) { - if (mId == 1172) + if (name.empty()) { - if (color == 1) - return "W:#115511,22aa22,99dd99;R:#547000,a5dc00,d1ff46"; - if (color == 0) - return "W:#547000,a5dc00,d1ff46;R:#115511,22aa22,99dd99"; - if (color == 3) - return "W:#ffffff,000000,000000;R:#333333,333333,333333"; + mColors = 0; + mColorList = ""; + } + else + { + mColors = ColorDB::getColorsList(name); + mColorList = name; } - return ""; } std::string ItemInfo::getDyeColorsString(int color) const { - if (mId == 1172) - { - if (color == 1) - return "#115511,22aa22,99dd99;#547000,a5dc00,d1ff46"; - if (color == 0) - return "#547000,a5dc00,d1ff46;#115511,22aa22,99dd99"; - if (color == 3) - return "#ffffff,000000,000000;#333333,333333,333333"; - } - return ""; + if (!mColors || mColorList.empty()) + return ""; + + std::map ::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 3b72c7830..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 @@ -111,7 +112,9 @@ class ItemInfo mDrawPriority(0), mIsRemoveSprites(false), mAttackAction(SpriteAction::INVALID), - mAttackRange(0) + mAttackRange(0), + mColors(0), + mColorList("") { } @@ -235,6 +238,11 @@ class ItemInfo 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; @@ -269,6 +277,8 @@ class ItemInfo /** Stores the names of sounds to be played at certain event. */ std::map < EquipmentSoundEvent, std::vector > mSounds; std::map mTags; + std::map *mColors; + std::string mColorList; }; #endif diff --git a/src/utils/stringutils.cpp b/src/utils/stringutils.cpp index 835f9ce00..63924eb78 100644 --- a/src/utils/stringutils.cpp +++ b/src/utils/stringutils.cpp @@ -388,6 +388,19 @@ std::list splitToIntList(const std::string &text, char separator) return tokens; } + +std::list splitToStringList(const std::string &text, + char separator) +{ + std::list 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()) @@ -397,3 +410,31 @@ std::string combineDye(std::string file, std::string dye) 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 list1 = splitToStringList(dye1, ';'); + std::list list2 = splitToStringList(dye, ';'); + std::list::iterator it1, it1_end = list1.end(); + std::list::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 52b47e6a2..02c25eddb 100644 --- a/src/utils/stringutils.h +++ b/src/utils/stringutils.h @@ -170,6 +170,11 @@ std::set splitToIntSet(const std::string &text, char separator); std::list splitToIntList(const std::string &text, char separator); +std::list 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 -- cgit v1.2.3-70-g09d2