430 lines
13 KiB
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
|