Ir para conteúdo

Posts Recomendados

  • Administrador
Testado em TFS 1.2, 10.77/78
reward_system2.png
INSTRUÇÕES
Execute a query na database:
CREATE TABLE IF NOT EXISTS `player_rewardchest` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `player_id` int(11) NOT NULL,
    `reward` text NOT NULL,
    `date` bigint(20) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;
src/const.h
Antes de...
ITEM_MARKET = 14405

Adicione:

ITEM_REWARD_CHEST = 21584,
REWARD_CHEST_DEPOT = 99,

separador-1.png

src/depotchest.h
Antes de:
explicit DepotChest(uint16_t _type);
Adicione:
uint32_t getDepotId() const {
    return depotId;
}


void setDepotId(uint32_t id) {
    depotId = id;
}

Antes de:

uint32_t maxDepotItems;

Adicione:

uint32_t depotId;src/depotchest.cpp

Antes de:

maxDepotItems = 1500;
Adicione:
depotId = 0;

Acima de:

return Container::queryAdd(index, thing, count, flags, actor);
Adicione:
if (actor != nullptr && getDepotId() == REWARD_CHEST_DEPOT) {
    return RETURNVALUE_NOTPOSSIBLE;
}src/depotlocker.h
Acima de:
//cylinder implementations
Adicione:
void setMaxLockerItems(uint32_t maxitems) {
    maxSize = maxitems;
}

separador-1.png

src/luascript.h
Acima de:
static int luaContainerGetSize(lua_State* L);
Adicione
static int luaContainerGetContentDescription(lua_State* L);

separador-1.png

src/luascript.cpp
Acima de:
registerMethod("Container", "getSize", LuaScriptInterface::luaContainerGetSize);
Adicione:
registerMethod("Container", "getContentDescription", LuaScriptInterface::luaContainerGetContentDescription);
Acima:
int LuaScriptInterface::luaContainerGetSize(lua_State* L)
Adicione:
int LuaScriptInterface::luaContainerGetContentDescription(lua_State* L)
{
    // container:getContentDescription()
    Container* container = getUserdata<Container>(L, 1);
    if (container) {
        std::ostringstream ss;
        ss << container->getContentDescription();
        pushString(L, ss.str());
    } else {
        lua_pushnil(L);
    }
    return 1;
}

separador-1.png

src/actions.cpp
Mude:
//depot container
if (DepotLocker* depot = container->getDepotLocker()) {
    DepotLocker* myDepotLocker = player->getDepotLocker(depot->getDepotId());
    myDepotLocker->setParent(depot->getParent()->getTile());
    openContainer = myDepotLocker;
    player->setLastDepotId(depot->getDepotId());
} else {
    openContainer = container;
}
Para:
//reward chest and depot container
if (item->getID() == ITEM_REWARD_CHEST) {
    DepotLocker* myRewardChest = player->getRewardChest();
    myRewardChest->setParent(item->getTile());
    openContainer = myRewardChest;
    player->setLastDepotId(REWARD_CHEST_DEPOT);
} else if (DepotLocker* depot = container->getDepotLocker()) {
    DepotLocker* myDepotLocker = player->getDepotLocker(depot->getDepotId());
    myDepotLocker->setParent(depot->getParent()->getTile());
    openContainer = myDepotLocker;
    player->setLastDepotId(depot->getDepotId());
} else {
    openContainer = container;
}
separador-1.png
src/player.h
Antes de:
DepotLocker* getDepotLocker(uint32_t depotId);
Adicione:
DepotLocker* getRewardChest();
separador-1.png
src/player.cpp
Antes de:
DepotChest* depotChest = new DepotChest(ITEM_DEPOT);
Adicione:
depotChest->setDepotId(depotId);
Acima de:
void Player::sendCancelMessage(ReturnValue message) const
Adicione:
DepotLocker* Player::getRewardChest()
{
    auto it = depotLockerMap.find(REWARD_CHEST_DEPOT);
    if (it != depotLockerMap.end()) {
        inbox->setParent(it->second);
        return it->second;
    }


    DepotLocker* rewardChest = new DepotLocker(ITEM_LOCKER1);
    rewardChest->setDepotId(REWARD_CHEST_DEPOT);
    rewardChest->setMaxLockerItems(1);
    rewardChest->internalAddThing(getDepotChest(REWARD_CHEST_DEPOT, true));
    depotLockerMap[REWARD_CHEST_DEPOT] = rewardChest;
    return rewardChest;
}

separador-1.png

On player.cpp, container.cpp, inbox.cpp
Mude:
if (!item->isPickupable()) {

Para:

if (item->getID() != 21518 && !item->isPickupable()) {

separador-1.png

Adicione @ data/actions/actions.xml
<!-- Reward Chest System -->
<action itemid="21584" script="reward_chest.lua"/>
<action actionid="21584" script="reward_chest.lua"/>
Crie @ data/actions/scripts/reward_chest.lua
function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    --Reward Chest
    if item:getId() == 21584 then
        if player:getExhaustion(REWARD_CHEST.STORAGE) > 0 then
            return player:sendCancelMessage('You need to wait ' .. string.diff(player:getStorageValue(REWARD_CHEST.STORAGE)-os.time()) .. ' before using this chest again.')
        end
        player:updateRewardChest()
    --Boss Corpse
    elseif item:getActionId() == 21584 then
        local reward = REWARD_CHEST.LOOT[tonumber(item:getAttribute('text'))][player:getGuid()]
        if reward ~= nil then
            local rewardBag = Container(doCreateItemEx(REWARD_CHEST.CONTAINER, 1))
            addContainerItems(rewardBag, reward)
            if player:getCapacity() < rewardBag:getCapacity() then
                return player:sendCancelMessage(RETURNVALUE_NOTENOUGHCAPACITY)
            end
            if player:addItemEx(rewardBag, false) == RETURNVALUE_NOERROR then
                REWARD_CHEST.LOOT[tonumber(item:getAttribute('text'))][player:getGuid()] = nil
                player:sendCancelMessage('You have picked a reward container.')
            else
                player:sendCancelMessage(RETURNVALUE_NOTENOUGHROOM)
                return true
            end
        end
    end
    return false
end
Adicione @ data/creaturescripts/creaturescripts.xml
<event type="kill" name="RewardChest" script="reward_chest.lua"/>
Register @data/creaturescripts/scripts/login.lua
player:registerEvent("RewardChest")

Crie @ data/creaturescripts/scripts/reward_chest.lua

REWARD_CHEST = {
    BOSSES = {"Bibby Bloodbath", "Chizzoron the Distorter", "Ferumbras",
            "Furyosa", "Gaz'haragoth", "Ghazbaran", "Hirintror",
            "Jaul", "Mad Mage", "Mawhawk", "Morgaroth", "Obujos",
            "Ocyakao", "Omrafir", "Orshabaal", "Raging Mage",
            "Tanjis", "The Mutated Pumpkin", "The Pale Count",
            "The Welter", "Tyrn", "White Pale", "Zulazza the Corruptor",
            "Zushuka"},
    LOOT = {},     
    DECAY = {},
    DEPOT_ID = 99,
    CONTAINER = 21518,
    EXPIRE = 7*24*60*60,     --days to erase stored rewards
    STORAGE = 18394,         --player storage for chest exhaustion
    EXHAUST = 5*60,         --time allowed to use again the chest
}

function table.find(t, value, sensitive)
    local sensitive = sensitive or true
    if(not sensitive and type(value) == 'string') then
        for i, v in pairs(t) do
            if(type(v) == 'string') then
                if(v:lower() == value:lower()) then
                    return i
                end
            end
        end
        return nil
    end
    for i, v in pairs(t) do
        if(v == value) then
            return i
        end
    end
    return nil
end

function table.serialize(x, recur)
    local t = type(x)
    recur = recur or {}
    if(t == nil) then
        return "nil"
    elseif(t == "string") then
        return string.format("%q", x)
    elseif(t == "number") then
        return tostring(x)
    elseif(t == "boolean") then
        return x and "true" or "false"
    elseif(getmetatable(x)) then
        error("Can not serialize a table that has a metatable associated with it.")
    elseif(t == "table") then
        if(table.find(recur, x)) then
            error("Can not serialize recursive tables.")
        end
        table.insert(recur, x)
        local s = "{"
        for k, v in pairs(x) do
            s = s .. "[" .. table.serialize(k, recur) .. "]" .. " = " .. table.serialize(v, recur) .. ", "
        end
        return s:sub(0, s:len() - 2) .. "}"
    end
    error("Can not serialize value of type '" .. t .. "'.")
end

function table.unserialize(str)
    return loadstring('return ' .. str)()
end

function addContainerItems(container, items)
    for k, v in pairs(items) do
        if ItemType(k):isContainer() then
            local newBag = Container(doCreateItemEx(k, 1))
            addContainerItems(newBag, v)
            container:addItemEx(newBag)
        else
            container:addItem(v[1], v[2])
        end
    end
end

function MonsterType.createLootItem(self, lootBlock, chance)
    local lootTable, itemCount = {}, 0
    local randvalue = math.random(0, 100000) / (getConfigInfo("rateLoot") * chance)
    if randvalue < lootBlock.chance then
        if (ItemType(lootBlock.itemId):isStackable()) then
            itemCount = randvalue % lootBlock.maxCount + 1
        else
            itemCount = 1
        end
    end

    while itemCount > 0 do
        local n = math.min(itemCount, 100)
        itemCount = itemCount - n
        table.insert(lootTable, {lootBlock.itemId, n})
    end

    return lootTable
end

function MonsterType.getBossReward(self, chance)
    local result = {}
    if getConfigInfo("rateLoot") > 0 then
        for _, loot in pairs(self:getLoot()) do
            local itemList = self:createLootItem(loot, chance)
            if itemList then
                for _, item in ipairs(itemList) do
                    table.insert(result, item)
                end
            end
        end
    end
    return result
end

function getDecayTime(id)
    local decayTime = 0
    do
        local o = io.open('data/items/items.xml','r')
        file = o:read('*a')
        o:close()
    end
    local function sumDecayTime(corpse)
        for attr in file:gmatch('<item.-id="' .. corpse ..'"(.-)</item>') do
            local decayTo = attr:match('<attribute.-key="decayTo".-value="(.-)".-/>')
            local duration = attr:match('<attribute.-key="duration".-value="(.-)".-/>')
            decayTime = decayTime + duration
            if tonumber(decayTo) > 0 then
                sumDecayTime(decayTo)
            end
            break
        end
    end
    sumDecayTime(id)
    return decayTime
end

function loadCorpses()
    for _, name in ipairs(REWARD_CHEST.BOSSES) do
        if MonsterType(name) ~= nil then
            REWARD_CHEST.DECAY[name] = getDecayTime(MonsterType(name):getCorpseId())
        end
    end
end
addEvent(loadCorpses, 0)

function getPlayerByGUID(guid)
    for _, player in ipairs(Game.getPlayers()) do
        if guid == player:getGuid() then
            return player
        end
    end
    return nil
end

function Player.addReward(self, reward, time, id)
    local LootBag = Container(doCreateItemEx(REWARD_CHEST.CONTAINER, 1))
    LootBag:setAttribute('text', time)
    addContainerItems(LootBag, reward)
    if id then
        db.query('DELETE FROM player_rewardchest WHERE id = ' .. id .. ';')
    end
    return self:getDepotChest(REWARD_CHEST.DEPOT_ID, true):addItemEx(LootBag)
end

function doSaveReward(uid, name)
    for GUID, items in pairs(REWARD_CHEST.LOOT[uid]) do
        local player = getPlayerByGUID(GUID)
        if player ~= nil then
            player:addReward(items, os.time())
            player:sendTextMessage(MESSAGE_INFO_DESCR, 'Your reward container from ' .. name .. ' was moved to your reward chest.')
        else
            db.query('INSERT INTO player_rewardchest VALUES (NULL, ' .. GUID ..', "' .. table.serialize(items) ..'", ' .. os.time() ..');')
        end
    end
    REWARD_CHEST.LOOT[uid] = nil
end

function Player.updateRewardChest(self)
    db.query('DELETE FROM player_rewardchest WHERE TIME_TO_SEC(TIMEDIFF(NOW(), FROM_UNIXTIME(date))) >= '.. REWARD_CHEST.EXPIRE ..';')
    local Query = db.storeQuery('SELECT id, reward, date FROM player_rewardchest WHERE player_id = '.. self:getGuid() ..';')
    if Query ~= false then
        repeat
            local rewardBag = table.unserialize(result.getDataString(Query, 'reward'))
            self:addReward(rewardBag, result.getDataInt(Query, 'date'), result.getDataInt(Query, 'id'))
        until not result.next(Query)
        result.free(Query)
    end
    local depotChest = self:getDepotChest(REWARD_CHEST.DEPOT_ID, true)
    for index = (depotChest:getSize() - 1), 0, -1 do
       local container = depotChest:getItem(index)
       if (container:getAttribute('text') ~= nil) and (tonumber(container:getAttribute('text')) + REWARD_CHEST.EXPIRE < os.time()) then
          container:remove()
       end
    end
    return self:setExhaustion(REWARD_CHEST.STORAGE, REWARD_CHEST.EXHAUST)
end

function string.diff(self)
    local format = {
        {'day', self / 60 / 60 / 24},
        {'hour', self / 60 / 60 % 24},
        {'minute', self / 60 % 60},
        {'second', self % 60}
    }

    local out = {}
    for k, t in ipairs(format) do
        local v = math.floor(t[2])
        if(v > 0) then
            table.insert(out, (k < #format and (#out > 0 and ', ' or '') or ' and ') .. v .. ' ' .. t[1] .. (v ~= 1 and 's' or ''))
        end
    end
    local ret = table.concat(out)
    if ret:len() < 16 and ret:find('second') then
        local a, b = ret:find(' and ')
        ret = ret:sub(b+1)
    end
    return ret
end

function doBossReward(monster, corpse)
    REWARD_CHEST.LOOT[corpse:getUniqueId()] = {}
    corpse:setAttribute('aid', 21584)
    corpse:setAttribute('text', corpse:getUniqueId())
    for killer, damage in pairs(monster:getDamageMap()) do
        local player, str = Player(killer), 'Loot of ' .. MonsterType(monster:getName()):getNameDescription() .. ': '
        if player ~= nil then
            local rewardBag = doCreateItemEx(REWARD_CHEST.CONTAINER)
            if player:getStamina() > 840 then
                local loot = MonsterType(monster:getName()):getBossReward(damage.total/monster:getMaxHealth())
                if #loot > 0 then
                    addContainerItems(Container(rewardBag), loot)
                    REWARD_CHEST.LOOT[corpse:getUniqueId()][player:getGuid()] = loot
                    str = str .. Container(rewardBag):getContentDescription()
                else
                    str = str .. 'nothing'
                end
            else
                str = str .. 'nothing (due to low stamina)'
            end
            player:sendTextMessage(MESSAGE_INFO_DESCR, str .. '.')
        end
    end
    addEvent(doSaveReward, REWARD_CHEST.DECAY[monster:getName()]*1000, corpse:getUniqueId(), MonsterType(monster:getName()):getNameDescription())
end

function onKill(creature, target)
    if (Monster(target) ~= nil) and isInArray(REWARD_CHEST.BOSSES, target:getName()) then
        local corpse = Item(doCreateItem(MonsterType(target:getName()):getCorpseId(), 1, target:getPosition()))
        corpse:decay()
        target:setDropLoot(false)
        doBossReward(target, corpse)
    end
end

Adicione @ data/items/items.xml

<item id="21518" article="a" name="reward container">
    <attribute key="weight" value="1800" />
    <attribute key="containersize" value="24" />
    <attribute key="slotType" value="backpack" />
</item>
<item id="21584" article="a" name="reward chest">
    <attribute key="type" value="depot" />
    <attribute key="containerSize" value="1" />
    <attribute key="description" value="This chest contains your rewards earned in battles." />
</item>

Adicione @ data/lib/core/player.lua

function Player.setExhaustion(self, value, time)
    return self:setStorageValue(value, time + os.time())
end

function Player.getExhaustion(self, value)
    local storage = self:getStorageValue(value)
    if storage <= 0 then
        return 0
    end
    return storage - os.time()
end
Créditos
@Cbrm
@Dalkon
@gugahoa
@Colandus
@Cykotitan
@Printer

 

Link para o comentário
Compartilhar em outros sites

  • 2 weeks later...

Oba muda ai pra tfs 1.0 que to esperando absolute, creaturescripts e a action.

 

Quando mata o boss.

Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/reward_chest.lua:onKill
data/creaturescripts/scripts/reward_chest.lua:249: attempt to index local 'target' (a number value)
stack traceback:
[C]: in function '__index'
data/creaturescripts/scripts/reward_chest.lua:249: in function <data/creaturescripts/scripts/reward_chest.lua:248>
Editado por GlobalCores
Link para o comentário
Compartilhar em outros sites

 

Oba muda ai pra tfs 1.0 que to esperando absolute, creaturescripts e a action.

 

Quando mata o boss.

Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/reward_chest.lua:onKill
data/creaturescripts/scripts/reward_chest.lua:249: attempt to index local 'target' (a number value)
stack traceback:
[C]: in function '__index'
data/creaturescripts/scripts/reward_chest.lua:249: in function <data/creaturescripts/scripts/reward_chest.lua:248>

 

 

Você ja adicionou nas sources os codes?

Link para o comentário
Compartilhar em outros sites

Sim Absolute, já tenho os códigos dentro da source e já compilei ela, tive que fazer algumas mudanças pois deu uns erros na hora de compilar mais coisa boba porque ele esta pra tfs 1.2 e o que usei foi pra 1.0

Link para o comentário
Compartilhar em outros sites

Sim Absolute, já tenho os códigos dentro da source e já compilei ela, tive que fazer algumas mudanças pois deu uns erros na hora de compilar mais coisa boba porque ele esta pra tfs 1.2 e o que usei foi pra 1.0

 

Certo, poste os códigos aqui da source que ai irei ajeitar o script

Link para o comentário
Compartilhar em outros sites

src/const.h

Antes de...

ITEM_MARKET = 14405


Adicione:

ITEM_REWARD_CHEST = 21584,

REWARD_CHEST_DEPOT = 99,


src/depotchest.h

Abaixo de:

~DepotChest();


Adicione:

uint32_t getDepotId() const {

return depotId;

}


void setDepotId(uint32_t id) {

depotId = id;

}


Abaixo de:

uint32_t maxDepotItems;


Adicione:

uint32_t depotId;


src/depotchest.cpp

Abaixo de:

maxDepotItems = 1500;


Adicione:

depotId = 0;


Acima de:

return Container::__queryAdd(index, thing, count, flags, actor);


Adicione:

if (actor != nullptr && getDepotId() == REWARD_CHEST_DEPOT) {

return RET_NOTPOSSIBLE;

}


src/depotlocker.h

Acima de:

//cylinder implementations


Adicione:

void setMaxDepotItems(uint32_t maxitems) {

maxDepotItems = maxitems;

}


src/luascript.h

Acima de:

static int32_t luaContainerGetSize(lua_State* L);


Adicione:

static int32_t luaContainerGetContentDescription(lua_State* L);


src/luascript.cpp

Acima de:

registerMethod("Container", "getSize", LuaScriptInterface::luaContainerGetSize);


Adicione:

registerMethod("Container", "getContentDescription", LuaScriptInterface::luaContainerGetContentDescription);


Acima de:

int32_t LuaScriptInterface::luaContainerGetSize(lua_State* L)


Adicione:

int32_t LuaScriptInterface::luaContainerGetContentDescription(lua_State* L)

{

// container:getContentDescription()

Container* container = getUserdata<Container>(L, 1);

if (container) {

std::ostringstream ss;

ss << container->getContentDescription();

pushString(L, ss.str());

} else {

lua_pushnil(L);

}

return 1;

}


src/actions.cpp

Mude:

//depot container

if (DepotLocker* depot = container->getDepotLocker()) {

DepotLocker* myDepotLocker = player->getDepotLocker(depot->getDepotId());

myDepotLocker->setParent(depot->getParent()->getTile());

openContainer = myDepotLocker;

player->setLastDepotId(depot->getDepotId());

} else {

openContainer = container;

}


Para:

//reward chest and depot container

if (item->getID() == ITEM_REWARD_CHEST) {

DepotLocker* myRewardChest = player->getRewardChest();

myRewardChest->setParent(item->getTile());

openContainer = myRewardChest;

player->setLastDepotId(REWARD_CHEST_DEPOT);

} else if (DepotLocker* depot = container->getDepotLocker()) {

DepotLocker* myDepotLocker = player->getDepotLocker(depot->getDepotId());

myDepotLocker->setParent(depot->getParent()->getTile());

openContainer = myDepotLocker;

player->setLastDepotId(depot->getDepotId());

} else {

openContainer = container;

}


src/player.h

Abaixo de:

DepotLocker* getDepotLocker(uint32_t depotId);


Adicione:

DepotLocker* getRewardChest();


src/player.cpp

Abaixo de:

DepotChest* depotChest = new DepotChest(ITEM_DEPOT);


Adicione:

depotChest->setDepotId(depotId);


Acima de:

void Player::sendCancelMessage(ReturnValue message) const


Adicione:

DepotLocker* Player::getRewardChest()

{

auto it = depotLockerMap.find(REWARD_CHEST_DEPOT);

if (it != depotLockerMap.end()) {

inbox->setParent(it->second);

return it->second;

}


DepotLocker* rewardChest = new DepotLocker(ITEM_LOCKER1);

rewardChest->setDepotId(REWARD_CHEST_DEPOT);

rewardChest->setMaxLockerItems(1);

rewardChest->__internalAddThing(getDepotChest(REWARD_CHEST_DEPOT, true));

depotLockerMap[REWARD_CHEST_DEPOT] = rewardChest;

return rewardChest;

}


EM player.cpp, container.cpp, inbox.cpp

Mude:

if (!item->isPickupable()) {


Para:

if (item->getID() != 21518 && !item->isPickupable()) {


Eu fiz assim porque do jeito que tem ai eu compilei e deu errado então verifiquei algumas coisas e ta tudo ai tem algumas coisas iguais mais tem outras pouco diferente.

ISSO AQUI É PRA TFS 1.0, NÃO USO TFS 1.1 NEM 1.0

Editado por GlobalCores
Link para o comentário
Compartilhar em outros sites

Altera seu creature pra este pra nós testarmos:

REWARD_CHEST = {
    BOSSES = {"Bibby Bloodbath", "Chizzoron the Distorter", "Ferumbras",
            "Furyosa", "Gaz'haragoth", "Ghazbaran", "Hirintror",
            "Jaul", "Mad Mage", "Mawhawk", "Morgaroth", "Obujos",
            "Ocyakao", "Omrafir", "Orshabaal", "Raging Mage",
            "Tanjis", "The Mutated Pumpkin", "The Pale Count",
            "The Welter", "Tyrn", "White Pale", "Zulazza the Corruptor",
            "Zushuka"},
    LOOT = {},     
    DECAY = {},
    DEPOT_ID = 99,
    CONTAINER = 21518,
    EXPIRE = 7*24*60*60,     --days to erase stored rewards
    STORAGE = 18394,         --player storage for chest exhaustion
    EXHAUST = 5*60,         --time allowed to use again the chest
}

function table.find(t, value, sensitive)
    local sensitive = sensitive or true
    if(not sensitive and type(value) == 'string') then
        for i, v in pairs(t) do
            if(type(v) == 'string') then
                if(v:lower() == value:lower()) then
                    return i
                end
            end
        end
        return nil
    end
    for i, v in pairs(t) do
        if(v == value) then
            return i
        end
    end
    return nil
end

function table.serialize(x, recur)
    local t = type(x)
    recur = recur or {}
    if(t == nil) then
        return "nil"
    elseif(t == "string") then
        return string.format("%q", x)
    elseif(t == "number") then
        return tostring(x)
    elseif(t == "boolean") then
        return x and "true" or "false"
    elseif(getmetatable(x)) then
        error("Can not serialize a table that has a metatable associated with it.")
    elseif(t == "table") then
        if(table.find(recur, x)) then
            error("Can not serialize recursive tables.")
        end
        table.insert(recur, x)
        local s = "{"
        for k, v in pairs(x) do
            s = s .. "[" .. table.serialize(k, recur) .. "]" .. " = " .. table.serialize(v, recur) .. ", "
        end
        return s:sub(0, s:len() - 2) .. "}"
    end
    error("Can not serialize value of type '" .. t .. "'.")
end

function table.unserialize(str)
    return loadstring('return ' .. str)()
end

function addContainerItems(container, items)
    for k, v in pairs(items) do
        if ItemType(k):isContainer() then
            local newBag = Container(doCreateItemEx(k, 1))
            addContainerItems(newBag, v)
            container:addItemEx(newBag)
        else
            container:addItem(v[1], v[2])
        end
    end
end

function MonsterType.createLootItem(self, lootBlock, chance)
    local lootTable, itemCount = {}, 0
    local randvalue = math.random(0, 100000) / (getConfigInfo("rateLoot") * chance)
    if randvalue < lootBlock.chance then
        if (ItemType(lootBlock.itemId):isStackable()) then
            itemCount = randvalue % lootBlock.maxCount + 1
        else
            itemCount = 1
        end
    end

    while itemCount > 0 do
        local n = math.min(itemCount, 100)
        itemCount = itemCount - n
        table.insert(lootTable, {lootBlock.itemId, n})
    end

    return lootTable
end

function MonsterType.getBossReward(self, chance)
    local result = {}
    if getConfigInfo("rateLoot") > 0 then
        for _, loot in pairs(self:getLoot()) do
            local itemList = self:createLootItem(loot, chance)
            if itemList then
                for _, item in ipairs(itemList) do
                    table.insert(result, item)
                end
            end
        end
    end
    return result
end

function getDecayTime(id)
    local decayTime = 0
    do
        local o = io.open('data/items/items.xml','r')
        file = o:read('*a')
        o:close()
    end
    local function sumDecayTime(corpse)
        for attr in file:gmatch('<item.-id="' .. corpse ..'"(.-)</item>') do
            local decayTo = attr:match('<attribute.-key="decayTo".-value="(.-)".-/>')
            local duration = attr:match('<attribute.-key="duration".-value="(.-)".-/>')
            decayTime = decayTime + duration
            if tonumber(decayTo) > 0 then
                sumDecayTime(decayTo)
            end
            break
        end
    end
    sumDecayTime(id)
    return decayTime
end

function loadCorpses()
    for _, name in ipairs(REWARD_CHEST.BOSSES) do
        if MonsterType(name) ~= nil then
            REWARD_CHEST.DECAY[name] = getDecayTime(MonsterType(name):getCorpseId())
        end
    end
end
addEvent(loadCorpses, 0)

function getPlayerByGUID(guid)
    for _, player in ipairs(Game.getPlayers()) do
        if guid == player:getGuid() then
            return player
        end
    end
    return nil
end

function Player.addReward(self, reward, time, id)
    local LootBag = Container(doCreateItemEx(REWARD_CHEST.CONTAINER, 1))
    LootBag:setAttribute('text', time)
    addContainerItems(LootBag, reward)
    if id then
        db.query('DELETE FROM player_rewardchest WHERE id = ' .. id .. ';')
    end
    return self:getDepotChest(REWARD_CHEST.DEPOT_ID, true):addItemEx(LootBag)
end

function doSaveReward(uid, name)
    for GUID, items in pairs(REWARD_CHEST.LOOT[uid]) do
        local player = getPlayerByGUID(GUID)
        if player ~= nil then
            player:addReward(items, os.time())
            player:sendTextMessage(MESSAGE_INFO_DESCR, 'Your reward container from ' .. name .. ' was moved to your reward chest.')
        else
            db.query('INSERT INTO player_rewardchest VALUES (NULL, ' .. GUID ..', "' .. table.serialize(items) ..'", ' .. os.time() ..');')
        end
    end
    REWARD_CHEST.LOOT[uid] = nil
end

function Player.updateRewardChest(self)
    db.query('DELETE FROM player_rewardchest WHERE TIME_TO_SEC(TIMEDIFF(NOW(), FROM_UNIXTIME(date))) >= '.. REWARD_CHEST.EXPIRE ..';')
    local Query = db.storeQuery('SELECT id, reward, date FROM player_rewardchest WHERE player_id = '.. self:getGuid() ..';')
    if Query ~= false then
        repeat
            local rewardBag = table.unserialize(result.getDataString(Query, 'reward'))
            self:addReward(rewardBag, result.getDataInt(Query, 'date'), result.getDataInt(Query, 'id'))
        until not result.next(Query)
        result.free(Query)
    end
    local depotChest = self:getDepotChest(REWARD_CHEST.DEPOT_ID, true)
    for index = (depotChest:getSize() - 1), 0, -1 do
       local container = depotChest:getItem(index)
       if (container:getAttribute('text') ~= nil) and (tonumber(container:getAttribute('text')) + REWARD_CHEST.EXPIRE < os.time()) then
          container:remove()
       end
    end
    return self:setExhaustion(REWARD_CHEST.STORAGE, REWARD_CHEST.EXHAUST)
end

function string.diff(self)
    local format = {
        {'day', self / 60 / 60 / 24},
        {'hour', self / 60 / 60 % 24},
        {'minute', self / 60 % 60},
        {'second', self % 60}
    }

    local out = {}
    for k, t in ipairs(format) do
        local v = math.floor(t[2])
        if(v > 0) then
            table.insert(out, (k < #format and (#out > 0 and ', ' or '') or ' and ') .. v .. ' ' .. t[1] .. (v ~= 1 and 's' or ''))
        end
    end
    local ret = table.concat(out)
    if ret:len() < 16 and ret:find('second') then
        local a, b = ret:find(' and ')
        ret = ret:sub(b+1)
    end
    return ret
end

function doBossReward(monster, corpse)
    REWARD_CHEST.LOOT[corpse:getUniqueId()] = {}
    corpse:setAttribute('aid', 21584)
    corpse:setAttribute('text', corpse:getUniqueId())
    for killer, damage in pairs(monster:getDamageMap()) do
        local player, str = Player(killer), 'Loot of ' .. MonsterType(monster:getName()):getNameDescription() .. ': '
        if player ~= nil then
            local rewardBag = doCreateItemEx(REWARD_CHEST.CONTAINER)
            if player:getStamina() > 840 then
                local loot = MonsterType(monster:getName()):getBossReward(damage.total/monster:getMaxHealth())
                if #loot > 0 then
                    addContainerItems(Container(rewardBag), loot)
                    REWARD_CHEST.LOOT[corpse:getUniqueId()][player:getGuid()] = loot
                    str = str .. Container(rewardBag):getContentDescription()
                else
                    str = str .. 'nothing'
                end
            else
                str = str .. 'nothing (due to low stamina)'
            end
            player:sendTextMessage(MESSAGE_INFO_DESCR, str .. '.')
        end
    end
    addEvent(doSaveReward, REWARD_CHEST.DECAY[monster:getName()]*1000, corpse:getUniqueId(), MonsterType(monster:getName()):getNameDescription())
end

end
Link para o comentário
Compartilhar em outros sites

Mudei e matei o monstro depois disso o server caiu.

[Warning - Event::checkScript] Can not load script: scripts/reward_chest.lua
data/creaturescripts/scripts/reward_chest.lua:248: <eof> expected near 'end'
Editado por GlobalCores
Link para o comentário
Compartilhar em outros sites

×
×
  • Criar Novo...