Administrador Administrador 1434 Postado Junho 13, 2015 Administrador Share Postado Junho 13, 2015 Testado em TFS 1.2, 10.77/78 Baseado em: http://www.tibia.com/news/?subtopic=newsarchive&id=2486 http://portaltibia.com.br/teaser-3-recompensa-para-quem-precisa-de-recompensa/ 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, 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; } src/luascript.h Acima de: static int luaContainerGetSize(lua_State* L); Adicione static int luaContainerGetContentDescription(lua_State* L); 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; } 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 Antes de: DepotLocker* getDepotLocker(uint32_t depotId); Adicione: DepotLocker* getRewardChest(); 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; } On player.cpp, container.cpp, inbox.cpp Mude: if (!item->isPickupable()) { Para: if (item->getID() != 21518 && !item->isPickupable()) { 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 More sharing options...
Furabio 257 Postado Junho 13, 2015 Share Postado Junho 13, 2015 Certamente, um belíssimo sistema. Link para o comentário Compartilhar em outros sites More sharing options...
AdilsonHacker 98 Postado Junho 14, 2015 Share Postado Junho 14, 2015 Funciona em 8.6, usando TFS 0.4? Ótimo Códigos, parabéns. Reputado. Link para o comentário Compartilhar em outros sites More sharing options...
Administrador Administrador 1434 Postado Junho 14, 2015 Autor Administrador Share Postado Junho 14, 2015 Apenas tfs 1.2 Link para o comentário Compartilhar em outros sites More sharing options...
mkbrabsolute 134 Postado Junho 25, 2015 Share Postado Junho 25, 2015 Vou modificar os codes e funções pra funfar no 1.0, acabar posto aqui Link para o comentário Compartilhar em outros sites More sharing options...
AdilsonHacker 98 Postado Junho 25, 2015 Share Postado Junho 25, 2015 Absolute, se possível tenta para 0.4 também mano. Abçs Link para o comentário Compartilhar em outros sites More sharing options...
mkbrabsolute 134 Postado Junho 25, 2015 Share Postado Junho 25, 2015 Absolute, se possível tenta para 0.4 também mano. Abçs Pra revs anteriores da 1.0 é complicado brother, muda praticamente todas as funções lua e os meta-métodos da source. Link para o comentário Compartilhar em outros sites More sharing options...
GlobalCores 0 Postado Junho 25, 2015 Share Postado Junho 25, 2015 (editado) 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 Junho 25, 2015 por GlobalCores Link para o comentário Compartilhar em outros sites More sharing options...
mkbrabsolute 134 Postado Junho 25, 2015 Share Postado Junho 25, 2015 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 More sharing options...
GustavaoTibia 0 Postado Junho 25, 2015 Share Postado Junho 25, 2015 Absolute não consigo te enviar mensagem privada, tbm to esperando os códigos pra tfs 1.0 ja tenho a source compilada com os códigos Link para o comentário Compartilhar em outros sites More sharing options...
GlobalCores 0 Postado Junho 25, 2015 Share Postado Junho 25, 2015 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 More sharing options...
mkbrabsolute 134 Postado Junho 25, 2015 Share Postado Junho 25, 2015 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 More sharing options...
GlobalCores 0 Postado Junho 25, 2015 Share Postado Junho 25, 2015 (editado) 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 Junho 25, 2015 por GlobalCores Link para o comentário Compartilhar em outros sites More sharing options...
mkbrabsolute 134 Postado Junho 25, 2015 Share Postado Junho 25, 2015 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 More sharing options...
GlobalCores 0 Postado Junho 25, 2015 Share Postado Junho 25, 2015 (editado) 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 Junho 25, 2015 por GlobalCores Link para o comentário Compartilhar em outros sites More sharing options...
Posts Recomendados