Postado Janeiro 23, 2018 7 anos Este é um post popular. Bom, fiz essa função para um projeto open source meu e decidi postar ela a parte. O atributo funciona como no PxG, ele é exibido no fim da descrição do item quando dado look. Você pode definir valores para cada item no items.xml, e quando os itens são agrupados o seu valor é multiplicado pela quantidade do mesmo. Também é possível alterar/pegar o valor do item durante o jogo utilizando código Lua. Demonstração Spoiler Exemplo de Item Spoiler O valor é em gold coins, então para calcular algo como 100 k você precisará pegar o número 100000 e multiplicar por 100. <item id="1294" article="a" name="small stone"> <attribute key="price" value="50" /> </item> Funções Lua Spoiler --Item item:getPrice() item:setAttribute('price', 100) item:removeAttribute('price') item:hasAttribute('price') --ItemType itemType:getPrice([count = 1]) -- A quantidade é opcional Implementação Não darei suporte para versões anteriores a 1.3 do TFS. Se você for implementar o código em versões anteriores (1.0, 1.1, 1.2), recomendo que tenha bons conhecimentos em C++ pois provavelmente dará algum erro. Siga todos os passos cautelosamente. #1 Spoiler No arquivo enums.h encontre o código: ITEM_ATTRIBUTE_DOORID = 1 << 22, E abaixo dele coloque o seguinte: ITEM_ATTRIBUTE_PRICE = 1 << 23, #2 Spoiler 1. No arquivo item.h encontre o código: ATTR_CUSTOM_ATTRIBUTES = 34 E logo ao fim da linha, depois do 34 adicione uma ',' VIRGULA. Então logo abaixo dele coloque o seguinte código: ATTR_PRICE = 35, 2. Encontre o seguinte código: static std::string getWeightDescription(const ItemType& it, uint32_t weight, uint32_t count = 1); E abaixo dele coloque o seguinte: static std::string getPriceDescription(const ItemType& it, int32_t price, uint32_t count = 1); 3. Encontre o seguinte código: std::string getWeightDescription() const; E abaixo dele coloque o seguinte: std::string getPriceDescription() const; 4. Encontre o seguinte código: uint32_t getBaseWeight() const { if (hasAttribute(ITEM_ATTRIBUTE_WEIGHT)) { return getIntAttr(ITEM_ATTRIBUTE_WEIGHT); } return items[id].weight; } E abaixo dele coloque o seguinte: virtual int32_t getPrice() const; int32_t getBasePrice() const { if (hasAttribute(ITEM_ATTRIBUTE_PRICE)) { return getIntAttr(ITEM_ATTRIBUTE_PRICE); } return items[id].price; } 5. Encontre o seguinte código: std::string getWeightDescription(uint32_t weight) const; E abaixo dele coloque o seguinte: std::string getPriceDescription(int32_t price) const; 6. Encontre o seguinte código: return (type & 0x7FFE13) != 0; E substitua ele pelo seguinte: return (type & 0xFFFE13) != 0; #3 Spoiler 1. No arquivo items.h encontre o código: uint32_t charges = 0; E abaixo dele coloque o seguinte: int32_t price = -1; #4 Spoiler 1. No arquivo tools.cpp encontre o código: } else if (str == "doorid") { return ITEM_ATTRIBUTE_DOORID; E abaixo dele coloque o seguinte: } else if (str == "price") { return ITEM_ATTRIBUTE_PRICE; #5 Spoiler 1. No arquivo items.cpp encontre o código: } else if (tmpStrValue == "forceserialize" || tmpStrValue == "forcesave") { it.forceSerialize = valueAttribute.as_bool(); E abaixo dele coloque o seguinte: } else if (tmpStrValue == "price") { it.price = pugi::cast<int32_t>(valueAttribute.value()); #6 Spoiler 1. No arquivo item.cpp encontre o código: case ATTR_SHOOTRANGE: { uint8_t shootRange; if (!propStream.read<uint8_t>(shootRange)) { return ATTR_READ_ERROR; } setIntAttr(ITEM_ATTRIBUTE_SHOOTRANGE, shootRange); break; } E abaixo dele coloque o seguinte: case ATTR_PRICE: { int32_t price; if (!propStream.read<int32_t>(price)) { return ATTR_READ_ERROR; } setIntAttr(ITEM_ATTRIBUTE_PRICE, price); break; } 2. Encontre o seguinte código: if (hasAttribute(ITEM_ATTRIBUTE_SHOOTRANGE)) { propWriteStream.write<uint8_t>(ATTR_SHOOTRANGE); propWriteStream.write<uint8_t>(getIntAttr(ITEM_ATTRIBUTE_SHOOTRANGE)); } E abaixo dele coloque o seguinte: if (hasAttribute(ITEM_ATTRIBUTE_PRICE)) { propWriteStream.write<uint8_t>(ATTR_PRICE); propWriteStream.write<int32_t>(getIntAttr(ITEM_ATTRIBUTE_PRICE)); } 3. Encontre o seguinte código: uint32_t Item::getWeight() const { uint32_t weight = getBaseWeight(); if (isStackable()) { return weight * std::max<uint32_t>(1, getItemCount()); } return weight; } E abaixo dele coloque o seguinte: int32_t Item::getPrice() const { int32_t price = getBasePrice(); if (isStackable()) { return price * std::max<uint32_t>(1, getItemCount()); } return price; } 4. Encontre o seguinte código: if (it.allowDistRead && it.id >= 7369 && it.id <= 7371) { if (!text && item) { text = &item->getText(); } if (text && !text->empty()) { s << '\n' << *text; } } E abaixo dele coloque o seguinte: // Item Price if (item) { const int32_t price = item->getPrice(); if (price >= 0 && it.pickupable) { s << ' ' << getPriceDescription(it, price, item->getItemCount()); } } else if (it.price >= 0 && it.pickupable){ s << ' ' << getPriceDescription(it, it.price); } 5. Encontre o seguinte código: std::string Item::getWeightDescription() const { uint32_t weight = getWeight(); if (weight == 0) { return std::string(); } return getWeightDescription(weight); } E abaixo dele coloque o seguinte: /* function used to convert a double to string without scientific notation or trailing zeros */ static std::string dbl2str(double d) { size_t len = std::snprintf(0, 0, "%.10f", d); std::string s(len+1, 0); std::snprintf(&s[0], len+1, "%.10f", d); s.pop_back(); s.erase(s.find_last_not_of('0') + 1, std::string::npos); if(s.back() == '.') { s.pop_back(); } return s; } std::string Item::getPriceDescription(const ItemType& it, int32_t price, uint32_t count /*= 1*/) { std::ostringstream ss; ss << "Price: "; if (price == 0) { ss << "Unsellable"; } else { double finalPrice = price / 100.0; ss << "$"; ss << dbl2str(finalPrice); } ss << "."; return ss.str(); } std::string Item::getPriceDescription(int32_t price) const { const ItemType& it = Item::items[id]; return getPriceDescription(it, price, getItemCount()); } std::string Item::getPriceDescription() const { int32_t price = getPrice(); if (price < 0) { return std::string(); } return getPriceDescription(price); } #7 Spoiler 1. No arquivo luascript.h encontre o código: static int luaItemGetWeight(lua_State* L); E abaixo dele coloque o seguinte: static int luaItemGetPrice(lua_State* L); 2. Encontre o seguinte código: static int luaItemTypeGetWeight(lua_State* L); E abaixo dele coloque o seguinte: static int luaItemTypeGetPrice(lua_State* L); #8 Spoiler 1. No arquivo luascript.cpp encontre o código: registerEnum(ITEM_ATTRIBUTE_DOORID) E abaixo dele coloque o seguinte: registerEnum(ITEM_ATTRIBUTE_PRICE) 2. Encontre o seguinte código: registerMethod("Item", "getWeight", LuaScriptInterface::luaItemGetWeight); E abaixo dele coloque o seguinte: registerMethod("Item", "getPrice", LuaScriptInterface::luaItemGetPrice); 3. Encontre o seguinte código: registerMethod("ItemType", "getWeight", LuaScriptInterface::luaItemTypeGetWeight); E abaixo dele coloque o seguinte: registerMethod("ItemType", "getPrice", LuaScriptInterface::luaItemTypeGetPrice); 4. Encontre o seguinte código: int LuaScriptInterface::luaItemGetWeight(lua_State* L) { // item:getWeight() Item* item = getUserdata<Item>(L, 1); if (item) { lua_pushnumber(L, item->getWeight()); } else { lua_pushnil(L); } return 1; } E abaixo dele coloque o seguinte: int LuaScriptInterface::luaItemGetPrice(lua_State* L) { // item:getPrice() Item* item = getUserdata<Item>(L, 1); if (item) { lua_pushnumber(L, item->getPrice()); } else { lua_pushnil(L); } return 1; } 5. Encontre o seguinte código: int LuaScriptInterface::luaItemTypeGetWeight(lua_State* L) { // itemType:getWeight([count = 1]) uint16_t count = getNumber<uint16_t>(L, 2, 1); const ItemType* itemType = getUserdata<const ItemType>(L, 1); if (!itemType) { lua_pushnil(L); return 1; } uint64_t weight = static_cast<uint64_t>(itemType->weight) * std::max<int32_t>(1, count); lua_pushnumber(L, weight); return 1; } E abaixo dele coloque o seguinte: int LuaScriptInterface::luaItemTypeGetPrice(lua_State* L) { // itemType:getPrice([count = 1]) uint16_t count = getNumber<uint16_t>(L, 2, 1); const ItemType* itemType = getUserdata<const ItemType>(L, 1); if (!itemType) { lua_pushnil(L); return 1; } int64_t price = static_cast<int64_t>(itemType->price) * std::max<int32_t>(1, count); lua_pushnumber(L, price); return 1; } Editado Janeiro 23, 2018 7 anos por Leohige (veja o histórico de edições)
Postado Janeiro 24, 2018 7 anos Parabéns, seu tópico de conteúdo foi aprovado! Muito obrigado pela sua contribuição, nós do Tibia King agradecemos. Seu conteúdo com certeza ajudará à muitos outros, você recebeu +1 REP. Spoiler Congratulations, your content has been approved! Thank you for your contribution, we of Tibia King we are grateful. Your content will help many other users, you received +1 REP. A TFS 1.3 já tem um sistema de adicionar um atributo custom no item de maneira mais eficiente, dai você só teria que fazer a parte lua... Mas muito bom.
Postado Janeiro 24, 2018 7 anos Muito bacana esse sistema, fiquei pensando se esses preços seriam o custo do item em NPCs ou market, pois dependendo da oferta/demanda os players negociam valores diferentes. De qualquer forma é muito criativo, parabéns.
Postado Janeiro 24, 2018 7 anos Bom demais, vai ajudar muita gente, até de base pra caso alguém queira adicionar algo semelhante, parabéns xD
Participe da conversa
Você pode postar agora e se cadastrar mais tarde. Se você tem uma conta, faça o login para postar com sua conta.