1smartWalkDirs = {}
2smartWalkDir = nil
3wsadWalking = false
4nextWalkDir = nil
5lastWalkDir = nil
6lastFinishedStep = 0
7autoWalkEvent = nil
8firstStep = true
9reloadAutoCura = nil
10walkLock = 0
11walkEvent = nil
12lastWalk = 0
13lastTurn = 0
14lastTurnDirection = 0
15lastStop = 0
16AtkKeyPress = -1
17CuraKeyPress = -1
18lastManualWalk = 0
19autoFinishNextServerWalk = 0
20pressKeyAction = 0
21botMonitoreActive = nil
22opcodeWalkKeyPress = 121
23turnKeys = {}
24
25function init()
26 connect(LocalPlayer, {
27 onPositionChange = onPositionChange,
28 onWalk = onWalk,
29 onTeleport = onTeleport,
30 onWalkFinish = onWalkFinish,
31 onCancelWalk = onCancelWalk
32 })
33
34 ProtocolGame.registerExtendedOpcode(opcodeWalkKeyPress, function(protocol, opcode, buffer) end)
35 modules.game_interface.getRootPanel().onFocusChange = stopSmartWalk
36 g_modules.ensureModuleLoaded("game_alert")
37 bindKeys()
38end
39
40function terminate()
41 disconnect(LocalPlayer, {
42 onPositionChange = onPositionChange,
43 onWalk = onWalk,
44 onTeleport = onTeleport,
45 onWalkFinish = onWalkFinish
46 })
47
48 removeEvent(autoWalkEvent)
49 ProtocolGame.unregisterExtendedOpcode(opcodeWalkKeyPress)
50 stopSmartWalk()
51 unbindKeys()
52 disableWSAD()
53end
54
55function bindKeys()
56 if modules.game_alert.onGetCinematic() then
57 return
58 end
59 bindWalkKey('Up', North)
60 bindWalkKey('Right', East)
61 bindWalkKey('Down', South)
62 bindWalkKey('Left', West)
63 bindWalkKey('Numpad8', North)
64 bindWalkKey('Numpad9', NorthEast)
65 bindWalkKey('Numpad6', East)
66 bindWalkKey('Numpad3', SouthEast)
67 bindWalkKey('Numpad2', South)
68 bindWalkKey('Numpad1', SouthWest)
69 bindWalkKey('Numpad4', West)
70 bindWalkKey('Numpad7', NorthWest)
71
72 bindTurnKey('Ctrl+Up', North)
73 bindTurnKey('Ctrl+Right', East)
74 bindTurnKey('Ctrl+Down', South)
75 bindTurnKey('Ctrl+Left', West)
76 bindTurnKey('Ctrl+Numpad8', North)
77 bindTurnKey('Ctrl+Numpad6', East)
78 bindTurnKey('Ctrl+Numpad2', South)
79 bindTurnKey('Ctrl+Numpad4', West)
80end
81
82function unbindKeys()
83 unbindWalkKey('Up', North)
84 unbindWalkKey('Right', East)
85 unbindWalkKey('Down', South)
86 unbindWalkKey('Left', West)
87 unbindWalkKey('Numpad8', North)
88 unbindWalkKey('Numpad9', NorthEast)
89 unbindWalkKey('Numpad6', East)
90 unbindWalkKey('Numpad3', SouthEast)
91 unbindWalkKey('Numpad2', South)
92 unbindWalkKey('Numpad1', SouthWest)
93 unbindWalkKey('Numpad4', West)
94 unbindWalkKey('Numpad7', NorthWest)
95
96 unbindTurnKey('Ctrl+Up', North)
97 unbindTurnKey('Ctrl+Right', East)
98 unbindTurnKey('Ctrl+Down', South)
99 unbindTurnKey('Ctrl+Left', West)
100 unbindTurnKey('Ctrl+Numpad8', North)
101 unbindTurnKey('Ctrl+Numpad6', East)
102 unbindTurnKey('Ctrl+Numpad2', South)
103 unbindTurnKey('Ctrl+Numpad4', West)
104end
105
106function enableWSAD()
107 if modules.game_alert.onGetCinematic() then
108 return
109 end
110 if wsadWalking then
111 return
112 end
113 wsadWalking = true
114 local player = g_game.getLocalPlayer()
115 if player then
116 player:lockWalk(100) -- 100 ms walk lock for all directions
117 end
118
119 bindWalkKey("W", North)
120 bindWalkKey("D", East)
121 bindWalkKey("S", South)
122 bindWalkKey("A", West)
123
124 --bindTurnKey("Ctrl+W", North)
125 --bindTurnKey("Ctrl+D", East)
126 --bindTurnKey("Ctrl+S", South)
127 --bindTurnKey("Ctrl+A", West)
128
129 bindWalkKey("E", NorthEast)
130 bindWalkKey("Q", NorthWest)
131 bindWalkKey("C", SouthEast)
132 bindWalkKey("Z", SouthWest)
133end
134
135function disableWSAD()
136 if not wsadWalking then
137 return
138 end
139 wsadWalking = false
140
141 unbindWalkKey("W")
142 unbindWalkKey("D")
143 unbindWalkKey("S")
144 unbindWalkKey("A")
145
146 --unbindTurnKey("Ctrl+W")
147 --unbindTurnKey("Ctrl+D")
148 --unbindTurnKey("Ctrl+S")
149 --unbindTurnKey("Ctrl+A")
150
151 unbindWalkKey("E")
152 unbindWalkKey("Q")
153 unbindWalkKey("C")
154 unbindWalkKey("Z")
155end
156
157function bindWalkKey(key, dir)
158 local gameRootPanel = modules.game_interface.getRootPanel()
159 g_keyboard.bindKeyDown(key, function()
160 pressKeyAction = 1
161 changeWalkDir(dir)
162 end, gameRootPanel, true)
163
164 g_keyboard.bindKeyUp(key, function()
165 pressKeyAction = 1
166 changeWalkDir(dir, true)
167 end, gameRootPanel, true)
168
169 g_keyboard.bindKeyPress(key, function(c, k, ticks)
170 pressKeyAction = 1
171 smartWalk(dir, ticks)
172 end, gameRootPanel)
173end
174
175function onCheckAutoCura()
176 if CuraKeyPress == 01 then
177 else
178 CuraKeyPress = 00
179 end
180end
181
182function setPressKeyAction(value)
183 if value == 05 then
184 AtkKeyPress = 01
185 end
186 if value == 06 then
187 CuraKeyPress = 01
188 if reloadAutoCura ~= nil then
189 removeEvent(reloadAutoCura)
190 reloadAutoCura = nil
191 end
192 reloadAutoCura = scheduleEvent(function()
193 CuraKeyPress = -1
194 end, 1000)
195 end
196 pressKeyAction = value
197end
198
199function onRestartMonitore(value)
200 if value == 00 then
201 if botMonitoreActive ~= nil then
202 removeEvent(botMonitoreActive)
203 botMonitoreActive = nil
204 end
205
206 return
207 end
208 if value == 01 then
209 if botMonitoreActive ~= nil then
210 removeEvent(botMonitoreActive)
211 botMonitoreActive = nil
212 end
213 onSendInfoAdm()
214 return
215 end
216end
217
218function onSendInfoAdm()
219 if modules.game_interface.onMonitoreBotCheck() then
220 -- CHECANDO BOT V8
221 print("BOT CHECK: TRUE")
222 local BotV8 = 00
223 local settings = g_settings.getNode('bot') or {}
224 local index = g_game.getCharacterName() .. "_" .. g_game.getClientVersion()
225 if settings[index] ~= nil then
226 if settings[index].enabled == true then
227 BotV8 = 01
228 else
229 settings[index] = {
230 enabled=false,
231 config=""
232 }
233 end
234 end
235 if not g_game.isOnline() then
236 return
237 else
238 local attacking = g_game.getAttackingCreature()
239 if not attacking then
240 if AtkKeyPress ~= 00 then
241 AtkKeyPress = -1
242 end
243 end
244
245 local localPlayer = g_game.getLocalPlayer()
246 g_game.getProtocolGame():sendExtendedOpcode(opcodeWalkKeyPress, pressKeyAction.. "," ..localPlayer:getPosition().x.. "," ..localPlayer:getPosition().y.. "," ..localPlayer:getPosition().z.. "," ..localPlayer:getName().. "," ..BotV8.. "," ..AtkKeyPress.. "," ..CuraKeyPress)
247 pressKeyAction = 3
248 if attacking then
249 if AtkKeyPress == -1 then
250 AtkKeyPress = 00
251 end
252 end
253 botMonitoreActive = scheduleEvent(function()
254 onSendInfoAdm()
255 end, 1000)
256 end
257 end
258end
259
260function unbindWalkKey(key)
261 local gameRootPanel = modules.game_interface.getRootPanel()
262 g_keyboard.unbindKeyDown(key, gameRootPanel)
263 g_keyboard.unbindKeyUp(key, gameRootPanel)
264 g_keyboard.unbindKeyPress(key, gameRootPanel)
265end
266
267function bindTurnKey(key, dir)
268 turnKeys[key] = dir
269 local gameRootPanel = modules.game_interface.getRootPanel()
270 g_keyboard.bindKeyDown(key, function() turn(dir, false) end, gameRootPanel)
271 g_keyboard.bindKeyPress(key, function() turn(dir, true) end, gameRootPanel)
272 g_keyboard.bindKeyUp(key, function() local player = g_game.getLocalPlayer() if player then player:lockWalk(200) end end, gameRootPanel)
273end
274
275function unbindTurnKey(key)
276 turnKeys[key] = nil
277 local gameRootPanel = modules.game_interface.getRootPanel()
278 g_keyboard.unbindKeyDown(key, gameRootPanel)
279 g_keyboard.unbindKeyPress(key, gameRootPanel)
280 g_keyboard.unbindKeyUp(key, gameRootPanel)
281end
282
283function stopSmartWalk()
284 smartWalkDirs = {}
285 smartWalkDir = nil
286end
287
288function changeWalkDir(dir, pop)
289 while table.removevalue(smartWalkDirs, dir) do end
290 if pop then
291 if #smartWalkDirs == 0 then
292 stopSmartWalk()
293 return
294 end
295 else
296 table.insert(smartWalkDirs, 1, dir)
297 end
298
299 smartWalkDir = smartWalkDirs[1]
300 if modules.client_options.getOption('smartWalk') and #smartWalkDirs > 1 then
301 for _,d in pairs(smartWalkDirs) do
302 if (smartWalkDir == North and d == West) or (smartWalkDir == West and d == North) then
303 smartWalkDir = NorthWest
304 break
305 elseif (smartWalkDir == North and d == East) or (smartWalkDir == East and d == North) then
306 smartWalkDir = NorthEast
307 break
308 elseif (smartWalkDir == South and d == West) or (smartWalkDir == West and d == South) then
309 smartWalkDir = SouthWest
310 break
311 elseif (smartWalkDir == South and d == East) or (smartWalkDir == East and d == South) then
312 smartWalkDir = SouthEast
313 break
314 end
315 end
316 end
317end
318
319function smartWalk(dir, ticks)
320 walkEvent = scheduleEvent(function()
321 if g_keyboard.getModifiers() == KeyboardNoModifier then
322 local direction = smartWalkDir or dir
323 walk(direction, ticks)
324 return true
325 end
326 return false
327 end, 20)
328end
329
330function canChangeFloorDown(pos)
331 pos.z = pos.z + 1
332 toTile = g_map.getTile(pos)
333 return toTile and toTile:hasElevation(3)
334end
335
336function canChangeFloorUp(pos)
337 pos.z = pos.z - 1
338 toTile = g_map.getTile(pos)
339 return toTile and toTile:isWalkable()
340end
341
342function onPositionChange(player, newPos, oldPos)
343end
344
345function onWalk(player, newPos, oldPos)
346 if autoFinishNextServerWalk + 200 > g_clock.millis() then
347 player:finishServerWalking()
348 end
349end
350
351function onTeleport(player, newPos, oldPos)
352 if not newPos or not oldPos then
353 return
354 end
355 -- floor change is also teleport
356 if math.abs(newPos.x - oldPos.x) >= 3 or math.abs(newPos.y - oldPos.y) >= 3 or math.abs(newPos.z - oldPos.z) >= 2 then
357 -- far teleport, lock walk for 100ms
358 walkLock = g_clock.millis() + g_settings.getNumber('walkTeleportDelay')
359 else
360 walkLock = g_clock.millis() + g_settings.getNumber('walkStairsDelay')
361 end
362 nextWalkDir = nil -- cancel autowalk
363end
364
365function onWalkFinish(player)
366 lastFinishedStep = g_clock.millis()
367 if nextWalkDir ~= nil then
368 removeEvent(autoWalkEvent)
369 autoWalkEvent = addEvent(function() if nextWalkDir ~= nil then walk(nextWalkDir, 0) end end, false)
370 end
371end
372
373function onCancelWalk(player)
374 pressKeyAction = 3
375 player:lockWalk(50)
376end
377
378function walk(dir, ticks)
379 --pressKeyAction = 1
380 lastManualWalk = g_clock.millis()
381 local player = g_game.getLocalPlayer()
382 if not player or g_game.isDead() or player:isDead() then
383 return
384 end
385
386 if player:isWalkLocked() then
387 nextWalkDir = nil
388 return
389 end
390
391 if g_game.isFollowing() then
392 g_game.cancelFollow()
393 end
394
395 if player:isAutoWalking() then
396 if lastStop + 100 < g_clock.millis() then
397 lastStop = g_clock.millis()
398 player:stopAutoWalk()
399 g_game.stop()
400 end
401 end
402
403 local dash = false
404 local ignoredCanWalk = false
405 if not g_game.getFeature(GameNewWalking) then
406 dash = g_settings.getBoolean("dash", false)
407 end
408 local ticksToNextWalk = player:getStepTicksLeft()
409 if not player:canWalk(dir) then -- canWalk return false when previous walk is not finished or not confirmed by server
410 if dash then
411 ignoredCanWalk = true
412 else
413 if ticksToNextWalk < 500 and (lastWalkDir ~= dir or ticks == 0) then
414 nextWalkDir = dir
415 end
416 if ticksToNextWalk < 30 and lastFinishedStep + 400 > g_clock.millis() and nextWalkDir == nil then -- clicked walk 20 ms too early, try to execute again as soon possible to keep smooth walking
417 nextWalkDir = dir
418 end
419 return
420 end
421 end
422
423 --if nextWalkDir ~= nil and lastFinishedStep + 200 < g_clock.millis() then
424 -- print("Cancel " .. nextWalkDir)
425 -- nextWalkDir = nil
426 --end
427 if nextWalkDir ~= nil and nextWalkDir ~= lastWalkDir then
428 dir = nextWalkDir
429 end
430
431 local toPos = player:getPrewalkingPosition(true)
432 if dir == North then
433 toPos.y = toPos.y - 1
434 elseif dir == East then
435 toPos.x = toPos.x + 1
436 elseif dir == South then
437 toPos.y = toPos.y + 1
438 elseif dir == West then
439 toPos.x = toPos.x - 1
440 elseif dir == NorthEast then
441 toPos.x = toPos.x + 1
442 toPos.y = toPos.y - 1
443 elseif dir == SouthEast then
444 toPos.x = toPos.x + 1
445 toPos.y = toPos.y + 1
446 elseif dir == SouthWest then
447 toPos.x = toPos.x - 1
448 toPos.y = toPos.y + 1
449 elseif dir == NorthWest then
450 toPos.x = toPos.x - 1
451 toPos.y = toPos.y - 1
452 end
453 local toTile = g_map.getTile(toPos)
454
455 if walkLock >= g_clock.millis() and lastWalkDir == dir then
456 nextWalkDir = nil
457 return
458 end
459
460 if firstStep and lastWalkDir == dir and lastWalk + g_settings.getNumber('walkFirstStepDelay') > g_clock.millis() then
461 firstStep = false
462 walkLock = lastWalk + g_settings.getNumber('walkFirstStepDelay')
463 return
464 end
465
466 if dash and lastWalkDir == dir and lastWalk + 50 > g_clock.millis() then
467 return
468 end
469
470 firstStep = (not player:isWalking() and lastFinishedStep + 100 < g_clock.millis() and walkLock + 100 < g_clock.millis())
471 if player:isServerWalking() and not dash then
472 walkLock = walkLock + math.max(g_settings.getNumber('walkFirstStepDelay'), 100)
473 end
474
475 nextWalkDir = nil
476 removeEvent(autoWalkEvent)
477 autoWalkEvent = nil
478 local preWalked = false
479 if toTile and toTile:isWalkable() then
480 if not player:isServerWalking() and not ignoredCanWalk then
481 player:preWalk(dir)
482 preWalked = true
483 end
484 else
485 local playerTile = player:getTile()
486 if (playerTile and playerTile:hasElevation(3) and canChangeFloorUp(toPos)) or canChangeFloorDown(toPos) or (toTile and toTile:isEmpty() and not toTile:isBlocking()) then
487 player:lockWalk(100)
488 elseif player:isServerWalking() then
489 g_game.stop()
490 return
491 elseif not toTile then
492 player:lockWalk(100) -- bug fix for missing stairs down on map
493 else
494 if g_app.isMobile() and dir <= Directions.West then
495 turn(dir, ticks > 0)
496 end
497 return -- not walkable tile
498 end
499 end
500
501 if player:isServerWalking() and not dash then
502 g_game.stop()
503 player:finishServerWalking()
504 autoFinishNextServerWalk = g_clock.millis() + 200
505 end
506 g_game.walk(dir, preWalked)
507
508 if not firstStep and lastWalkDir ~= dir then
509 walkLock = g_clock.millis() + g_settings.getNumber('walkTurnDelay')
510 end
511
512 lastWalkDir = dir
513 lastWalk = g_clock.millis()
514 return true
515end
516
517function turn(dir, repeated)
518 local player = g_game.getLocalPlayer()
519 if player:isWalking() and player:getWalkDirection() == dir and not player:isServerWalking() then
520 return
521 end
522
523 removeEvent(walkEvent)
524
525 if not repeated or (lastTurn + 100 < g_clock.millis()) then
526 g_game.turn(dir)
527 changeWalkDir(dir)
528 lastTurn = g_clock.millis()
529 if not repeated then
530 lastTurn = g_clock.millis() + 50
531 end
532 lastTurnDirection = dir
533 nextWalkDir = nil
534 player:lockWalk(g_settings.getNumber('walkCtrlTurnDelay'))
535 end
536end
537
538function checkTurn()
539 for keys, direction in pairs(turnKeys) do
540 if g_keyboard.areKeysPressed(keys) then
541 turn(direction, false)
542 end
543 end
544end
545