444 lines
12 KiB
Lua

battleWindow = nil
battleButton = nil
battlePanel = nil
filterPanel = nil
toggleFilterButton = nil
mouseWidget = nil
updateEvent = nil
hoveredCreature = nil
newHoveredCreature = nil
prevCreature = nil
battleButtons = {}
local ageNumber = 1
function init()
g_ui.importStyle('battlebutton')
battleButton = modules.client_topmenu.addRightGameToggleButton('battleButton', tr('Battle') .. ' (Ctrl+B)', '/images/topbuttons/battle', toggle, false, 2)
battleButton:setOn(true)
battleWindow = g_ui.loadUI('battle', modules.game_interface.getRightPanel())
g_keyboard.bindKeyDown('Ctrl+B', toggle)
-- this disables scrollbar auto hiding
local scrollbar = battleWindow:getChildById('miniwindowScrollBar')
scrollbar:mergeStyle({ ['$!on'] = { }})
battlePanel = battleWindow:recursiveGetChildById('battlePanel')
filterPanel = battleWindow:recursiveGetChildById('filterPanel')
toggleFilterButton = battleWindow:recursiveGetChildById('toggleFilterButton')
if isHidingFilters() then
hideFilterPanel()
end
local sortTypeBox = filterPanel.sortPanel.sortTypeBox
local sortOrderBox = filterPanel.sortPanel.sortOrderBox
mouseWidget = g_ui.createWidget('UIButton')
mouseWidget:setVisible(false)
mouseWidget:setFocusable(false)
mouseWidget.cancelNextRelease = false
battleWindow:setContentMinimumHeight(80)
sortTypeBox:addOption('Name', 'name')
sortTypeBox:addOption('Distance', 'distance')
sortTypeBox:addOption('Age', 'age')
sortTypeBox:addOption('Health', 'health')
sortTypeBox:setCurrentOptionByData(getSortType())
sortTypeBox.onOptionChange = onChangeSortType
sortOrderBox:addOption('Asc.', 'asc')
sortOrderBox:addOption('Desc.', 'desc')
sortOrderBox:setCurrentOptionByData(getSortOrder())
sortOrderBox.onOptionChange = onChangeSortOrder
battleWindow:setup()
for i=1,30 do
local battleButton = g_ui.createWidget('BattleButton', battlePanel)
battleButton:setup()
battleButton:hide()
battleButton.onHoverChange = onBattleButtonHoverChange
battleButton.onMouseRelease = onBattleButtonMouseRelease
table.insert(battleButtons, battleButton)
end
updateBattleList()
connect(LocalPlayer, {
onPositionChange = onPlayerPositionChange
})
connect(Creature, {
onAppear = updateSquare,
onDisappear = updateSquare
})
connect(g_game, {
onAttackingCreatureChange = updateSquare,
onFollowingCreatureChange = updateSquare
})
end
function terminate()
if battleButton == nil then
return
end
battleButtons = {}
g_keyboard.unbindKeyDown('Ctrl+B')
battleButton:destroy()
battleWindow:destroy()
mouseWidget:destroy()
disconnect(LocalPlayer, {
onPositionChange = onPlayerPositionChange
})
disconnect(Creature, {
onAppear = onCreatureAppear,
onDisappear = onCreatureDisappear
})
disconnect(g_game, {
onAttackingCreatureChange = updateSquare,
onFollowingCreatureChange = updateSquare
})
removeEvent(updateEvent)
end
function toggle()
if battleButton:isOn() then
battleWindow:close()
battleButton:setOn(false)
else
battleWindow:open()
battleButton:setOn(true)
end
end
function onMiniWindowClose()
battleButton:setOn(false)
end
function getSortType()
local settings = g_settings.getNode('BattleList')
if not settings then
if g_app.isMobile() then
return 'distance'
else
return 'name'
end
end
return settings['sortType']
end
function setSortType(state)
settings = {}
settings['sortType'] = state
g_settings.mergeNode('BattleList', settings)
checkCreatures()
end
function getSortOrder()
local settings = g_settings.getNode('BattleList')
if not settings then
return 'asc'
end
return settings['sortOrder']
end
function setSortOrder(state)
settings = {}
settings['sortOrder'] = state
g_settings.mergeNode('BattleList', settings)
checkCreatures()
end
function isSortAsc()
return getSortOrder() == 'asc'
end
function isSortDesc()
return getSortOrder() == 'desc'
end
function isHidingFilters()
local settings = g_settings.getNode('BattleList')
if not settings then
return false
end
return settings['hidingFilters']
end
function setHidingFilters(state)
settings = {}
settings['hidingFilters'] = state
g_settings.mergeNode('BattleList', settings)
end
function hideFilterPanel()
filterPanel.originalHeight = filterPanel:getHeight()
filterPanel:setHeight(0)
toggleFilterButton:getParent():setMarginTop(0)
toggleFilterButton:setImageClip(torect("0 0 21 12"))
setHidingFilters(true)
filterPanel:setVisible(false)
end
function showFilterPanel()
toggleFilterButton:getParent():setMarginTop(5)
filterPanel:setHeight(filterPanel.originalHeight)
toggleFilterButton:setImageClip(torect("21 0 21 12"))
setHidingFilters(false)
filterPanel:setVisible(true)
end
function toggleFilterPanel()
if filterPanel:isVisible() then
hideFilterPanel()
else
showFilterPanel()
end
end
function onChangeSortType(comboBox, option)
setSortType(option:lower())
end
function onChangeSortOrder(comboBox, option)
-- Replace dot in option name
setSortOrder(option:lower():gsub('[.]', ''))
end
-- functions
function updateBattleList()
removeEvent(updateEvent)
updateEvent = scheduleEvent(updateBattleList, 100)
checkCreatures()
end
function checkCreatures()
if not battlePanel or not g_game.isOnline() then
return
end
local player = g_game.getLocalPlayer()
if not player then
return
end
local dimension = modules.game_interface.getMapPanel():getVisibleDimension()
local spectators = g_map.getSpectatorsInRangeEx(player:getPosition(), false, math.floor(dimension.width / 2), math.floor(dimension.width / 2), math.floor(dimension.height / 2), math.floor(dimension.height / 2))
local maxCreatures = battlePanel:getChildCount()
local creatures = {}
for _, creature in ipairs(spectators) do
if doCreatureFitFilters(creature) and #creatures < maxCreatures then
if not creature.age then
creature.age = ageNumber
ageNumber = ageNumber + 1
end
table.insert(creatures, creature)
end
end
updateSquare()
sortCreatures(creatures)
battlePanel:getLayout():disableUpdates()
-- sorting
local ascOrder = isSortAsc()
for i=1,#creatures do
local creature = creatures[i]
if ascOrder then
creature = creatures[#creatures - i + 1]
end
local battleButton = battleButtons[i]
battleButton:creatureSetup(creature)
battleButton:show()
battleButton:setOn(true)
end
if g_app.isMobile() and #creatures > 0 then
onBattleButtonHoverChange(battleButtons[1], true)
end
for i=#creatures + 1,maxCreatures do
if battleButtons[i]:isHidden() then break end
battleButtons[i]:hide()
battleButton:setOn(false)
end
battlePanel:getLayout():enableUpdates()
battlePanel:getLayout():update()
end
function doCreatureFitFilters(creature)
if creature:isLocalPlayer() then
return false
end
if creature:getHealthPercent() <= 0 then
return false
end
local pos = creature:getPosition()
if not pos then return false end
local localPlayer = g_game.getLocalPlayer()
if pos.z ~= localPlayer:getPosition().z or not creature:canBeSeen() then return false end
local hidePlayers = filterPanel.buttons.hidePlayers:isChecked()
local hideNPCs = filterPanel.buttons.hideNPCs:isChecked()
local hideMonsters = filterPanel.buttons.hideMonsters:isChecked()
local hideSkulls = filterPanel.buttons.hideSkulls:isChecked()
local hideParty = filterPanel.buttons.hideParty:isChecked()
if hidePlayers and creature:isPlayer() then
return false
elseif hideNPCs and creature:isNpc() then
return false
elseif hideMonsters and creature:isMonster() then
return false
elseif hideSkulls and creature:isPlayer() and creature:getSkull() == SkullNone then
return false
elseif hideParty and creature:getShield() > ShieldWhiteBlue then
return false
end
return true
end
local function getDistanceBetween(p1, p2)
return math.max(math.abs(p1.x - p2.x), math.abs(p1.y - p2.y))
end
function sortCreatures(creatures)
local player = g_game.getLocalPlayer()
if getSortType() == 'distance' then
local playerPos = player:getPosition()
table.sort(creatures, function(a, b)
if getDistanceBetween(playerPos, a:getPosition()) == getDistanceBetween(playerPos, b:getPosition()) then
return a.age > b.age
end
return getDistanceBetween(playerPos, a:getPosition()) > getDistanceBetween(playerPos, b:getPosition())
end)
elseif getSortType() == 'health' then
table.sort(creatures, function(a, b)
if a:getHealthPercent() == b:getHealthPercent() then
return a.age > b.age
end
return a:getHealthPercent() > b:getHealthPercent()
end)
elseif getSortType() == 'age' then
table.sort(creatures, function(a, b) return a.age > b.age end)
else -- name
table.sort(creatures, function(a, b)
if a:getName():lower() == b:getName():lower() then
return a.age > b.age
end
return a:getName():lower() > b:getName():lower()
end)
end
end
-- other functions
function onBattleButtonMouseRelease(self, mousePosition, mouseButton)
if mouseWidget.cancelNextRelease then
mouseWidget.cancelNextRelease = false
return false
end
if not self.creature then
return false
end
if ((g_mouse.isPressed(MouseLeftButton) and mouseButton == MouseRightButton)
or (g_mouse.isPressed(MouseRightButton) and mouseButton == MouseLeftButton)) then
mouseWidget.cancelNextRelease = true
g_game.look(self.creature, true)
return true
elseif mouseButton == MouseLeftButton and g_keyboard.isShiftPressed() then
g_game.look(self.creature, true)
return true
elseif mouseButton == MouseRightButton and not g_mouse.isPressed(MouseLeftButton) then
modules.game_interface.createThingMenu(mousePosition, nil, nil, self.creature)
return true
elseif mouseButton == MouseLeftButton and not g_mouse.isPressed(MouseRightButton) then
if self.isTarget then
g_game.cancelAttack()
else
g_game.attack(self.creature)
end
return true
end
return false
end
function onBattleButtonHoverChange(battleButton, hovered)
if not hovered then
newHoveredCreature = nil
else
newHoveredCreature = battleButton.creature
end
if battleButton.isHovered ~= hovered then
battleButton.isHovered = hovered
battleButton:update()
end
updateSquare()
end
function onPlayerPositionChange(creature, newPos, oldPos)
addEvent(checkCreatures)
end
local CreatureButtonColors = {
onIdle = {notHovered = '#888888', hovered = '#FFFFFF' },
onTargeted = {notHovered = '#FF0000', hovered = '#FF8888' },
onFollowed = {notHovered = '#00FF00', hovered = '#88FF88' }
}
function updateSquare()
local following = g_game.getFollowingCreature()
local attacking = g_game.getAttackingCreature()
if newHoveredCreature == nil then
if hoveredCreature ~= nil then
hoveredCreature:hideStaticSquare()
hoveredCreature = nil
end
else
if hoveredCreature ~= nil then
hoveredCreature:hideStaticSquare()
end
hoveredCreature = newHoveredCreature
hoveredCreature:showStaticSquare(CreatureButtonColors.onIdle.hovered)
end
local color = CreatureButtonColors.onIdle
local creature = nil
if attacking then
color = CreatureButtonColors.onTargeted
creature = attacking
elseif following then
color = CreatureButtonColors.onFollowed
creature = following
end
if prevCreature ~= creature then
if prevCreature ~= nil then
prevCreature:hideStaticSquare()
end
prevCreature = creature
end
if not creature then
return
end
color = creature == hoveredCreature and color.hovered or color.notHovered
creature:showStaticSquare(color)
end