Ir para conteúdo

Featured Replies

Postado
  • 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

item_attribute.thumb.gif.8efa31acfe22775c64ed36b9e6fc81d6.gif

 

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 por Leohige (veja o histórico de edições)

Postado

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

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.

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.

Visitante
Responder

Quem Está Navegando 0

  • Nenhum usuário registrado visualizando esta página.

Estatísticas dos Fóruns

  • Tópicos 96.9k
  • Posts 519.6k

Informação Importante

Confirmação de Termo