tibia-client/modules/game_skills/skills.lua

430 lines
13 KiB
Lua

skillsWindow = nil
skillsButton = nil
function init()
connect(LocalPlayer, {
onExperienceChange = onExperienceChange,
onLevelChange = onLevelChange,
onHealthChange = onHealthChange,
onManaChange = onManaChange,
onSoulChange = onSoulChange,
onFreeCapacityChange = onFreeCapacityChange,
onTotalCapacityChange = onTotalCapacityChange,
onStaminaChange = onStaminaChange,
onOfflineTrainingChange = onOfflineTrainingChange,
onRegenerationChange = onRegenerationChange,
onSpeedChange = onSpeedChange,
onBaseSpeedChange = onBaseSpeedChange,
onMagicLevelChange = onMagicLevelChange,
onBaseMagicLevelChange = onBaseMagicLevelChange,
onSkillChange = onSkillChange,
onBaseSkillChange = onBaseSkillChange
})
connect(g_game, {
onGameStart = refresh,
onGameEnd = offline
})
skillsButton = modules.client_topmenu.addRightGameToggleButton('skillsButton', tr('Skills') .. ' (Ctrl+S)', '/images/topbuttons/skills', toggle)
skillsButton:setOn(true)
skillsWindow = g_ui.loadUI('skills', modules.game_interface.getRightPanel())
g_keyboard.bindKeyDown('Ctrl+S', toggle)
refresh()
skillsWindow:setup()
end
function terminate()
disconnect(LocalPlayer, {
onExperienceChange = onExperienceChange,
onLevelChange = onLevelChange,
onHealthChange = onHealthChange,
onManaChange = onManaChange,
onSoulChange = onSoulChange,
onFreeCapacityChange = onFreeCapacityChange,
onTotalCapacityChange = onTotalCapacityChange,
onStaminaChange = onStaminaChange,
onOfflineTrainingChange = onOfflineTrainingChange,
onRegenerationChange = onRegenerationChange,
onSpeedChange = onSpeedChange,
onBaseSpeedChange = onBaseSpeedChange,
onMagicLevelChange = onMagicLevelChange,
onBaseMagicLevelChange = onBaseMagicLevelChange,
onSkillChange = onSkillChange,
onBaseSkillChange = onBaseSkillChange
})
disconnect(g_game, {
onGameStart = refresh,
onGameEnd = offline
})
g_keyboard.unbindKeyDown('Ctrl+S')
skillsWindow:destroy()
skillsButton:destroy()
end
function expForLevel(level)
return math.floor((50*level*level*level)/3 - 100*level*level + (850*level)/3 - 200)
end
function expToAdvance(currentLevel, currentExp)
return expForLevel(currentLevel+1) - currentExp
end
function resetSkillColor(id)
local skill = skillsWindow:recursiveGetChildById(id)
local widget = skill:getChildById('value')
widget:setColor('#bbbbbb')
end
function toggleSkill(id, state)
local skill = skillsWindow:recursiveGetChildById(id)
skill:setVisible(state)
end
function setSkillBase(id, value, baseValue)
if baseValue <= 0 or value < 0 then
return
end
local skill = skillsWindow:recursiveGetChildById(id)
local widget = skill:getChildById('value')
if value > baseValue then
widget:setColor('#008b00') -- green
skill:setTooltip(baseValue .. ' +' .. (value - baseValue))
elseif value < baseValue then
widget:setColor('#b22222') -- red
skill:setTooltip(baseValue .. ' ' .. (value - baseValue))
else
widget:setColor('#bbbbbb') -- default
skill:removeTooltip()
end
end
function setSkillValue(id, value)
local skill = skillsWindow:recursiveGetChildById(id)
local widget = skill:getChildById('value')
widget:setText(value)
end
function setSkillColor(id, value)
local skill = skillsWindow:recursiveGetChildById(id)
local widget = skill:getChildById('value')
widget:setColor(value)
end
function setSkillTooltip(id, value)
local skill = skillsWindow:recursiveGetChildById(id)
local widget = skill:getChildById('value')
widget:setTooltip(value)
end
function setSkillPercent(id, percent, tooltip, color)
local skill = skillsWindow:recursiveGetChildById(id)
local widget = skill:getChildById('percent')
if widget then
widget:setPercent(math.floor(percent))
if tooltip then
widget:setTooltip(tooltip)
end
if color then
widget:setBackgroundColor(color)
end
end
end
function checkAlert(id, value, maxValue, threshold, greaterThan)
if greaterThan == nil then greaterThan = false end
local alert = false
-- maxValue can be set to false to check value and threshold
-- used for regeneration checking
if type(maxValue) == 'boolean' then
if maxValue then
return
end
if greaterThan then
if value > threshold then
alert = true
end
else
if value < threshold then
alert = true
end
end
elseif type(maxValue) == 'number' then
if maxValue < 0 then
return
end
local percent = math.floor((value / maxValue) * 100)
if greaterThan then
if percent > threshold then
alert = true
end
else
if percent < threshold then
alert = true
end
end
end
if alert then
setSkillColor(id, '#b22222') -- red
else
resetSkillColor(id)
end
end
function update()
local offlineTraining = skillsWindow:recursiveGetChildById('offlineTraining')
if not g_game.getFeature(GameOfflineTrainingTime) then
offlineTraining:hide()
else
offlineTraining:show()
end
local regenerationTime = skillsWindow:recursiveGetChildById('regenerationTime')
if not g_game.getFeature(GamePlayerRegenerationTime) then
regenerationTime:hide()
else
regenerationTime:show()
end
end
function refresh()
local player = g_game.getLocalPlayer()
if not player then return end
if expSpeedEvent then expSpeedEvent:cancel() end
expSpeedEvent = cycleEvent(checkExpSpeed, 30*1000)
onExperienceChange(player, player:getExperience())
onLevelChange(player, player:getLevel(), player:getLevelPercent())
onHealthChange(player, player:getHealth(), player:getMaxHealth())
onManaChange(player, player:getMana(), player:getMaxMana())
onSoulChange(player, player:getSoul())
onFreeCapacityChange(player, player:getFreeCapacity())
onStaminaChange(player, player:getStamina())
onMagicLevelChange(player, player:getMagicLevel(), player:getMagicLevelPercent())
onOfflineTrainingChange(player, player:getOfflineTrainingTime())
onRegenerationChange(player, player:getRegenerationTime())
onSpeedChange(player, player:getSpeed())
local hasAdditionalSkills = g_game.getFeature(GameAdditionalSkills)
for i = Skill.Fist, Skill.ManaLeechAmount do
onSkillChange(player, i, player:getSkillLevel(i), player:getSkillLevelPercent(i))
onBaseSkillChange(player, i, player:getSkillBaseLevel(i))
if i > Skill.Fishing then
toggleSkill('skillId'..i, hasAdditionalSkills)
end
end
update()
local contentsPanel = skillsWindow:getChildById('contentsPanel')
skillsWindow:setContentMinimumHeight(44)
if hasAdditionalSkills then
skillsWindow:setContentMaximumHeight(480)
else
skillsWindow:setContentMaximumHeight(390)
end
end
function offline()
if expSpeedEvent then expSpeedEvent:cancel() expSpeedEvent = nil end
end
function toggle()
if skillsButton:isOn() then
skillsWindow:close()
skillsButton:setOn(false)
else
skillsWindow:open()
skillsButton:setOn(true)
end
end
function checkExpSpeed()
local player = g_game.getLocalPlayer()
if not player then return end
local currentExp = player:getExperience()
local currentTime = g_clock.seconds()
if player.lastExps ~= nil then
player.expSpeed = (currentExp - player.lastExps[1][1])/(currentTime - player.lastExps[1][2])
onLevelChange(player, player:getLevel(), player:getLevelPercent())
else
player.lastExps = {}
end
table.insert(player.lastExps, {currentExp, currentTime})
if #player.lastExps > 30 then
table.remove(player.lastExps, 1)
end
end
function onMiniWindowClose()
skillsButton:setOn(false)
end
function onSkillButtonClick(button)
local percentBar = button:getChildById('percent')
if percentBar then
percentBar:setVisible(not percentBar:isVisible())
if percentBar:isVisible() then
button:setHeight(21)
else
button:setHeight(21 - 6)
end
end
end
function onExperienceChange(localPlayer, value)
setSkillValue('experience', value)
end
function onLevelChange(localPlayer, value, percent)
setSkillValue('level', value)
local text = tr('You have %s percent to go', 100 - percent) .. '\n' ..
tr('%s of experience left', expToAdvance(localPlayer:getLevel(), localPlayer:getExperience()))
if localPlayer.expSpeed ~= nil then
local expPerHour = math.floor(localPlayer.expSpeed * 3600)
if expPerHour > 0 then
local nextLevelExp = expForLevel(localPlayer:getLevel()+1)
local hoursLeft = (nextLevelExp - localPlayer:getExperience()) / expPerHour
local minutesLeft = math.floor((hoursLeft - math.floor(hoursLeft))*60)
hoursLeft = math.floor(hoursLeft)
text = text .. '\n' .. tr('%d of experience per hour', expPerHour)
text = text .. '\n' .. tr('Next level in %d hours and %d minutes', hoursLeft, minutesLeft)
end
end
setSkillPercent('level', percent, text)
end
function onHealthChange(localPlayer, health, maxHealth)
setSkillValue('health', health)
checkAlert('health', health, maxHealth, 30)
end
function onManaChange(localPlayer, mana, maxMana)
setSkillValue('mana', mana)
checkAlert('mana', mana, maxMana, 30)
end
function onSoulChange(localPlayer, soul)
setSkillValue('soul', soul)
end
function onFreeCapacityChange(localPlayer, freeCapacity)
setSkillValue('capacity', freeCapacity)
checkAlert('capacity', freeCapacity, localPlayer:getTotalCapacity(), 20)
end
function onTotalCapacityChange(localPlayer, totalCapacity)
checkAlert('capacity', localPlayer:getFreeCapacity(), totalCapacity, 20)
end
function onStaminaChange(localPlayer, stamina)
local hours = math.floor(stamina / 60)
local minutes = stamina % 60
if minutes < 10 then
minutes = '0' .. minutes
end
local percent = math.floor(100 * stamina / (42 * 60)) -- max is 42 hours --TODO not in all client versions
setSkillValue('stamina', hours .. ":" .. minutes)
--TODO not all client versions have premium time
if stamina > 2400 and g_game.getClientVersion() >= 1038 and localPlayer:isPremium() then
local text = tr("You have %s hours and %s minutes left", hours, minutes) .. '\n' ..
tr("Now you will gain 50%% more experience")
setSkillPercent('stamina', percent, text, 'green')
elseif stamina > 2400 and g_game.getClientVersion() >= 1038 and not localPlayer:isPremium() then
local text = tr("You have %s hours and %s minutes left", hours, minutes) .. '\n' ..
tr("You will not gain 50%% more experience because you aren't premium player, now you receive only 1x experience points")
setSkillPercent('stamina', percent, text, '#89F013')
elseif stamina > 2400 and g_game.getClientVersion() < 1038 then
local text = tr("You have %s hours and %s minutes left", hours, minutes) .. '\n' ..
tr("If you are premium player, you will gain 50%% more experience")
setSkillPercent('stamina', percent, text, 'green')
elseif stamina <= 2400 and stamina > 840 then
setSkillPercent('stamina', percent, tr("You have %s hours and %s minutes left", hours, minutes), 'orange')
elseif stamina <= 840 and stamina > 0 then
local text = tr("You have %s hours and %s minutes left", hours, minutes) .. "\n" ..
tr("You gain only 50%% experience and you don't may gain loot from monsters")
setSkillPercent('stamina', percent, text, 'red')
elseif stamina == 0 then
local text = tr("You have %s hours and %s minutes left", hours, minutes) .. "\n" ..
tr("You don't may receive experience and loot from monsters")
setSkillPercent('stamina', percent, text, 'black')
end
end
function onOfflineTrainingChange(localPlayer, offlineTrainingTime)
if not g_game.getFeature(GameOfflineTrainingTime) then
return
end
local hours = math.floor(offlineTrainingTime / 60)
local minutes = offlineTrainingTime % 60
if minutes < 10 then
minutes = '0' .. minutes
end
local percent = 100 * offlineTrainingTime / (12 * 60) -- max is 12 hours
setSkillValue('offlineTraining', hours .. ":" .. minutes)
setSkillPercent('offlineTraining', percent, tr('You have %s percent', percent))
end
function onRegenerationChange(localPlayer, regenerationTime)
if not g_game.getFeature(GamePlayerRegenerationTime) or regenerationTime < 0 then
return
end
local minutes = math.floor(regenerationTime / 60)
local seconds = regenerationTime % 60
if seconds < 10 then
seconds = '0' .. seconds
end
setSkillValue('regenerationTime', minutes .. ":" .. seconds)
checkAlert('regenerationTime', regenerationTime, false, 300)
end
function onSpeedChange(localPlayer, speed)
setSkillValue('speed', speed)
onBaseSpeedChange(localPlayer, localPlayer:getBaseSpeed())
end
function onBaseSpeedChange(localPlayer, baseSpeed)
setSkillBase('speed', localPlayer:getSpeed(), baseSpeed)
end
function onMagicLevelChange(localPlayer, magiclevel, percent)
setSkillValue('magiclevel', magiclevel)
setSkillPercent('magiclevel', percent, tr('You have %s percent to go', 100 - percent))
onBaseMagicLevelChange(localPlayer, localPlayer:getBaseMagicLevel())
end
function onBaseMagicLevelChange(localPlayer, baseMagicLevel)
setSkillBase('magiclevel', localPlayer:getMagicLevel(), baseMagicLevel)
end
function onSkillChange(localPlayer, id, level, percent)
setSkillValue('skillId' .. id, level)
setSkillPercent('skillId' .. id, percent, tr('You have %s percent to go', 100 - percent))
onBaseSkillChange(localPlayer, id, localPlayer:getSkillBaseLevel(id))
end
function onBaseSkillChange(localPlayer, id, baseLevel)
setSkillBase('skillId'..id, localPlayer:getSkillLevel(id), baseLevel)
end