Por
sornii
Olá, tenho alma de compartilhador de conhecimento, assim como peguei algumas coisas daqui, sinto que devo também.
Meu parceiro pediu-me que fizesse com que as quests dele tivessem seu funcionamento no TFS 1.0 assim como em um servidor que baixara a muito tempo. Eu olhei o script e era uma zona total, não entendi nada e resolvi escrever um do jeito que eu entendo por programação.
O que ele gostaria é que tivesse o poder de criar quests, do modo antigo do tibia, apenas você e o baú, pelo próprio editor. Com essa maneira, ele simplesmente coloca qualquer container no mapa, mas pera aí, o que é um container para um código de OT? É qualquer coisa que possa carregar em dentro de si, uma ou mais de uma outra coisa. Corpos mortos, baús, etc.
Note que caso o container, por exemplo um baú, seja para beneficar o jogador com mais de um item, é necessário criar um outro container dentro deste e adicionar os itens dentro desse último container criado. Um exemplo: para uma quest que dê 10 cerejas e 10 pães crie um baú com uma bag dentro, dentro da bag adicione as 10 cerejas e os 10 pães.
Mãos a obra.
Copie o código abaixo para um arquivo com qualquer nome desejável, eu o nomeei de "editor.lua"
function onUse(cid, item, fromPosition, itemEx, toPosition)
local container = Container(item.uid)
local player = Player(cid)
if player:getStorageValue(item.uid) == -1 then
local questReward = container:getItem(0)
local questRewardName = questReward:getType():getName()
local weight = 0;
if questReward:isContainer() then
weight = questReward:getWeight()
else
weight = questReward:getType():getWeight(questReward:getCount())
end
local freecap = player:getFreeCapacity()
if freecap >= weight then
local reward = questReward:clone()
local result = player:addItemEx(reward)
if result ~= RETURNVALUE_NOERROR then
player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have not enough room.')
else
player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have found a ' .. questRewardName .. '.')
player:setStorageValue(item.uid, 1)
end
else
player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have found a ' .. questRewardName .. ' weighing ' .. string.format("%.2f", weight) .. ' oz. It\'s too heavy.')
end
else
player:sendTextMessage(MESSAGE_INFO_DESCR, "It is empty.")
end
return true
end
Neste outro passo tu podes seguir dois caminhos, o primeiro e o mais correto é uma alteração no código fonte do forgottenserver. Então, desta forma, se for a preferia por ti. Faça:
No arquivo luascript.h, logo após a linha de número 744, ou procure algo parecido com:
static int32_t luaContainerGetSize(lua_State* L);
static int32_t luaContainerGetCapacity(lua_State* L);
static int32_t luaContainerGetEmptySlots(lua_State* L);
adicione uma nova linha com o seguinte:
static int32_t luaContainerGetWeight(lua_State* L);
No arquivo luascript.cpp, logo após a linha de número 2100, ou procure algo parecido com:
registerMethod("Container", "getSize", LuaScriptInterface::luaContainerGetSize);
registerMethod("Container", "getCapacity", LuaScriptInterface::luaContainerGetCapacity);
registerMethod("Container", "getEmptySlots", LuaScriptInterface::luaContainerGetEmptySlots);
adicione uma nova linha com o seguinte:
registerMethod("Container", "getWeight", LuaScriptInterface::luaContainerGetWeight);
Ainda em luascript.cpp, logo após a linha de número 6895, ou procure algo parecido com:
int32_t LuaScriptInterface::luaContainerGetEmptySlots(lua_State* L)
Logo após essa função (não a linha), insira o código abaixo:
int32_t LuaScriptInterface::luaContainerGetWeight(lua_State* L)
{
// container:getWeight()
Container* container = getUserdata<Container>(L, 1);
if (!container) {
lua_pushnil(L);
return 1;
}
double weight = container->getWeight();
lua_pushnumber(L, weight);
return 1;
}
E qual o motivo de eu preferir ter este código no lado do servidor compilado? Desempenho. O peso do container é guardado em memória e acessado diretamente, não há qualquer conta com inúmeras multiplicações ou funções recursivas.
Mas caso esteja de mal humor e não queira compilar um servidor, terá que construir uma função da qual eu particularmente não gosto:
function getWeight(item)
local totalWeight = 0;
if item:isContainer() then
local size = item:getSize()
for i = 0, size - 1 do
totalWeight = totalWeight + getWeight(item:getItem(i))
end
else
totalWeight = totalWeight + item:getType():getWeight(item:getCount())
end
return totalWeight;
end
Coloque este código, essa função, antes da função onUse dentro de editor.lua
E troque aonde diz
questReward:getWeight()
por
getWeight(questReward)
Para terminar e fechar logo, não esqueça de adicionar o action id , eu normalmente uso 2000 pra esta actionId. É importante também lembrar que o UniqueId do baú deve ser ÚNICO em todo seu servidor, apenas dessa forma poderemos saber quais baús o jogador já abriu e conseguiu a recompensa.
Agora, vá aos testes meu querido! Salve todos os scripts, se tiver que compilar o servidor, vá e faça isso. Coloque um baú no seu mapa com um item apenas dentro, se tu colocares mais do que um item, apenas o primeiro será considerado, assim como pode ser visto na linha:
local questReward = container:getItem(0)
Dessa forma, caso seja necessário vários itens, lembre-se, uma bag, backpack, qualquer container com os itens dentro.
Agora seja criativo, crie corpos de dragões, humanos, esqueletos, coloque chaves dentro de caixas, livros importantes na biblioteca, entre várias oportunidades.
E então, o que acharam?