Client Upload Part 2

RD Core / Commit #5

Commit Client Upload Part 2

Alex Alex committed 19/10/2026 00:06 main Patch
1,244 files +271,215 -0
A RD_Client/modules/game_alert/alert.otmod +13-0 View file
@@ -0,0 +1,13 @@
1+Module
2+ name: game_alert
3+ description: Mensagens de alerta durante o gameplay
4+ author: Frenesy
5+ website: https://github.com/edubart/otclient
6+ sandboxed: true
7+ scripts: [ alert ]
8+
9+ autoload: true
10+ autoload-priority: 1000
11+
12+ @onLoad: init()
13+ @onUnload: terminate()
A RD_Client/modules/game_alert/alert.otui +44-0 View file
@@ -0,0 +1,44 @@
1+MainWindow
2+ id: alertWindow
3+ size: 220 60
4+ image-source: /images/custom/UI/loot_2
5+ draggable: false
6+ focusable: false
7+
8+ UIButton
9+ id: img
10+ size: 32 32
11+ image-source: /images/custom/Items/2002
12+ anchors.top: parent.top
13+ anchors.right: parent.right
14+ margin-right: 10
15+ margin-top: -22
16+
17+ UIButton
18+ id: star
19+ size: 31 10
20+ image-source: /images/custom/UI/star_0
21+ anchors.top: parent.top
22+ anchors.right: img.left
23+ margin-right: 15
24+ margin-top: -28
25+
26+ UIButton
27+ id: name
28+ size: 200 20
29+ text: Noobie Helmet
30+ text-align: right
31+ anchors.top: star.bottom
32+ anchors.right: img.left
33+ margin-right: 15
34+ margin-top: 3
35+
36+ UIButton
37+ id: qnt
38+ size: 200 20
39+ text: x1
40+ text-align: right
41+ anchors.top: name.bottom
42+ anchors.right: img.left
43+ margin-right: 15
44+ margin-top: -5
A RD_Client/modules/game_alert/chest.otui +227-0 View file
@@ -0,0 +1,227 @@
1+MainWindow
2+ id: chestWindow
3+ size: 250 380
4+ image-source: /images/custom/UI/back_menu
5+ draggable: false
6+ focusable: true
7+ @onEscape: closer()
8+
9+ UIButton
10+ id: Visor
11+ height: 50
12+ image-source: /images/custom/Time/timer_back
13+ anchors.top: parent.top
14+ anchors.left: parent.left
15+ anchors.right: parent.right
16+ margin-left: 05
17+ margin-right: 05
18+ margin-top: -10
19+
20+ Label
21+ id: Status
22+ font: newfont-16px-rounded
23+ size: 200 30
24+ phantom: true
25+ anchors.top: parent.top
26+ anchors.left: parent.left
27+ margin-top: 10
28+ margin-left: 38
29+
30+ Label
31+ id: Dig_1
32+ size: 15 30
33+ phantom: true
34+ anchors.top: parent.top
35+ anchors.left: parent.left
36+ margin-top: 10
37+ margin-left: 50
38+
39+ Label
40+ id: Dig_2
41+ size: 15 30
42+ phantom: true
43+ anchors.top: parent.top
44+ anchors.left: Dig_1.right
45+ margin-top: 10
46+ margin-left: 15
47+
48+ Label
49+ id: Dig_3
50+ size: 15 30
51+ phantom: true
52+ anchors.top: parent.top
53+ anchors.left: Dig_2.right
54+ margin-top: 10
55+ margin-left: 15
56+
57+ Label
58+ id: Dig_4
59+ size: 15 30
60+ phantom: true
61+ anchors.top: parent.top
62+ anchors.left: Dig_3.right
63+ margin-top: 10
64+ margin-left: 15
65+
66+ UIButton
67+ id: Number_1
68+ size: 64 72
69+ font: sans-bold-16px
70+ text: 1
71+ image-source: /images/custom/Task/Monster_3
72+ anchors.top: Visor.bottom
73+ anchors.left: parent.left
74+ margin-top: 20
75+ margin-left: 08
76+ opacity: 0.8
77+ $pressed:
78+ opacity: 0.6
79+ $hover !pressed:
80+ opacity: 1.0
81+
82+ UIButton
83+ id: Number_2
84+ size: 64 72
85+ font: sans-bold-16px
86+ text: 2
87+ image-source: /images/custom/Task/Monster_3
88+ anchors.top: Visor.bottom
89+ anchors.left: Number_1.right
90+ margin-top: 20
91+ margin-left: 05
92+ opacity: 0.8
93+ $pressed:
94+ opacity: 0.6
95+ $hover !pressed:
96+ opacity: 1.0
97+
98+ UIButton
99+ id: Number_3
100+ size: 64 72
101+ font: sans-bold-16px
102+ text: 3
103+ image-source: /images/custom/Task/Monster_3
104+ anchors.top: Visor.bottom
105+ anchors.left: Number_2.right
106+ margin-top: 20
107+ margin-left: 05
108+ opacity: 0.8
109+ $pressed:
110+ opacity: 0.6
111+ $hover !pressed:
112+ opacity: 1.0
113+
114+ UIButton
115+ id: Number_4
116+ size: 64 72
117+ font: sans-bold-16px
118+ text: 4
119+ image-source: /images/custom/Task/Monster_3
120+ anchors.top: Number_1.bottom
121+ anchors.left: parent.left
122+ margin-top: 05
123+ margin-left: 08
124+ opacity: 0.8
125+ $pressed:
126+ opacity: 0.6
127+ $hover !pressed:
128+ opacity: 1.0
129+
130+ UIButton
131+ id: Number_5
132+ size: 64 72
133+ font: sans-bold-16px
134+ text: 5
135+ image-source: /images/custom/Task/Monster_3
136+ anchors.top: Number_1.bottom
137+ anchors.left: Number_4.right
138+ margin-top: 05
139+ margin-left: 05
140+ opacity: 0.8
141+ $pressed:
142+ opacity: 0.6
143+ $hover !pressed:
144+ opacity: 1.0
145+
146+ UIButton
147+ id: Number_6
148+ size: 64 72
149+ font: sans-bold-16px
150+ text: 6
151+ image-source: /images/custom/Task/Monster_3
152+ anchors.top: Number_1.bottom
153+ anchors.left: Number_5.right
154+ margin-top: 05
155+ margin-left: 05
156+ opacity: 0.8
157+ $pressed:
158+ opacity: 0.6
159+ $hover !pressed:
160+ opacity: 1.0
161+
162+ UIButton
163+ id: Number_7
164+ size: 64 72
165+ font: sans-bold-16px
166+ text: 7
167+ image-source: /images/custom/Task/Monster_3
168+ anchors.top: Number_4.bottom
169+ anchors.left: parent.left
170+ margin-top: 05
171+ margin-left: 08
172+ opacity: 0.8
173+ $pressed:
174+ opacity: 0.6
175+ $hover !pressed:
176+ opacity: 1.0
177+
178+ UIButton
179+ id: Number_8
180+ size: 64 72
181+ font: sans-bold-16px
182+ text: 8
183+ image-source: /images/custom/Task/Monster_3
184+ anchors.top: Number_4.bottom
185+ anchors.left: Number_7.right
186+ margin-top: 05
187+ margin-left: 05
188+ opacity: 0.8
189+ $pressed:
190+ opacity: 0.6
191+ $hover !pressed:
192+ opacity: 1.0
193+
194+ UIButton
195+ id: Number_9
196+ size: 64 72
197+ font: sans-bold-16px
198+ text: 9
199+ image-source: /images/custom/Task/Monster_3
200+ anchors.top: Number_4.bottom
201+ anchors.left: Number_8.right
202+ margin-top: 05
203+ margin-left: 05
204+ opacity: 0.8
205+ $pressed:
206+ opacity: 0.6
207+ $hover !pressed:
208+ opacity: 1.0
209+
210+ UIButton
211+ id: exitPass
212+ height: 30
213+ font: sans-bold-16px
214+ !text: tr('Sair')
215+ image-source: /images/custom/UI/button_3
216+ anchors.bottom: parent.bottom
217+ anchors.left: parent.left
218+ anchors.right: parent.right
219+ margin-bottom: 03
220+ margin-left: 05
221+ margin-right: 05
222+ @onClick: closer()
223+ opacity: 0.8
224+ $pressed:
225+ opacity: 0.6
226+ $hover !pressed:
227+ opacity: 1.0
A RD_Client/modules/game_alert/placar.otui +54-0 View file
@@ -0,0 +1,54 @@
1+MainWindow
2+ id: placarWindow
3+ size: 300 38
4+ image-source: /images/custom/UI/placar
5+ phantom: true
6+ draggable: false
7+ focusable: false
8+
9+ UIButton
10+ id: timer
11+ text: 00:00
12+ size: 45 15
13+ anchors.top: parent.top
14+ anchors.left: parent.left
15+ margin-left: 110
16+ margin-top: -42
17+
18+ UIButton
19+ id: blueParty
20+ text: TIME BLUE
21+ size: 100 15
22+ anchors.top: parent.top
23+ anchors.left: parent.left
24+ margin-left: -05
25+ margin-top: -27
26+
27+ UIButton
28+ id: blueScore
29+ text: 0
30+ font: sans-bold-16px
31+ size: 30 20
32+ anchors.top: parent.top
33+ anchors.left: blueParty.right
34+ margin-left: 07
35+ margin-top: -27
36+
37+ UIButton
38+ id: redScore
39+ text: 0
40+ font: sans-bold-16px
41+ size: 30 20
42+ anchors.top: parent.top
43+ anchors.left: blueScore.right
44+ margin-left: 05
45+ margin-top: -27
46+
47+ UIButton
48+ id: redParty
49+ text: TIME RED
50+ size: 100 20
51+ anchors.top: parent.top
52+ anchors.left: redScore.right
53+ margin-left: 07
54+ margin-top: -29
A RD_Client/modules/game_alert/timer.otui +60-0 View file
@@ -0,0 +1,60 @@
1+MainWindow
2+ id: timeWindow
3+ size: 140 85
4+ image-source: /images/custom/UI/none
5+ draggable: false
6+ focusable: false
7+
8+ UIButton
9+ size: 137 50
10+ image-source: /images/custom/Time/timer_back
11+ anchors.top: parent.top
12+ anchors.left: parent.left
13+ margin-left: -15
14+ margin-top: -35
15+ rotation: 180
16+
17+ Button
18+ id: desistirDG
19+ size: 100 25
20+ !text: tr('Desistir')
21+ anchors.top: parent.top
22+ anchors.left: parent.left
23+ margin-top: 17
24+ @onClick: onDGDesistir()
25+
26+ UIButton
27+ id: Time1
28+ size: 15 30
29+ image-source: /images/custom/Time/0
30+ anchors.top: parent.top
31+ anchors.left: parent.left
32+ margin-left: 10
33+ margin-top: -27
34+
35+ UIButton
36+ id: Time2
37+ size: 15 30
38+ image-source: /images/custom/Time/0
39+ anchors.top: parent.top
40+ anchors.left: Time1.right
41+ margin-left: 03
42+ margin-top: -27
43+
44+ UIButton
45+ id: Time3
46+ size: 15 30
47+ image-source: /images/custom/Time/0
48+ anchors.top: parent.top
49+ anchors.left: Time2.right
50+ margin-left: 15
51+ margin-top: -27
52+
53+ UIButton
54+ id: Time4
55+ size: 15 30
56+ image-source: /images/custom/Time/0
57+ anchors.top: parent.top
58+ anchors.left: Time3.right
59+ margin-left: 03
60+ margin-top: -27
A RD_Client/modules/game_alert/tutor.otui +39-0 View file
@@ -0,0 +1,39 @@
1+MainWindow
2+ id: tutorWindow
3+ size: 223 320
4+ image-source: /images/custom/Tutor/tutor_window
5+ draggable: false
6+ focusable: false
7+ @onClick: closer()
8+
9+ UILabel
10+ id: title
11+ size: 195 21
12+ font: sans-bold-16px
13+ color: yellow
14+ text-align: center
15+ anchors.top: parent.top
16+ anchors.left: parent.left
17+ margin-left: -03
18+ margin-top: -27
19+ @onClick: closer()
20+
21+ UIButton
22+ id: imgDestaque
23+ size: 215 145
24+ anchors.top: parent.top
25+ anchors.left: parent.left
26+ margin-left: -12
27+ margin-top: 01
28+ @onClick: closer()
29+
30+ UILabel
31+ id: desc
32+ size: 205 120
33+ font: lucida-11px-rounded
34+ text-wrap: true
35+ anchors.top: imgDestaque.bottom
36+ anchors.left: parent.left
37+ margin-left: -07
38+ margin-top: 08
39+ @onClick: closer()
A RD_Client/modules/game_alert/war.otui +78-0 View file
@@ -0,0 +1,78 @@
1+MainWindow
2+ id: warWindow
3+ size: 190 120
4+ image-source: /images/custom/UI/back_menu
5+ draggable: false
6+ focusable: false
7+
8+ $mobile:
9+ size: 150 80
10+
11+ UIButton
12+ id: img
13+ size: 52 52
14+ image-source: /images/custom/UI/atk_mobile
15+ anchors.top: parent.top
16+ anchors.left: parent.left
17+ margin-top: -20
18+
19+ $mobile:
20+ visible: false
21+
22+ UIButton
23+ id: txt
24+ font: lucida-11px-rounded
25+ !text: tr('Participe da batalha de 30 vs 30.')
26+ text-wrap: true
27+ height: 35
28+ phantom: true
29+ anchors.top: parent.top
30+ anchors.left: img.right
31+ anchors.right: parent.right
32+ margin-top: -20
33+ margin-right: 05
34+ margin-left: 10
35+
36+ $mobile:
37+ text: Warzone
38+ height: 15
39+ anchors.left: parent.left
40+ margin-left: 05
41+
42+ ProgressBar
43+ id: playerProgress
44+ background-color: white
45+ opacity: 0.5
46+ size: 150 05
47+ phantom: false
48+ anchors.top: txt.bottom
49+ anchors.left: img.right
50+ anchors.right: parent.right
51+ margin-left: 10
52+ margin-right: 05
53+ margin-top: 05
54+
55+ $mobile:
56+ size: 150 05
57+ anchors.left: parent.left
58+ margin-left: 05
59+
60+ UIButton
61+ id: starButton
62+ !text: tr('Participar')
63+ height: 25
64+ image-source: /images/custom/UI/button_2
65+ anchors.bottom: parent.bottom
66+ anchors.left: parent.left
67+ anchors.right: parent.right
68+ margin-left: 05
69+ margin-right: 05
70+ opacity: 0.8
71+ @onClick: onParticipeWar()
72+ $pressed:
73+ opacity: 0.6
74+ $hover !pressed:
75+ opacity: 1.0
76+
77+ $mobile:
78+ height: 20
A RD_Client/modules/game_battle/battle.lua +462-0 View file
@@ -0,0 +1,462 @@
1+battleWindow = nil
2+battleButton = nil
3+battlePanel = nil
4+filterPanel = nil
5+toggleFilterButton = nil
6+
7+mouseWidget = nil
8+updateEvent = nil
9+
10+hoveredCreature = nil
11+newHoveredCreature = nil
12+prevCreature = nil
13+
14+battleButtons = {}
15+local ageNumber = 1
16+local ages = {}
17+
18+function init()
19+ g_ui.importStyle('battlebutton')
20+ battleButton = modules.client_topmenu.addRightGameToggleButton('battleButton', tr('Battle') .. ' (Ctrl+B)', '/images/topbuttons/battle', toggle, false, 2)
21+ --battleButton:setOn(true)
22+ battleWindow = g_ui.loadUI('battle', modules.game_interface.getRightPanel())
23+ --g_keyboard.bindKeyDown('Ctrl+B', toggle)
24+
25+ -- this disables scrollbar auto hiding
26+ local scrollbar = battleWindow:getChildById('miniwindowScrollBar')
27+ scrollbar:mergeStyle({ ['$!on'] = { }})
28+
29+ battlePanel = battleWindow:recursiveGetChildById('battlePanel')
30+
31+ filterPanel = battleWindow:recursiveGetChildById('filterPanel')
32+ toggleFilterButton = battleWindow:recursiveGetChildById('toggleFilterButton')
33+
34+ if isHidingFilters() then
35+ hideFilterPanel()
36+ end
37+
38+ local sortTypeBox = filterPanel.sortPanel.sortTypeBox
39+ local sortOrderBox = filterPanel.sortPanel.sortOrderBox
40+
41+ mouseWidget = g_ui.createWidget('UIButton')
42+ mouseWidget:setVisible(false)
43+ mouseWidget:setFocusable(false)
44+ mouseWidget.cancelNextRelease = false
45+
46+ battleWindow:setContentMinimumHeight(80)
47+
48+ sortTypeBox:addOption('Name', 'name')
49+ sortTypeBox:addOption('Distance', 'distance')
50+ sortTypeBox:addOption('Total age', 'age')
51+ sortTypeBox:addOption('Screen age', 'screenage')
52+ sortTypeBox:addOption('Health', 'health')
53+ sortTypeBox:setCurrentOptionByData(getSortType())
54+ sortTypeBox.onOptionChange = onChangeSortType
55+
56+ sortOrderBox:addOption('Asc.', 'asc')
57+ sortOrderBox:addOption('Desc.', 'desc')
58+ sortOrderBox:setCurrentOptionByData(getSortOrder())
59+ sortOrderBox.onOptionChange = onChangeSortOrder
60+
61+ battleWindow:setup()
62+
63+ for i=1,30 do
64+ local battleButton = g_ui.createWidget('BattleButton', battlePanel)
65+ battleButton:setup()
66+ battleButton:hide()
67+ battleButton.onHoverChange = onBattleButtonHoverChange
68+ battleButton.onMouseRelease = onBattleButtonMouseRelease
69+ table.insert(battleButtons, battleButton)
70+ end
71+
72+ updateBattleList()
73+
74+ connect(LocalPlayer, {
75+ onPositionChange = onPlayerPositionChange
76+ })
77+ connect(Creature, {
78+ onAppear = updateSquare,
79+ onDisappear = updateSquare
80+ })
81+ connect(g_game, {
82+ onAttackingCreatureChange = updateSquare,
83+ onFollowingCreatureChange = updateSquare
84+ })
85+end
86+
87+function terminate()
88+ if battleButton == nil then
89+ return
90+ end
91+
92+ battleButtons = {}
93+
94+ g_keyboard.unbindKeyDown('Ctrl+B')
95+ battleButton:destroy()
96+ battleWindow:destroy()
97+ mouseWidget:destroy()
98+
99+ disconnect(LocalPlayer, {
100+ onPositionChange = onPlayerPositionChange
101+ })
102+ disconnect(Creature, {
103+ onAppear = onCreatureAppear,
104+ onDisappear = onCreatureDisappear
105+ })
106+ disconnect(g_game, {
107+ onAttackingCreatureChange = updateSquare,
108+ onFollowingCreatureChange = updateSquare
109+ })
110+
111+ removeEvent(updateEvent)
112+end
113+
114+function Meclose()
115+ battleWindow:close()
116+end
117+function toggle()
118+ if battleButton:isOn() then
119+ battleWindow:close()
120+ battleButton:setOn(false)
121+ else
122+ battleWindow:open()
123+ battleButton:setOn(true)
124+ end
125+end
126+
127+function onMiniWindowClose()
128+ battleButton:setOn(false)
129+end
130+
131+function getSortType()
132+ local settings = g_settings.getNode('BattleList')
133+ if not settings then
134+ if g_app.isMobile() then
135+ return 'distance'
136+ else
137+ return 'distance'
138+ end
139+ end
140+ return settings['sortType']
141+end
142+
143+function setSortType(state)
144+ settings = {}
145+ settings['sortType'] = state
146+ g_settings.mergeNode('BattleList', settings)
147+
148+ checkCreatures()
149+end
150+
151+function getSortOrder()
152+ local settings = g_settings.getNode('BattleList')
153+ if not settings then
154+ return 'asc'
155+ end
156+ return settings['sortOrder']
157+end
158+
159+function setSortOrder(state)
160+ settings = {}
161+ settings['sortOrder'] = state
162+ g_settings.mergeNode('BattleList', settings)
163+
164+ checkCreatures()
165+end
166+
167+function isSortAsc()
168+ return getSortOrder() == 'asc'
169+end
170+
171+function isSortDesc()
172+ return getSortOrder() == 'desc'
173+end
174+
175+function isHidingFilters()
176+ local settings = g_settings.getNode('BattleList')
177+ if not settings then
178+ return false
179+ end
180+ return settings['hidingFilters']
181+end
182+
183+function setHidingFilters(state)
184+ settings = {}
185+ settings['hidingFilters'] = state
186+ g_settings.mergeNode('BattleList', settings)
187+end
188+
189+function hideFilterPanel()
190+ filterPanel.originalHeight = filterPanel:getHeight()
191+ filterPanel:setHeight(0)
192+ toggleFilterButton:getParent():setMarginTop(0)
193+ toggleFilterButton:setImageClip(torect("0 0 21 12"))
194+ setHidingFilters(true)
195+ filterPanel:setVisible(false)
196+end
197+
198+function showFilterPanel()
199+ toggleFilterButton:getParent():setMarginTop(5)
200+ filterPanel:setHeight(filterPanel.originalHeight)
201+ toggleFilterButton:setImageClip(torect("21 0 21 12"))
202+ setHidingFilters(false)
203+ filterPanel:setVisible(true)
204+end
205+
206+function toggleFilterPanel()
207+ if filterPanel:isVisible() then
208+ hideFilterPanel()
209+ else
210+ showFilterPanel()
211+ end
212+end
213+
214+function onChangeSortType(comboBox, option, value)
215+ setSortType(value:lower())
216+end
217+
218+function onChangeSortOrder(comboBox, option, value)
219+ -- Replace dot in option name
220+ setSortOrder(value:lower():gsub('[.]', ''))
221+end
222+
223+-- functions
224+function updateBattleList()
225+ removeEvent(updateEvent)
226+ updateEvent = scheduleEvent(updateBattleList, 100)
227+ checkCreatures()
228+end
229+
230+function checkCreatures()
231+ if not battlePanel or not g_game.isOnline() then
232+ return
233+ end
234+
235+ local player = g_game.getLocalPlayer()
236+ if not player then
237+ return
238+ end
239+
240+ local dimension = modules.game_interface.getMapPanel():getVisibleDimension()
241+ 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))
242+ local maxCreatures = battlePanel:getChildCount()
243+
244+ local creatures = {}
245+ local now = g_clock.millis()
246+ local resetAgePoint = now - 250
247+ for _, creature in ipairs(spectators) do
248+ if doCreatureFitFilters(creature) and #creatures < maxCreatures then
249+ if not creature.lastSeen or creature.lastSeen < resetAgePoint then
250+ creature.screenAge = now
251+ end
252+ creature.lastSeen = now
253+ if not ages[creature:getId()] then
254+ if ageNumber > 1000 then
255+ ageNumber = 1
256+ ages = {}
257+ end
258+ ages[creature:getId()] = ageNumber
259+ ageNumber = ageNumber + 1
260+ end
261+ table.insert(creatures, creature)
262+ end
263+ end
264+
265+ updateSquare()
266+ sortCreatures(creatures)
267+ battlePanel:getLayout():disableUpdates()
268+
269+ -- sorting
270+ local ascOrder = isSortAsc()
271+ for i=1,#creatures do
272+ local creature = creatures[i]
273+ if ascOrder then
274+ creature = creatures[#creatures - i + 1]
275+ end
276+ local battleButton = battleButtons[i]
277+ battleButton:creatureSetup(creature)
278+ battleButton:show()
279+ battleButton:setOn(true)
280+ end
281+
282+ if g_app.isMobile() and #creatures > 0 then
283+ onBattleButtonHoverChange(battleButtons[1], true)
284+ end
285+
286+ for i=#creatures + 1,maxCreatures do
287+ if battleButtons[i]:isHidden() then break end
288+ battleButtons[i]:hide()
289+ battleButton:setOn(false)
290+ end
291+
292+ battlePanel:getLayout():enableUpdates()
293+ battlePanel:getLayout():update()
294+end
295+
296+function doCreatureFitFilters(creature)
297+ if creature:isLocalPlayer() then
298+ return false
299+ end
300+ if creature:getHealthPercent() <= 0 then
301+ return false
302+ end
303+
304+ local pos = creature:getPosition()
305+ if not pos then return false end
306+
307+ local localPlayer = g_game.getLocalPlayer()
308+ if pos.z ~= localPlayer:getPosition().z or not creature:canBeSeen() then return false end
309+
310+ local hidePlayers = filterPanel.buttons.hidePlayers:isChecked()
311+ local hideNPCs = filterPanel.buttons.hideNPCs:isChecked()
312+ local hideMonsters = filterPanel.buttons.hideMonsters:isChecked()
313+ local hideSkulls = filterPanel.buttons.hideSkulls:isChecked()
314+ local hideParty = filterPanel.buttons.hideParty:isChecked()
315+
316+ if hidePlayers and creature:isPlayer() then
317+ return false
318+ elseif hideNPCs and creature:isNpc() then
319+ return false
320+ elseif hideMonsters and creature:isMonster() then
321+ return false
322+ elseif hideSkulls and creature:isPlayer() and creature:getSkull() == SkullNone then
323+ return false
324+ elseif hideParty and creature:getShield() > ShieldWhiteBlue then
325+ return false
326+ end
327+
328+ return true
329+end
330+
331+local function getDistanceBetween(p1, p2)
332+ return math.max(math.abs(p1.x - p2.x), math.abs(p1.y - p2.y))
333+end
334+
335+function sortCreatures(creatures)
336+ local player = g_game.getLocalPlayer()
337+
338+ if getSortType() == 'distance' then
339+ local playerPos = player:getPosition()
340+ table.sort(creatures, function(a, b)
341+ if getDistanceBetween(playerPos, a:getPosition()) == getDistanceBetween(playerPos, b:getPosition()) then
342+ return ages[a:getId()] > ages[b:getId()]
343+ end
344+ return getDistanceBetween(playerPos, a:getPosition()) > getDistanceBetween(playerPos, b:getPosition())
345+ end)
346+ elseif getSortType() == 'health' then
347+ table.sort(creatures, function(a, b)
348+ if a:getHealthPercent() == b:getHealthPercent() then
349+ return ages[a:getId()] > ages[b:getId()]
350+ end
351+ return a:getHealthPercent() > b:getHealthPercent()
352+ end)
353+ elseif getSortType() == 'age' then
354+ table.sort(creatures, function(a, b) return ages[a:getId()] > ages[b:getId()] end)
355+ elseif getSortType() == 'screenage' then
356+ table.sort(creatures, function(a, b) return a.screenAge > b.screenAge end)
357+ else -- name
358+ table.sort(creatures, function(a, b)
359+ if a:getName():lower() == b:getName():lower() then
360+ return ages[a:getId()] > ages[b:getId()]
361+ end
362+ return a:getName():lower() > b:getName():lower()
363+ end)
364+ end
365+end
366+
367+-- other functions
368+function onBattleButtonMouseRelease(self, mousePosition, mouseButton)
369+ if mouseWidget.cancelNextRelease then
370+ mouseWidget.cancelNextRelease = false
371+ return false
372+ end
373+ if not self.creature then
374+ return false
375+ end
376+ if ((g_mouse.isPressed(MouseLeftButton) and mouseButton == MouseRightButton)
377+ or (g_mouse.isPressed(MouseRightButton) and mouseButton == MouseLeftButton)) then
378+ mouseWidget.cancelNextRelease = true
379+ g_game.look(self.creature, true)
380+ return true
381+ elseif mouseButton == MouseLeftButton and g_keyboard.isShiftPressed() then
382+ g_game.look(self.creature, true)
383+ return true
384+ elseif mouseButton == MouseRightButton and not g_mouse.isPressed(MouseLeftButton) then
385+ modules.game_interface.createThingMenu(mousePosition, nil, nil, self.creature)
386+ return true
387+ elseif mouseButton == MouseLeftButton and not g_mouse.isPressed(MouseRightButton) then
388+ if self.isTarget then
389+ g_game.cancelAttack()
390+ else
391+ g_game.attack(self.creature)
392+ modules.game_walking.setPressKeyAction(05)
393+ end
394+ return true
395+ end
396+ return false
397+end
398+
399+function onBattleButtonHoverChange(battleButton, hovered)
400+ if not hovered then
401+ newHoveredCreature = nil
402+ else
403+ newHoveredCreature = battleButton.creature
404+ end
405+ if battleButton.isHovered ~= hovered then
406+ battleButton.isHovered = hovered
407+ battleButton:update()
408+ end
409+ updateSquare()
410+end
411+
412+function onPlayerPositionChange(creature, newPos, oldPos)
413+ addEvent(checkCreatures)
414+end
415+
416+local CreatureButtonColors = {
417+ onIdle = {notHovered = '#888888', hovered = '#FFFFFF' },
418+ onTargeted = {notHovered = '#FF0000', hovered = '#FF8888' },
419+ onFollowed = {notHovered = '#00FF00', hovered = '#88FF88' }
420+}
421+
422+function updateSquare()
423+ local following = g_game.getFollowingCreature()
424+ local attacking = g_game.getAttackingCreature()
425+
426+ if newHoveredCreature == nil then
427+ if hoveredCreature ~= nil then
428+ hoveredCreature:hideStaticSquare()
429+ hoveredCreature = nil
430+ end
431+ else
432+ if hoveredCreature ~= nil then
433+ hoveredCreature:hideStaticSquare()
434+ end
435+ hoveredCreature = newHoveredCreature
436+ hoveredCreature:showStaticSquare(CreatureButtonColors.onIdle.hovered)
437+ end
438+
439+ local color = CreatureButtonColors.onIdle
440+ local creature = nil
441+ if attacking then
442+ color = CreatureButtonColors.onTargeted
443+ creature = attacking
444+ elseif following then
445+ color = CreatureButtonColors.onFollowed
446+ creature = following
447+ end
448+
449+ if prevCreature ~= creature then
450+ if prevCreature ~= nil then
451+ prevCreature:hideStaticSquare()
452+ end
453+ prevCreature = creature
454+ end
455+
456+ if not creature then
457+ return
458+ end
459+
460+ color = creature == hoveredCreature and color.hovered or color.notHovered
461+ creature:showStaticSquare(color)
462+end
A RD_Client/modules/game_battle/battle.otmod +9-0 View file
@@ -0,0 +1,9 @@
1+Module
2+ name: game_battle
3+ description: Manage battle window (new)
4+ author: otclient@otclient.ovh
5+ website: otclient.ovh
6+ sandboxed: true
7+ scripts: [ battle ]
8+ @onLoad: init()
9+ @onUnload: terminate()
Top