mirror of
https://github.com/edubart/otclient.git
synced 2025-04-30 01:29:21 +02:00

1. Change colors on certain values, when stamina time was change. 2. Change tooltip on certain values, when stamina time was change. 3. Work with most protocols, including the most popular (8.54 - 10.98). 4. In protocols >= 1031 use information about premium account to show if player have premium stamina time.
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
|