Acabei implementando um sistema de skill stages em meu server, ele até funciona, porém a cada magia que um player utiliza, aparece o seguinte erro no console:
(Estou usando tfs 1.3x)
Players.lua:
-- Internal Use
STONE_SKIN_AMULET = 2197
GOLD_POUNCH = 26377
ITEM_STORE_INBOX = 26052
ITEM_PARCEL = 2595
CONTAINER_PESO = 450000
-- No move items with actionID 8000
NOT_MOVEABLE_ACTION = 8000
-- Players cannot throw items on teleports if set to true
local blockTeleportTrashing = true
local titles = {
{storageID = 14960, title = " Scout"},
{storageID = 14961, title = " Sentinel"},
{storageID = 14962, title = " Steward"},
{storageID = 14963, title = " Warden"},
{storageID = 14964, title = " Squire"},
{storageID = 14965, title = " Warrior"},
{storageID = 14966, title = " Keeper"},
{storageID = 14967, title = " Guardian"},
{storageID = 14968, title = " Sage"},
{storageID = 14969, title = " Tutor"},
{storageID = 14970, title = " Senior Tutor"},
{storageID = 14971, title = " King"},
}
local function getTitle(uid)
local player = Player(uid)
if not player then return false end
for i = #titles, 1, -1 do
if player:getStorageValue(titles[i].storageID) == 1 then
return titles[i].title
end
end
return false
end
function Player:onBrowseField(position)
return true
end
local function getHours(seconds)
return math.floor((seconds/60)/60)
end
local function getMinutes(seconds)
return math.floor(seconds/60)
end
local function getSeconds(seconds)
return seconds%60
end
local function getTime(seconds)
local hours, minutes = getHours(seconds), getMinutes(seconds)
if (minutes > 59) then
minutes = minutes-hours*60
end
if (minutes < 10) then
minutes = "0" ..minutes
end
return hours..":"..minutes.. "h"
end
local function getTimeinWords(secs)
local hours, minutes, seconds = getHours(secs), getMinutes(secs), getSeconds(secs)
if (minutes > 59) then
minutes = minutes-hours*60
end
local timeStr = ''
if hours > 0 then
timeStr = timeStr .. ' hours '
end
timeStr = timeStr .. minutes .. ' minutes and '.. seconds .. 'seconds.'
return timeStr
end
function Player:onLook(thing, position, distance)
local description = "You see "
if thing:isItem() then
if thing.actionid == 5640 then
description = description .. "a honeyflower patch."
elseif thing.actionid == 5641 then
description = description .. "a banana palm."
elseif thing.itemid >= ITEM_HEALTH_CASK_START and thing.itemid <= ITEM_HEALTH_CASK_END
or thing.itemid >= ITEM_MANA_CASK_START and thing.itemid <= ITEM_MANA_CASK_END
or thing.itemid >= ITEM_SPIRIT_CASK_START and thing.itemid <= ITEM_SPIRIT_CASK_END
or thing.itemid >= ITEM_KEG_START and thing.itemid <= ITEM_KEG_END then
description = description .. thing:getDescription(distance)
local charges = thing:getCharges()
if charges then
description = string.format("%s\nIt has %d refillings left.", description, charges)
end
else
description = description .. thing:getDescription(distance)
end
else
description = description .. thing:getDescription(distance)
if thing:isMonster() then
local master = thing:getMaster()
if master and table.contains({'thundergiant','grovebeast','emberwing','skullfrost'}, thing:getName():lower()) then
description = description..' (Master: ' .. master:getName() .. '). It will disappear in ' .. getTimeinWords(master:getStorageValue(Storage.PetSummon) - os.time())
end
end
end
if self:getGroup():getAccess() then
if thing:isItem() then
description = string.format("%s\nItem ID: %d", description, thing:getId())
local actionId = thing:getActionId()
if actionId ~= 0 then
description = string.format("%s, Action ID: %d", description, actionId)
end
local uniqueId = thing:getAttribute(ITEM_ATTRIBUTE_UNIQUEID)
if uniqueId > 0 and uniqueId < 65536 then
description = string.format("%s, Unique ID: %d", description, uniqueId)
end
local itemType = thing:getType()
local transformEquipId = itemType:getTransformEquipId()
local transformDeEquipId = itemType:getTransformDeEquipId()
if transformEquipId ~= 0 then
description = string.format("%s\nTransforms to: %d (onEquip)", description, transformEquipId)
elseif transformDeEquipId ~= 0 then
description = string.format("%s\nTransforms to: %d (onDeEquip)", description, transformDeEquipId)
end
local decayId = itemType:getDecayId()
if decayId ~= -1 then
description = string.format("%s\nDecays to: %d", description, decayId)
end
elseif thing:isCreature() then
local str = "%s\nHealth: %d / %d"
if thing:isPlayer() and thing:getMaxMana() > 0 then
str = string.format("%s, Mana: %d / %d", str, thing:getMana(), thing:getMaxMana())
end
description = string.format(str, description, thing:getHealth(), thing:getMaxHealth()) .. "."
end
local position = thing:getPosition()
description = string.format(
"%s\nPosition: %d, %d, %d",
description, position.x, position.y, position.z
)
if thing:isCreature() then
if thing:isPlayer() then
description = string.format("%s\nIP: %s.", description, Game.convertIpToString(thing:getIp()))
end
end
end
if thing:isCreature() then
if thing:isPlayer() then
local KD = (math.max(0, thing:getStorageValue(STORAGEVALUE_KILLS)) + math.max(0, thing:getStorageValue(STORAGEVALUE_ASSISTS))) / math.max(1, thing:getStorageValue(STORAGEVALUE_DEATHS))
description = string.format("%s\nKD: [%0.2f]", description, KD)
end
end
self:sendTextMessage(MESSAGE_INFO_DESCR, description)
end
function Player:onLookInBattleList(creature, distance)
local description = "You see " .. creature:getDescription(distance)
if creature:isMonster() then
local master = creature:getMaster()
if master and table.contains({'thundergiant','grovebeast','emberwing','skullfrost'}, creature:getName():lower()) then
description = description..' (Master: ' .. master:getName() .. '). It will disappear in ' .. getTimeinWords(master:getStorageValue(Storage.PetSummon) - os.time())
end
end
if self:getGroup():getAccess() then
local str = "%s\nHealth: %d / %d"
if creature:isPlayer() and creature:getMaxMana() > 0 then
str = string.format("%s, Mana: %d / %d", str, creature:getMana(), creature:getMaxMana())
end
description = string.format(str, description, creature:getHealth(), creature:getMaxHealth()) .. "."
local position = creature:getPosition()
description = string.format(
"%s\nPosition: %d, %d, %d",
description, position.x, position.y, position.z
)
if creature:isPlayer() then
description = string.format("%s\nIP: %s", description, Game.convertIpToString(creature:getIp()))
end
end
self:sendTextMessage(MESSAGE_INFO_DESCR, description)
end
function Player:onLookInTrade(partner, item, distance)
self:sendTextMessage(MESSAGE_INFO_DESCR, "You see " .. item:getDescription(distance))
end
function Player:onLookInShop(itemType, count)
return true
end
local config = {
maxItemsPerSeconds = 1,
exhaustTime = 2000,
}
if not pushDelay then
pushDelay = { }
end
local function antiPush(self, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
if toPosition.x == CONTAINER_POSITION then
return true
end
local tile = Tile(toPosition)
if not tile then
self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
return false
end
local cid = self:getId()
if not pushDelay[cid] then
pushDelay[cid] = {items = 0, time = 0}
end
pushDelay[cid].items = pushDelay[cid].items + 1
local currentTime = os.mtime()
if pushDelay[cid].time == 0 then
pushDelay[cid].time = currentTime
elseif pushDelay[cid].time == currentTime then
pushDelay[cid].items = pushDelay[cid].items + 1
elseif currentTime > pushDelay[cid].time then
pushDelay[cid].time = 0
pushDelay[cid].items = 0
end
if pushDelay[cid].items > config.maxItemsPerSeconds then
pushDelay[cid].time = currentTime + config.exhaustTime
end
if pushDelay[cid].time > currentTime then
self:sendCancelMessage("You can't move that item so fast.")
return false
end
return true
end
function Player:onMoveItem(item, count, fromPosition, toPosition, fromCylinder, toCylinder)
-- No move if item count > 20 items
local tile = Tile(toPosition)
if tile and tile:getItemCount() > 20 then
self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
return false
end
-- Loot Analyser apenas 11.x+
--[[if self:getClient().os == CLIENTOS_NEW_WINDOWS then
local t = Tile(fromCylinder:getPosition())
local corpse = t:getTopDownItem()
if corpse then
local itemType = corpse:getType()
if itemType:isCorpse() and toPosition.x == CONTAINER_POSITION then
self:sendLootStats(item)
end
end
end]]--
checkWallArito(item, toPosition)
-- No move parcel very heavy
if ItemType(item:getId()):isContainer() and item:getWeight() > CONTAINER_PESO then
self:sendCancelMessage('You cannot move containers with more than ' .. CONTAINER_PESO .. ' oz.')
return false
end
-- Cults of Tibia begin
local frompos = Position(33023, 31904, 14) -- Checagem
local topos = Position(33052, 31932, 15) -- Checagem
if self:getPosition():isInRange(frompos, topos) and item:getId() == 26397 then
local tileBoss = Tile(toPosition)
if tileBoss and tileBoss:getTopCreature() and tileBoss:getTopCreature():isMonster() then
if tileBoss:getTopCreature():getName():lower() == 'the remorseless corruptor' then
tileBoss:getTopCreature():addHealth(-17000)
item:remove(1)
if tileBoss:getTopCreature():getHealth() <= 300 then
tileBoss:getTopCreature():remove()
local monster = Game.createMonster('the corruptor of souls', toPosition)
monster:registerEvent('checkPiso')
if Game.getStorageValue('healthSoul') > 0 then
monster:addHealth(-(monster:getHealth() - Game.getStorageValue('healthSoul')))
end
Game.setStorageValue('checkPiso', os.time()+30)
end
elseif tileBoss:getTopCreature():getName():lower() == 'the corruptor of souls' then
Game.setStorageValue('checkPiso', os.time()+30)
item:remove(1)
end
end
end
-- Cults of Tibia end
--- LIONS ROCK START
if self:getStorageValue(lionrock.storages.playerCanDoTasks) - os.time() < 0 then
local p, i = lionrock.positions, lionrock.items
local checkPr = false
if item:getId() == 2147 and toPosition.x == 33069 and toPosition.y == 32298 and toPosition.z == 9 then
-- Ruby
self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You place the ruby on the small socket. A red flame begins to burn.")
checkPr = true
if lionrock.taskactive.ruby ~= true then
lionrock.taskactive.ruby = true
end
local item = Tile(Position(33069, 32298, 9))
if (item:getItemCountById(1488) > 0) then
local flameruby = Game.createItem(1488, 1, Position(33069, 32298, 9))
end
end
if item:getId() == 2146 and toPosition.x == 33069 and toPosition.y == 32302 and toPosition.z == 9 then
-- Sapphire
self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You place the sapphire on the small socket. A blue flame begins to burn.")
checkPr = true
if lionrock.taskactive.sapphire ~= true then
lionrock.taskactive.sapphire = true
end
local item = Tile(Position(33069, 32302, 9))
if (item:getItemCountById(8058) > 0) then
local flamesapphire = Game.createItem(8058, 1, Position(33069, 32302, 9))
end
end
if item:getId() == 2150 and toPosition.x == 33077 and toPosition.y == 32302 and toPosition.z == 9 then
-- Amethyst
self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You place the amethyst on the small socket. A violet flame begins to burn.")
checkPr = true
if lionrock.taskactive.amethyst ~= true then
lionrock.taskactive.amethyst = true
end
local item = Tile(Position(33077, 32302, 9))
if (item:getItemCountById(1500) > 0) then
local flameamethyst = Game.createItem(1500, 1, Position(33077, 32302, 9))
end
end
if item:getId() == 9970 and toPosition.x == 33077 and toPosition.y == 32298 and toPosition.z == 9 then
-- Topaz
self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You place the topaz on the small socket. A yellow flame begins to burn.")
checkPr = true
if lionrock.taskactive.topaz ~= true then
lionrock.taskactive.topaz = true
end
local item = Tile(Position(33077, 32298, 9))
if (item:getItemCountById(7473) > 0) then
local flametopaz = Game.createItem(7473, 1, Position(33077, 32298, 9))
end
end
if checkPr == true then
-- Adding the Fountain which gives present
if lionrock.taskactive.ruby == true and lionrock.taskactive.sapphire == true and lionrock.taskactive.amethyst == true and lionrock.taskactive.topaz == true then
local fountain = Game.createItem(6390, 1, Position(33073, 32300, 9))
fountain:setActionId(41357)
local stone = Tile(Position(33073, 32300, 9)):getItemById(3608)
if stone ~= nil then
stone:remove()
end
self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Something happens at the centre of the room ...");
end
-- Removing Item
item:remove(1)
end
end
---- LIONS ROCK END
-- SSA exhaust
local exhaust = { }
if toPosition.x == CONTAINER_POSITION and toPosition.y == CONST_SLOT_NECKLACE and item:getId() == STONE_SKIN_AMULET then
local pid = self:getId()
if exhaust[pid] then
self:sendCancelMessage(RETURNVALUE_YOUAREEXHAUSTED)
return false
else
exhaust[pid] = true
addEvent(function() exhaust[pid] = false end, 4000, pid)
return true
end
end
-- Store Inbox
local containerIdFrom = fromPosition.y - 64
local containerFrom = self:getContainerById(containerIdFrom)
if (containerFrom) then
if (containerFrom:getId() == ITEM_STORE_INBOX and toPosition.y >= 1 and toPosition.y <= 11 and toPosition.y ~= 3) then
self:sendCancelMessage(RETURNVALUE_CONTAINERNOTENOUGHROOM)
return false
end
end
local containerTo = self:getContainerById(toPosition.y-64)
if (containerTo) then
if (containerTo:getId() == ITEM_STORE_INBOX) then
self:sendCancelMessage(RETURNVALUE_CONTAINERNOTENOUGHROOM)
return false
end
-- Gold Pounch
if (containerTo:getId() == GOLD_POUNCH) then
if (not (item:getId() == ITEM_CRYSTAL_COIN or item:getId() == ITEM_PLATINUM_COIN or item:getId() == ITEM_GOLD_COIN)) then
self:sendCancelMessage("You can move only money to this container.")
return false
end
end
end
-- No move gold pounch
if item:getId() == GOLD_POUNCH then
self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
return false
end
-- No move items with actionID 8000
if item:getActionId() == NOT_MOVEABLE_ACTION then
self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
return false
end
-- Check two-handed weapons
if toPosition.x ~= CONTAINER_POSITION then
return true
end
if item:getTopParent() == self and bit.band(toPosition.y, 0x40) == 0 then
local itemType, moveItem = ItemType(item:getId())
if bit.band(itemType:getSlotPosition(), SLOTP_TWO_HAND) ~= 0 and toPosition.y == CONST_SLOT_LEFT then
moveItem = self:getSlotItem(CONST_SLOT_RIGHT)
elseif itemType:getWeaponType() == WEAPON_SHIELD and toPosition.y == CONST_SLOT_RIGHT then
moveItem = self:getSlotItem(CONST_SLOT_LEFT)
if moveItem and bit.band(ItemType(moveItem:getId()):getSlotPosition(), SLOTP_TWO_HAND) == 0 then
return true
end
end
if moveItem then
local parent = item:getParent()
if parent:getSize() == parent:getCapacity() then
self:sendTextMessage(MESSAGE_STATUS_SMALL, Game.getReturnMessage(RETURNVALUE_CONTAINERNOTENOUGHROOM))
return false
else
return moveItem:moveTo(parent)
end
end
end
-- Reward System
if toPosition.x == CONTAINER_POSITION then
local containerId = toPosition.y - 64
local container = self:getContainerById(containerId)
if not container then
return true
end
-- Do not let the player insert items into either the Reward Container or the Reward Chest
local itemId = container:getId()
if itemId == ITEM_REWARD_CONTAINER or itemId == ITEM_REWARD_CHEST then
self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
return false
end
-- The player also shouldn't be able to insert items into the boss corpse
local tile = Tile(container:getPosition())
for _, item in ipairs(tile:getItems() or { }) do
if item:getAttribute(ITEM_ATTRIBUTE_CORPSEOWNER) == 2^31 - 1 and item:getName() == container:getName() then
self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
return false
end
end
end
-- Do not let the player move the boss corpse.
if item:getAttribute(ITEM_ATTRIBUTE_CORPSEOWNER) == 2^31 - 1 then
self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
return false
end
-- Players cannot throw items on reward chest
local tile = Tile(toPosition)
if tile and tile:getItemById(ITEM_REWARD_CHEST) then
self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
self:getPosition():sendMagicEffect(CONST_ME_POFF)
return false
end
-- Players cannot throw items on teleports
if blockTeleportTrashing and toPosition.x ~= CONTAINER_POSITION then
local thing = Tile(toPosition):getItemByType(ITEM_TYPE_TELEPORT)
if thing then
self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
self:getPosition():sendMagicEffect(CONST_ME_POFF)
return false
end
end
if tile and tile:getItemById(370) then -- Trapdoor
self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
self:getPosition():sendMagicEffect(CONST_ME_POFF)
return false
end
if not antiPush(self, item, count, fromPosition, toPosition, fromCylinder, toCylinder) then
return false
end
return true
end
function Player:onMoveCreature(creature, fromPosition, toPosition)
return true
end
local function hasPendingReport(name, targetName, reportType)
local f = io.open(string.format("data/reports/players/%s-%s-%d.txt", name, targetName, reportType), "r")
if f then
io.close(f)
return true
else
return false
end
end
function Player:onReportRuleViolation(targetName, reportType, reportReason, comment, translation)
local name = self:getName()
if hasPendingReport(name, targetName, reportType) then
self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your report is being processed.")
return
end
local file = io.open(string.format("data/reports/players/%s-%s-%d.txt", name, targetName, reportType), "a")
if not file then
self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "There was an error when processing your report, please contact a gamemaster.")
return
end
io.output(file)
io.write("------------------------------\n")
io.write("Reported by: " .. name .. "\n")
io.write("Target: " .. targetName .. "\n")
io.write("Type: " .. reportType .. "\n")
io.write("Reason: " .. reportReason .. "\n")
io.write("Comment: " .. comment .. "\n")
if reportType ~= REPORT_TYPE_BOT then
io.write("Translation: " .. translation .. "\n")
end
io.write("------------------------------\n")
io.close(file)
self:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("Thank you for reporting %s. Your report will be processed by %s team as soon as possible.", targetName, configManager.getString(configKeys.SERVER_NAME)))
return
end
function Player:onReportBug(message, position, category)
local name = self:getName()
local file = io.open("data/reports/bugs/" .. name .. " report.txt", "a")
if not file then
self:sendTextMessage(MESSAGE_EVENT_DEFAULT, "There was an error when processing your report, please contact a gamemaster.")
return true
end
io.output(file)
io.write("------------------------------\n")
io.write("Name: " .. name)
if category == BUG_CATEGORY_MAP then
io.write(" [Map position: " .. position.x .. ", " .. position.y .. ", " .. position.z .. "]")
end
local playerPosition = self:getPosition()
io.write(" [Player Position: " .. playerPosition.x .. ", " .. playerPosition.y .. ", " .. playerPosition.z .. "]\n")
io.write("Comment: " .. message .. "\n")
io.close(file)
self:sendTextMessage(MESSAGE_EVENT_DEFAULT, "Your report has been sent to " .. configManager.getString(configKeys.SERVER_NAME) .. ".")
return true
end
function Player:onTurn(direction)
if self:getGroup():getAccess() and self:getDirection() == direction then
local nextPosition = self:getPosition()
nextPosition:getNextPosition(direction)
self:teleportTo(nextPosition, true)
end
return true
end
function Player:onTradeRequest(target, item)
getTrade = 1
return true
end
function Player:onTradeAccept(target, item, targetItem)
getTrade = 0
return true
end
local soulCondition = Condition(CONDITION_SOUL, CONDITIONID_DEFAULT)
soulCondition:setTicks(4 * 60 * 1000)
soulCondition:setParameter(CONDITION_PARAM_SOULGAIN, 1)
local function useStamina(player)
local staminaMinutes = player:getStamina()
if staminaMinutes == 0 then
return
end
local playerId = player:getId()
local currentTime = os.time()
local timePassed = currentTime - nextUseStaminaTime[playerId]
if timePassed <= 0 then
return
end
if timePassed > 60 then
if staminaMinutes > 2 then
staminaMinutes = staminaMinutes - 2
else
staminaMinutes = 0
end
nextUseStaminaTime[playerId] = currentTime + 120
else
staminaMinutes = staminaMinutes - 1
nextUseStaminaTime[playerId] = currentTime + 60
end
player:setStamina(staminaMinutes)
end
local function useStaminaXp(player)
local staminaMinutes = player:getExpBoostStamina() / 60
if staminaMinutes == 0 then
return
end
local playerId = player:getId()
local currentTime = os.time()
local timePassed = currentTime - nextUseXpStamina[playerId]
if timePassed <= 0 then
return
end
if timePassed > 60 then
if staminaMinutes > 2 then
staminaMinutes = staminaMinutes - 2
else
staminaMinutes = 0
end
nextUseXpStamina[playerId] = currentTime + 120
else
staminaMinutes = staminaMinutes - 1
nextUseXpStamina[playerId] = currentTime + 60
end
player:setExpBoostStamina(staminaMinutes * 60)
end
function Player:onGainExperience(source, exp, rawExp)
if not source or source:isPlayer() then
return exp
end
if CASTEXP[self:getName()] then
if CASTEXP[self:getName()] <= os.time() then
exp = (exp * CASTEXP_PERCENT) + exp
end
end
-- Soul regeneration
local vocation = self:getVocation()
if self:getSoul() < vocation:getMaxSoul() and exp >= self:getLevel() then
soulCondition:setParameter(CONDITION_PARAM_SOULTICKS, vocation:getSoulGainTicks() * 1000)
self:addCondition(soulCondition)
end
-- Apply experience stage multiplier
exp = exp * Game.getExperienceStage(self:getLevel())
if (self:getExpBoostStamina() <= 0 and self:getStoreXpBoost() > 0) then
self:setStoreXpBoost(0) -- reset xp boost to 0
end
-- More compact, after checking before (reset) it only of xp if you have
if (self:getStoreXpBoost() > 0) then
exp = exp + (exp * (self:getStoreXpBoost()/100)) -- Exp Boost
end
local party = self:getParty()
if (party) then
if (party:isSharedExperienceActive() and
party:isSharedExperienceEnabled()) then
local tableVocs = {}
local count = 0
local totalCount = 0
local leaderId = party:getLeader():getVocation():getId()
if (leaderId) then
tableVocs[leaderId] = 1
count = count + 1
totalCount = totalCount + 1
end
for i, v in pairs(party:getMembers()) do
local vocId = v:getVocation():getId()
if (tableVocs[vocId] == nil) then
tableVocs[vocId] = 1
count = count + 1
end
totalCount = totalCount + 1
end
if (totalCount <= 10 and
count >= 4) then
exp = exp * 2
end
end
end
-- Exp Boost Modifier
useStaminaXp(self)
-- Exp stats Redundante!
--local staminaMinutes = self:getStamina()
--local Boost = self:getExpBoostStamina()
--if staminaMinutes > 2400 and self:isPremium() and Boost > 0 then
-- self:setBaseXpGain(Game.getExperienceStage(self:getLevel())*2) -- 200 = 1.0x, 200 = 2.0x, ... premium account
--elseif staminaMinutes > 2400 and self:isPremium() and Boost <= 0 then
-- self:setBaseXpGain(Game.getExperienceStage(self:getLevel())*1.5) -- 150 = 1.0x, 150 = 1.5x, ... premium account
--elseif staminaMinutes <= 2400 and staminaMinutes > 840 and self:isPremium() and Boost > 0 then
-- self:setBaseXpGain(Game.getExperienceStage(self:getLevel())*1.5) -- 150 = 1.5x premium account
--elseif staminaMinutes > 840 and Boost > 0 then
-- self:setBaseXpGain(Game.getExperienceStage(self:getLevel())*1.5) -- 150 = 1.5x free account
--elseif staminaMinutes <= 840 and Boost > 0 then
-- self:setBaseXpGain(Game.getExperienceStage(self:getLevel())*1) -- 50 = 0.5x all players
--elseif staminaMinutes <= 840 then
-- self:setBaseXpGain(Game.getExperienceStage(self:getLevel())*0.5) -- 50 = 0.5x all players
--end
-- Extra xp to use client 12
if self:getClient().version >= 1200 then
exp = (exp * 0.25) + exp
end
-- Stamina modifier
if configManager.getBoolean(configKeys.STAMINA_SYSTEM) then
useStamina(self)
local staminaMinutes = self:getStamina()
if staminaMinutes > 2400 and self:isPremium() then
exp = exp * 2
elseif staminaMinutes <= 840 then
exp = exp * 1
end
end
return exp
end
function Player:onLoseExperience(exp)
return exp
end
SkillsTable = {
[0] = { --[[ SKILL_FIST ]]
stage = {
[{0, 30}] = 50,
[{31, 50}] = 35,
[{51, 70}] = 20,
[{71, 80}] = 15,
[{81, 90}] = 10,
[{91, 110}] = 5,
[{111, 300}] = 2
},
rate = configKeys.RATE_SKILL
},
[1] = { --[[ SKILL_CLUB ]]
stage = {
[{0, 30}] = 50,
[{31, 50}] = 35,
[{51, 70}] = 20,
[{71, 80}] = 15,
[{81, 90}] = 10,
[{91, 110}] = 5,
[{111, 300}] = 2
},
rate = configKeys.RATE_SKILL
},
[2] = { --[[ SKILL_SWORD ]]
stage = {
[{0, 30}] = 50,
[{31, 50}] = 35,
[{51, 70}] = 20,
[{71, 80}] = 15,
[{81, 90}] = 10,
[{91, 110}] = 5,
[{111, 300}] = 2
},
rate = configKeys.RATE_SKILL
},
[3] = { --[[ SKILL_AXE ]]
stage = {
[{0, 30}] = 50,
[{31, 50}] = 35,
[{51, 70}] = 20,
[{71, 80}] = 15,
[{81, 90}] = 10,
[{91, 110}] = 5,
[{111, 300}] = 2
},
rate = configKeys.RATE_SKILL
},
[4] = { --[[ SKILL_DISTANCE ]]
stage = {
[{0, 30}] = 50,
[{31, 50}] = 35,
[{51, 70}] = 20,
[{71, 80}] = 15,
[{81, 90}] = 10,
[{91, 110}] = 5,
[{111, 300}] = 2
},
rate = configKeys.RATE_SKILL
},
[5] = { --[[ SKILL_SHIELD ]]
stage = {
[{0, 30}] = 50,
[{31, 50}] = 30,
[{51, 70}] = 20,
[{71, 90}] = 10,
[{91, 110}] = 5,
[{111, 300}] = 2
},
rate = configKeys.RATE_SKILL
},
[6] = { --[[ SKILL_FISHING ]]
stage = {
[{0, 20}] = 40,
[{21, 40}] = 30,
[{41, 60}] = 20,
[{61, 80}] = 10,
[{81, 100}] = 5,
[{101, 300}] = 2
},
rate = configKeys.RATE_SKILL
},
[7] = { --[[ SKILL_MAGLEVEL ]]
stage = {
[{0, 25}] = 13,
[{26, 50}] = 10,
[{51, 70}] = 6,
[{71, 80}] = 5,
[{81, 90}] = 4,
[{91, 100}] = 3,
[{101, 300}] = 2
},
rate = configKeys.RATE_MAGIC
}
}
function getSkillsRate(level, skill)
local skillRange = SkillsTable[skill]
if next(skillRange.stage) then
for sLevel, multiplier in pairs(skillRange.stage) do
if level >= sLevel[1] and level <= sLevel[2] then
return multiplier
end
end
end
return 1
end
function Player:onGainSkillTries(skill, tries)
if APPLY_SKILL_MULTIPLIER == false then
return tries
end
local skills = SkillsTable[skill]
if next(skills) and skills.rate then
local rate = configManager.getNumber(skills.rate)
if rate > 0 then
return tries * rate
else
return tries * getSkillsRate(self:getEffectiveSkillLevel(skill), skill)
end
end
end
function Player:onRemoveCount(item)
-- Apenas cliente 11.x
if self:getClient().os == CLIENTOS_NEW_WINDOWS then
self:sendWaste(item:getId())
end
end
local breakableItems = {29087, 3798, 3799, 7539, 7538}
function Player:onUseItem(item, target)
local itemId = item:getId()
if (itemId == 2550) and (target:getId() == 1445) then
if (target:getActionId() == 32931) then
if (player:getStorageValue(SECRET_LIBRARY_FINAL_STORAGE) ~= 1) then return true end
self:teleportTo({x = 32515, y = 32537, z = 12})
self:getPosition():sendMagicEffect(CONST_ME_MORTAREA)
self:updateSecretLibraryQuestlog(SL_VELLED_HOARD, 1)
end
end
if isInArray({WEAPON_AXE, WEAPON_SWORD, WEAPON_CLUB}, ItemType(itemId):getWeaponType()) then
if isInArray(breakableItems, target:getId()) then
local bi_mr = math.random(1, 10)
if (bi_mr > 7) then
target:remove()
target:getPosition():sendMagicEffect(CONST_ME_POFF)
return false
else
target:getPosition():sendMagicEffect(CONST_ME_POFF)
return false
end
end
end
return true
end
function Player:onSendBestiaryMonsters(requestType, className)
if (requestType == 1) then
sendSearchedCreatures(self:getId(), requestType, className)
else
sendCreatures(self:getId(), requestType, className)
end
return true
end
function Player:onLoadCyclopedia()
sendRaces(self:getId())
Charms.sendCharmInfo(self:getId())
return true
end
function Player:onBestiaryMonsterInfo(monsterId)
sendMonsterData(self:getId(), monsterId)
return true
end
function Player:onCharmSlots(charmId, state, raceId)
Charms.charmSlots(self:getId(), charmId + 1, state, raceId)
return true
end
function Player:onSendBestiaryTracker(raceId, isEnabled)
if (isEnabled == true) then
BestiaryTracker[#BestiaryTracker + 1] = raceId
else
BestiaryTracker[#BestiaryTracker] = nil
end
Bestiary.sendBestiaryTracker(self:getId(), raceId)
return true
end