mirror of
				https://github.com/ErikasKontenis/SabrehavenServer.git
				synced 2025-10-30 19:56:22 +01:00 
			
		
		
		
	commit client
This commit is contained in:
		
							
								
								
									
										431
									
								
								SabrehavenOTClient/modules/game_walking/walking.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										431
									
								
								SabrehavenOTClient/modules/game_walking/walking.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,431 @@ | ||||
| smartWalkDirs = {} | ||||
| smartWalkDir = nil | ||||
| wsadWalking = false | ||||
| nextWalkDir = nil | ||||
| lastWalkDir = nil | ||||
| lastFinishedStep = 0 | ||||
| autoWalkEvent = nil | ||||
| firstStep = true | ||||
| walkLock = 0 | ||||
| walkEvent = nil | ||||
| lastWalk = 0 | ||||
| lastTurn = 0 | ||||
| lastTurnDirection = 0 | ||||
| lastStop = 0 | ||||
| lastManualWalk = 0 | ||||
| autoFinishNextServerWalk = 0 | ||||
| turnKeys = {} | ||||
|  | ||||
| function init() | ||||
|   connect(LocalPlayer, { | ||||
|     onPositionChange = onPositionChange, | ||||
|     onWalk = onWalk, | ||||
|     onTeleport = onTeleport, | ||||
|     onWalkFinish = onWalkFinish, | ||||
|     onCancelWalk = onCancelWalk | ||||
|   }) | ||||
|  | ||||
|   modules.game_interface.getRootPanel().onFocusChange = stopSmartWalk | ||||
|   bindKeys() | ||||
| end | ||||
|  | ||||
| function terminate() | ||||
|   disconnect(LocalPlayer, { | ||||
|     onPositionChange = onPositionChange, | ||||
|     onWalk = onWalk, | ||||
|     onTeleport = onTeleport, | ||||
|     onWalkFinish = onWalkFinish | ||||
|   }) | ||||
|   removeEvent(autoWalkEvent) | ||||
|   stopSmartWalk() | ||||
|   unbindKeys() | ||||
|   disableWSAD() | ||||
| end | ||||
|  | ||||
| function bindKeys() | ||||
|   bindWalkKey('Up', North) | ||||
|   bindWalkKey('Right', East) | ||||
|   bindWalkKey('Down', South) | ||||
|   bindWalkKey('Left', West) | ||||
|   bindWalkKey('Numpad8', North) | ||||
|   bindWalkKey('Numpad9', NorthEast) | ||||
|   bindWalkKey('Numpad6', East) | ||||
|   bindWalkKey('Numpad3', SouthEast) | ||||
|   bindWalkKey('Numpad2', South) | ||||
|   bindWalkKey('Numpad1', SouthWest) | ||||
|   bindWalkKey('Numpad4', West) | ||||
|   bindWalkKey('Numpad7', NorthWest) | ||||
|  | ||||
|   bindTurnKey('Ctrl+Up', North) | ||||
|   bindTurnKey('Ctrl+Right', East) | ||||
|   bindTurnKey('Ctrl+Down', South) | ||||
|   bindTurnKey('Ctrl+Left', West) | ||||
|   bindTurnKey('Ctrl+Numpad8', North) | ||||
|   bindTurnKey('Ctrl+Numpad6', East) | ||||
|   bindTurnKey('Ctrl+Numpad2', South) | ||||
|   bindTurnKey('Ctrl+Numpad4', West) | ||||
| end | ||||
|  | ||||
| function unbindKeys() | ||||
|   unbindWalkKey('Up', North) | ||||
|   unbindWalkKey('Right', East) | ||||
|   unbindWalkKey('Down', South) | ||||
|   unbindWalkKey('Left', West) | ||||
|   unbindWalkKey('Numpad8', North) | ||||
|   unbindWalkKey('Numpad9', NorthEast) | ||||
|   unbindWalkKey('Numpad6', East) | ||||
|   unbindWalkKey('Numpad3', SouthEast) | ||||
|   unbindWalkKey('Numpad2', South) | ||||
|   unbindWalkKey('Numpad1', SouthWest) | ||||
|   unbindWalkKey('Numpad4', West) | ||||
|   unbindWalkKey('Numpad7', NorthWest) | ||||
|  | ||||
|   unbindTurnKey('Ctrl+Up', North) | ||||
|   unbindTurnKey('Ctrl+Right', East) | ||||
|   unbindTurnKey('Ctrl+Down', South) | ||||
|   unbindTurnKey('Ctrl+Left', West) | ||||
|   unbindTurnKey('Ctrl+Numpad8', North) | ||||
|   unbindTurnKey('Ctrl+Numpad6', East) | ||||
|   unbindTurnKey('Ctrl+Numpad2', South) | ||||
|   unbindTurnKey('Ctrl+Numpad4', West) | ||||
| end | ||||
|  | ||||
| function enableWSAD() | ||||
|   if wsadWalking then | ||||
|     return | ||||
|   end | ||||
|   wsadWalking = true   | ||||
|   local player = g_game.getLocalPlayer() | ||||
|   if player then | ||||
|     player:lockWalk(100) -- 100 ms walk lock for all directions     | ||||
|   end | ||||
|  | ||||
|   bindWalkKey("W", North) | ||||
|   bindWalkKey("D", East) | ||||
|   bindWalkKey("S", South) | ||||
|   bindWalkKey("A", West) | ||||
|  | ||||
|   bindTurnKey("Ctrl+W", North) | ||||
|   bindTurnKey("Ctrl+D", East) | ||||
|   bindTurnKey("Ctrl+S", South) | ||||
|   bindTurnKey("Ctrl+A", West) | ||||
|  | ||||
|   bindWalkKey("E", NorthEast) | ||||
|   bindWalkKey("Q", NorthWest) | ||||
|   bindWalkKey("C", SouthEast) | ||||
|   bindWalkKey("Z", SouthWest) | ||||
| end | ||||
|  | ||||
| function disableWSAD() | ||||
|   if not wsadWalking then | ||||
|     return | ||||
|   end | ||||
|   wsadWalking = false | ||||
|  | ||||
|   unbindWalkKey("W") | ||||
|   unbindWalkKey("D") | ||||
|   unbindWalkKey("S") | ||||
|   unbindWalkKey("A") | ||||
|  | ||||
|   unbindTurnKey("Ctrl+W") | ||||
|   unbindTurnKey("Ctrl+D") | ||||
|   unbindTurnKey("Ctrl+S") | ||||
|   unbindTurnKey("Ctrl+A") | ||||
|  | ||||
|   unbindWalkKey("E") | ||||
|   unbindWalkKey("Q") | ||||
|   unbindWalkKey("C") | ||||
|   unbindWalkKey("Z") | ||||
| end | ||||
|  | ||||
| function bindWalkKey(key, dir) | ||||
|   local gameRootPanel = modules.game_interface.getRootPanel() | ||||
|   g_keyboard.bindKeyDown(key, function() changeWalkDir(dir) end, gameRootPanel, true) | ||||
|   g_keyboard.bindKeyUp(key, function() changeWalkDir(dir, true) end, gameRootPanel, true) | ||||
|   g_keyboard.bindKeyPress(key, function(c, k, ticks) smartWalk(dir, ticks) end, gameRootPanel) | ||||
| end | ||||
|  | ||||
| function unbindWalkKey(key) | ||||
|   local gameRootPanel = modules.game_interface.getRootPanel() | ||||
|   g_keyboard.unbindKeyDown(key, gameRootPanel) | ||||
|   g_keyboard.unbindKeyUp(key, gameRootPanel) | ||||
|   g_keyboard.unbindKeyPress(key, gameRootPanel) | ||||
| end | ||||
|  | ||||
| function bindTurnKey(key, dir) | ||||
|   turnKeys[key] = dir | ||||
|   local gameRootPanel = modules.game_interface.getRootPanel() | ||||
|   g_keyboard.bindKeyDown(key, function() turn(dir, false) end, gameRootPanel) | ||||
|   g_keyboard.bindKeyPress(key, function() turn(dir, true) end, gameRootPanel) | ||||
|   g_keyboard.bindKeyUp(key, function() local player = g_game.getLocalPlayer() if player then player:lockWalk(200) end end, gameRootPanel) | ||||
| end | ||||
|  | ||||
| function unbindTurnKey(key) | ||||
|   turnKeys[key] = nil | ||||
|   local gameRootPanel = modules.game_interface.getRootPanel() | ||||
|   g_keyboard.unbindKeyDown(key, gameRootPanel) | ||||
|   g_keyboard.unbindKeyPress(key, gameRootPanel) | ||||
|   g_keyboard.unbindKeyUp(key, gameRootPanel) | ||||
| end | ||||
|  | ||||
| function stopSmartWalk() | ||||
|   smartWalkDirs = {} | ||||
|   smartWalkDir = nil | ||||
| end | ||||
|  | ||||
| function changeWalkDir(dir, pop) | ||||
|   while table.removevalue(smartWalkDirs, dir) do end | ||||
|   if pop then | ||||
|     if #smartWalkDirs == 0 then | ||||
|       stopSmartWalk() | ||||
|       return | ||||
|     end | ||||
|   else | ||||
|     table.insert(smartWalkDirs, 1, dir) | ||||
|   end | ||||
|  | ||||
|   smartWalkDir = smartWalkDirs[1] | ||||
|   if modules.client_options.getOption('smartWalk') and #smartWalkDirs > 1 then | ||||
|     for _,d in pairs(smartWalkDirs) do | ||||
|       if (smartWalkDir == North and d == West) or (smartWalkDir == West and d == North) then | ||||
|         smartWalkDir = NorthWest | ||||
|         break | ||||
|       elseif (smartWalkDir == North and d == East) or (smartWalkDir == East and d == North) then | ||||
|         smartWalkDir = NorthEast | ||||
|         break | ||||
|       elseif (smartWalkDir == South and d == West) or (smartWalkDir == West and d == South) then | ||||
|         smartWalkDir = SouthWest | ||||
|         break | ||||
|       elseif (smartWalkDir == South and d == East) or (smartWalkDir == East and d == South) then | ||||
|         smartWalkDir = SouthEast | ||||
|         break | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  | ||||
| function smartWalk(dir, ticks) | ||||
|   walkEvent = scheduleEvent(function()  | ||||
|     if g_keyboard.getModifiers() == KeyboardNoModifier then | ||||
|       local direction = smartWalkDir or dir | ||||
|       walk(direction, ticks) | ||||
|       return true | ||||
|     end | ||||
|     return false | ||||
|   end, 20) | ||||
| end | ||||
|  | ||||
| function canChangeFloorDown(pos) | ||||
|   pos.z = pos.z + 1 | ||||
|   toTile = g_map.getTile(pos) | ||||
|   return toTile and toTile:hasElevation(3) | ||||
| end | ||||
|  | ||||
| function canChangeFloorUp(pos) | ||||
|   pos.z = pos.z - 1 | ||||
|   toTile = g_map.getTile(pos) | ||||
|   return toTile and toTile:isWalkable() | ||||
| end | ||||
|  | ||||
| function onPositionChange(player, newPos, oldPos) | ||||
| end | ||||
|  | ||||
| function onWalk(player, newPos, oldPos) | ||||
|   if autoFinishNextServerWalk + 200 > g_clock.millis() then | ||||
|     player:finishServerWalking() | ||||
|   end | ||||
| end | ||||
|  | ||||
| function onTeleport(player, newPos, oldPos) | ||||
|   if not newPos or not oldPos then | ||||
|     return | ||||
|   end | ||||
|   -- floor change is also teleport | ||||
|   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   | ||||
|     -- far teleport, lock walk for 100ms | ||||
|     walkLock = g_clock.millis() + g_settings.getNumber('walkTeleportDelay') | ||||
|   else | ||||
|     walkLock = g_clock.millis() + g_settings.getNumber('walkStairsDelay') | ||||
|   end | ||||
|   nextWalkDir = nil -- cancel autowalk | ||||
| end | ||||
|  | ||||
| function onWalkFinish(player) | ||||
|   lastFinishedStep = g_clock.millis() | ||||
|   if nextWalkDir ~= nil then | ||||
|     removeEvent(autoWalkEvent) | ||||
|     autoWalkEvent = addEvent(function() if nextWalkDir ~= nil then walk(nextWalkDir, 0) end end, false) | ||||
|   end | ||||
| end | ||||
|  | ||||
| function onCancelWalk(player) | ||||
|   player:lockWalk(50) | ||||
| end | ||||
|  | ||||
| function walk(dir, ticks)  | ||||
|   lastManualWalk = g_clock.millis() | ||||
|   local player = g_game.getLocalPlayer() | ||||
|   if not player or g_game.isDead() or player:isDead() then | ||||
|     return | ||||
|   end | ||||
|  | ||||
|   if player:isWalkLocked() then | ||||
|     nextWalkDir = nil | ||||
|     return | ||||
|   end | ||||
|  | ||||
|   if g_game.isFollowing() then | ||||
|     g_game.cancelFollow() | ||||
|   end | ||||
|  | ||||
|   if player:isAutoWalking() then | ||||
|     if lastStop + 100 < g_clock.millis() then | ||||
|       lastStop = g_clock.millis() | ||||
|       player:stopAutoWalk() | ||||
|       g_game.stop() | ||||
|     end | ||||
|   end | ||||
|       | ||||
|   local dash = false | ||||
|   local ignoredCanWalk = false | ||||
|   if not g_game.getFeature(GameNewWalking) then | ||||
|     dash = g_settings.getBoolean("dash", false) | ||||
|   end | ||||
|  | ||||
|   local ticksToNextWalk = player:getStepTicksLeft() | ||||
|   if not player:canWalk(dir) then -- canWalk return false when previous walk is not finished or not confirmed by server | ||||
|     if dash then  | ||||
|       ignoredCanWalk = true | ||||
|     else | ||||
|       if ticksToNextWalk < 500 and (lastWalkDir ~= dir or ticks == 0) then | ||||
|         nextWalkDir = dir | ||||
|       end | ||||
|       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 | ||||
|         nextWalkDir = dir | ||||
|       end | ||||
|       return | ||||
|     end | ||||
|   end | ||||
|    | ||||
|   --if nextWalkDir ~= nil and lastFinishedStep + 200 < g_clock.millis() then | ||||
|   --  print("Cancel " .. nextWalkDir) | ||||
|   --  nextWalkDir = nil | ||||
|   --end | ||||
|   if nextWalkDir ~= nil and nextWalkDir ~= lastWalkDir then  | ||||
|     dir = nextWalkDir | ||||
|   end | ||||
|  | ||||
|   local toPos = player:getPrewalkingPosition(true) | ||||
|   if dir == North then | ||||
|     toPos.y = toPos.y - 1 | ||||
|   elseif dir == East then | ||||
|     toPos.x = toPos.x + 1 | ||||
|   elseif dir == South then | ||||
|     toPos.y = toPos.y + 1 | ||||
|   elseif dir == West then | ||||
|     toPos.x = toPos.x - 1 | ||||
|   elseif dir == NorthEast then | ||||
|     toPos.x = toPos.x + 1 | ||||
|     toPos.y = toPos.y - 1 | ||||
|   elseif dir == SouthEast then | ||||
|     toPos.x = toPos.x + 1 | ||||
|     toPos.y = toPos.y + 1 | ||||
|   elseif dir == SouthWest then | ||||
|     toPos.x = toPos.x - 1 | ||||
|     toPos.y = toPos.y + 1 | ||||
|   elseif dir == NorthWest then | ||||
|     toPos.x = toPos.x - 1 | ||||
|     toPos.y = toPos.y - 1 | ||||
|   end | ||||
|   local toTile = g_map.getTile(toPos) | ||||
|  | ||||
|   if walkLock >= g_clock.millis() and lastWalkDir == dir then | ||||
|     nextWalkDir = nil | ||||
|     return | ||||
|   end | ||||
|  | ||||
|   if firstStep and lastWalkDir == dir and lastWalk + g_settings.getNumber('walkFirstStepDelay') > g_clock.millis() then | ||||
|     firstStep = false | ||||
|     walkLock = lastWalk + g_settings.getNumber('walkFirstStepDelay') | ||||
|     return | ||||
|   end | ||||
|    | ||||
|   if dash and lastWalkDir == dir and lastWalk + 50 > g_clock.millis() then | ||||
|     return | ||||
|   end   | ||||
|    | ||||
|   firstStep = (not player:isWalking() and lastFinishedStep + 100 < g_clock.millis() and walkLock + 100 < g_clock.millis()) | ||||
|   if player:isServerWalking() and not dash then | ||||
|     walkLock = walkLock + math.max(g_settings.getNumber('walkFirstStepDelay'), 100) | ||||
|   end | ||||
|    | ||||
|   nextWalkDir = nil | ||||
|   removeEvent(autoWalkEvent) | ||||
|   autoWalkEvent = nil | ||||
|   local preWalked = false | ||||
|   if toTile and toTile:isWalkable() then | ||||
|     if not player:isServerWalking() and not ignoredCanWalk then | ||||
|       player:preWalk(dir) | ||||
|       preWalked = true | ||||
|     end | ||||
|   else | ||||
|     local playerTile = player:getTile() | ||||
|     if (playerTile and playerTile:hasElevation(3) and canChangeFloorUp(toPos)) or canChangeFloorDown(toPos) or (toTile and toTile:isEmpty() and not toTile:isBlocking()) then | ||||
|       player:lockWalk(100) | ||||
|     elseif player:isServerWalking() then | ||||
|       g_game.stop() | ||||
|       return | ||||
|     elseif not toTile then | ||||
|       player:lockWalk(100) -- bug fix for missing stairs down on map | ||||
|     else | ||||
|       if g_app.isMobile() and dir <= Directions.West then  | ||||
|         turn(dir, ticks > 0) | ||||
|       end | ||||
|       return -- not walkable tile | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   if player:isServerWalking() and not dash then | ||||
|     g_game.stop() | ||||
|     player:finishServerWalking() | ||||
|     autoFinishNextServerWalk = g_clock.millis() + 200 | ||||
|   end | ||||
|   g_game.walk(dir, preWalked)   | ||||
|    | ||||
|   if not firstStep and lastWalkDir ~= dir then | ||||
|     walkLock = g_clock.millis() + g_settings.getNumber('walkTurnDelay')     | ||||
|   end | ||||
|    | ||||
|   lastWalkDir = dir | ||||
|   lastWalk = g_clock.millis() | ||||
|   return true | ||||
| end | ||||
|  | ||||
| function turn(dir, repeated) | ||||
|   local player = g_game.getLocalPlayer() | ||||
|   if player:isWalking() and player:getWalkDirection() == dir and not player:isServerWalking() then | ||||
|     return | ||||
|   end | ||||
|    | ||||
|   removeEvent(walkEvent) | ||||
|    | ||||
|   if not repeated or (lastTurn + 100 < g_clock.millis()) then | ||||
|     g_game.turn(dir) | ||||
|     changeWalkDir(dir) | ||||
|     lastTurn = g_clock.millis() | ||||
|     if not repeated then | ||||
|       lastTurn = g_clock.millis() + 50 | ||||
|     end | ||||
|     lastTurnDirection = dir | ||||
|     nextWalkDir = nil | ||||
|     player:lockWalk(g_settings.getNumber('walkCtrlTurnDelay')) | ||||
|   end | ||||
| end | ||||
|  | ||||
| function checkTurn() | ||||
|   for keys, direction in pairs(turnKeys) do | ||||
|     if g_keyboard.areKeysPressed(keys) then | ||||
|       turn(direction, false) | ||||
|     end | ||||
|   end | ||||
| end | ||||
							
								
								
									
										9
									
								
								SabrehavenOTClient/modules/game_walking/walking.otmod
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								SabrehavenOTClient/modules/game_walking/walking.otmod
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| Module | ||||
|   name: game_walking | ||||
|   description: Control walking and turns | ||||
|   author: otclient.ovh | ||||
|   website: http://otclient.ovh | ||||
|   scripts: [ walking ] | ||||
|   dependencies: [ game_interface ] | ||||
|   @onLoad: init() | ||||
|   @onUnload: terminate() | ||||
		Reference in New Issue
	
	Block a user
	 ErikasKontenis
					ErikasKontenis