Codesmith512 Posted December 3, 2016 Share Posted December 3, 2016 Earlier this week I posted a question regarding pathfinding so I could implement the ability to right-click on the map screen to initiate travel, unfortunately it seemed that the game's native pathfinding system doesn't support long-distance travel. So I present to you modders, Trailblazer! Trailblazer is a (beta) pathfinding API that is capable of finding a path through entire maps! Currently it finds paths across huge worlds (without looping or branching, intended to be the longest paths possible) in about a second (usually a little less). If it interests you, feel free to grab my Map Travel mod as an example on how to use this. If you find any bugs, please report them here. And if you find anything I did wrong, please tell me so I can learn from it! Finally, if you're an aspiring artist, feel free to make me an icon, and I'll give you credit in the mod's description! Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/ Share on other sites More sharing options...
Serpens Posted December 3, 2016 Share Posted December 3, 2016 (edited) Is pathfinding already better than the ingame pathfinding which the waypoint mod uses? And are there conflicts with minimap mod? I think it would be the best, to disable the "rightclick-travel" for minimap... but if possible you could add option to allow it to work even for minimap. And are there lags when trying to find the path? When I remember right, the waypoint mod added the option to disable the ingame pathfinding thing, cause it causes lag on cluttered servers. Edited December 3, 2016 by Serpens Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-844378 Share on other sites More sharing options...
Codesmith512 Posted December 3, 2016 Author Share Posted December 3, 2016 (edited) 1 hour ago, Serpens said: Is pathfinding already better than the ingame pathfinding which the waypoint mod uses? The ingame pathfinding algorithm just returns a straight line if the path exceeds a given length (probably 40 units), but this algorithm will traverse the entire map, so in this sense it's more robust. However it's currently single-threaded for simplicity of development, if that becomes an issue I'm sure I can make it multithreaded or concurrent (given that LUA supports either) 1 hour ago, Serpens said: And are there conflicts with minimap mod? I think it would be the best, to disable the "rightclick-travel" for minimap... but if possible you could add option to allow it to work even for minimap. I don't think there should be conflicts with the minimap mod, but I'll have to check. The right-click to travel portion is actually a separate mod, this only implements a pathfinding algorithm, and a simple way to invoke movement using it. 1 hour ago, Serpens said: ... are there lags when trying to find the path? When I remember right, the waypoint mod added the option to disable the ingame pathfinding thing, cause it causes lag on cluttered servers. I'm not sure as of yet how it will affect the networking side of things, but I've got plans to test it tonight with a friend (testing both client and host side), but that's the most testing I can give it as I don't have a server with quite a few people. So I might need some help from you guys in this respect. However, if there are lag issues, I'm sure LUA has a multithreading (or at least a concurrency) API that would solve this problem. - Codesmith Edited December 3, 2016 by Codesmith512 fixed typo Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-844387 Share on other sites More sharing options...
Serpens Posted December 3, 2016 Share Posted December 3, 2016 (edited) And it is not a good idea to replace the locomotor component. Better add this to your modmain: Spoiler local ARRIVE_STEP = .15 -- I think we can't access the local one in origial locomotor ... AddComponentPostInit("locomotor", function(self) local _PreviewAction = self.PreviewAction self.PreviewAction = function(self, bufferedaction, run, try_instant) if bufferedaction == nil then return end if bufferedaction.action == GLOBAL.ACTIONS.TRAILBLAZE then self.throttle = 1 self:Clear() self:Trailblaze(bufferedaction.pos, bufferedaction, run) else return _PreviewAction(self, bufferedaction, run, try_instant) end end local _PushAction = self.PushAction self.PushAction = function(self, bufferedaction, run, try_instant) if bufferedaction == nil then return end if bufferedaction.action == GLOBAL.ACTIONS.TRAILBLAZE then self.throttle = 1 local success, reason = bufferedaction:TestForStart() if not success then self.inst:PushEvent("actionfailed", { action = bufferedaction, reason = reason }) return end self:Clear() self:Trailblaze(bufferedaction.pos, bufferedaction, run) if self.inst.components.playercontroller ~= nil then self.inst.components.playercontroller:OnRemoteBufferedAction() end else return _PushAction(self, bufferedaction, run, try_instant) end end self.Trailblaze = function(self, pt, bufferedaction, run, overridedest) print("TRAILBLAZE!!!!") self.dest = GLOBAL.Dest(overridedest, pt) --print("TRAILBLAZE!!!! "..GLOBAL.tostring(pt).." bufferedaction: "..GLOBAL.tostring(bufferedaction).." run: "..GLOBAL.tostring(run).." dest: "..GLOBAL.tostring(self.dest)) self.throttle = 1 self.arrive_dist = bufferedaction ~= nil and (bufferedaction.distance or GLOBAL.math.max(bufferedaction.action.mindistance or 0, ARRIVE_STEP)) or ARRIVE_STEP self.wantstorun = run if self.directdrive then if run then self:RunForward() else self:WalkForward() end else local p0 = GLOBAL.Vector3(self.inst.Transform:GetWorldPosition()) local p1 = GLOBAL.Vector3(self.dest:GetPoint()) local pathfinder = GLOBAL.require("components/trailblazer") local path = pathfinder.find_path(p0, p1, self.pathcaps) if path.steps ~= nil then self.path = {} self.path.steps = path.steps self.path.currentstep = 2 self.path.handle = nil end end self.wantstomoveforward = true self:SetBufferedAction(bufferedaction) self:StartUpdatingInternal() end end) -- Register trailblaze action (can be submitted to locomotor just like WALKTO; uses custom pathfinding algorithm) AddAction("TRAILBLAZE", "Travel via Trailblaze", function(act) end) Edited December 3, 2016 by Serpens added spoiler and fixed code Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-844389 Share on other sites More sharing options...
Serpens Posted December 3, 2016 Share Posted December 3, 2016 (edited) thank you for response Minimap mod makes no problems, but rightclick on it also won't do anything. I think this is okay, but if you have some time left, you could try to make it optionally work also with minimap mod The conflict described below is fixed with the new code in modmain, without replacing the component files. Don't ask me why The only conflict I found so far is the "auto-actions" mod, I already reported it at the mod at steamworkshop, cause I think this is something the author should fix and not you... but I'm not 100% sure.http://steamcommunity.com/workshop/filedetails/discussion/651419070/365163686037074563/#c152390648088243595 Edited December 3, 2016 by Serpens Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-844390 Share on other sites More sharing options...
Serpens Posted December 3, 2016 Share Posted December 3, 2016 (edited) I fixed the code for locomoter above The only thing we can not access is ARRIVE_STEP, so I added a local with same value at the beginning of modmain. Now it works About lagging: Playing alone, the screen stops for a short time, when hitting in a long distance on the map. The question is, if this also happens at clients pc, while the host (=server if without caves) rightclicks. Edited December 3, 2016 by Serpens Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-844394 Share on other sites More sharing options...
Codesmith512 Posted December 5, 2016 Author Share Posted December 5, 2016 (edited) I completely got my threads mixed up this weekend, so I missed your last comment. I did all of my testing in a game with caves, so I'll need to do some more with just a standard multiplayer world, hopefully tonight. Also, thanks for taking care of the locomotor code, I was curious to see how that was going to end up since it has a custom function. Edited December 5, 2016 by Codesmith512 Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-844940 Share on other sites More sharing options...
Serpens Posted December 5, 2016 Share Posted December 5, 2016 Although I shortly tested my code for modmain, better test it also again before releasing, just to make sure I made no mistakes. Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-844948 Share on other sites More sharing options...
Codesmith512 Posted December 5, 2016 Author Share Posted December 5, 2016 (edited) I made a few tweaks so I didn't have to override the entirety of the locomotor's update function for my speed multiplier fix After testing, everything else looks good Edited December 5, 2016 by Codesmith512 Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-844950 Share on other sites More sharing options...
Codesmith512 Posted December 5, 2016 Author Share Posted December 5, 2016 When I get a few minutes today I think I'm going to start implementing the concurrent routine, even if there isn't any networking issues (it would be weird if there weren't), it'll fix the entire game hanging during calculation, and it shouldn't be too difficult to implement (I hope...) Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-844951 Share on other sites More sharing options...
Codesmith512 Posted December 5, 2016 Author Share Posted December 5, 2016 (edited) So LUA doesn't support multithreading (I should've guessed that a scripting language wouldn't), but I do have a concurrent method, I just need a way to update it once a frame. I tried putting the call in 'Locomotor:OnUpdate', but that only updates while the player is walking (go figure...). From the few basic tests I've done, it looks pretty smooth, I just need a reliable way to get it to be called each frame (or at a very regular interval) Any Ideas? Edit: I do see lots of mods using 'inst:DoPeriodicTask', but it would be ideal to be able to have a 'inst:RemovePeriodicTask' Edited December 5, 2016 by Codesmith512 Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-845215 Share on other sites More sharing options...
Kzisor Posted December 6, 2016 Share Posted December 6, 2016 1 hour ago, Codesmith512 said: I tried putting the call in 'Locomotor:OnUpdate', but that only updates while the player is walking (go figure...). This isn't entirely accurate. OnUpdate is called when the game gets back around to calling it after calling all the other components with OnUpdate. I believe there is a specific amount of components which will update on any given frame hence the 'dt' variable of the OnUpdate function. If you're wanting to use path finding to it's fullest, the optimal way would be to create a brain (these run on every frame [or just about]) and set it for the player when they right click on the map. If they decide to press any key, reset the brain back to the default player brain. This should give you the most optimal set-up. Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-845240 Share on other sites More sharing options...
Codesmith512 Posted December 6, 2016 Author Share Posted December 6, 2016 (edited) 21 minutes ago, Kzisor said: This isn't entirely accurate. OnUpdate is called when the game gets back around to calling it after calling all the other components with OnUpdate. I believe there is a specific amount of components which will update on any given frame hence the 'dt' variable of the OnUpdate function. This may also be the case, but the code I'm using looks like this -- Concurrently process trailblazer local _OnUpdate = self.OnUpdate self.OnUpdate = function(self, dt) if self.trailblazePath ~= nil then if trailblazer.processPath(self.trailblazePath, 1000) then if self.trailblazePath.nativePath.steps ~= nil then self.path = {} self.path.steps = self.trailblazePath.nativePath.steps self.path.currentstep = 2 self.path.handle = nil self.wantstomoveforward = true self:SetBufferedAction(bufferedaction) self:StartUpdatingInternal() end self.trailblazer = nil end print("Processing Path...") end _OnUpdate(self, dt) end If I click somewhere, and leave the computer for 1-2 minutes, nothing. I don't even get the print. However, as soon as I click somewhere, and the player starts moving, I get "Processing Path..." in the console, and a fraction of a second later, the player starts going on my path instead. That said, I don't need to update exactly every frame, but I do need some frequency (it takes ~27 calls to 'processPath' to finish an end-end map traversal). I think I'm going to play with the 'DoPeriodicWork', coding a new brain and hotswapping them seems like overkill (even if it's not a medical procedure lol) Edited December 6, 2016 by Codesmith512 Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-845248 Share on other sites More sharing options...
Codesmith512 Posted December 6, 2016 Author Share Posted December 6, 2016 So the locomotor isn't an entity (I guess) so I can't use 'DoPeriodicTask'.. I'd rather not code a brain just for the update loop for a few cycles, but it may come to that. Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-845251 Share on other sites More sharing options...
Kzisor Posted December 6, 2016 Share Posted December 6, 2016 14 minutes ago, Codesmith512 said: This may also be the case, but the code I'm using looks like this If I click somewhere, and leave the computer for 1-2 minutes, nothing. I don't even get the print. However, as soon as I click somewhere, and the player starts moving, I get "Processing Path..." in the console, and a fraction of a second later, the player starts going on my path instead. That said, I don't need to update exactly every frame, but I do need some frequency (it takes ~27 calls to 'processPath' to finish an end-end map traversal). I think I'm going to play with the 'DoPeriodicWork', coding a new brain and hotswapping them seems like overkill (even if it's not a medical procedure lol) That's strange and it probably is an error somewhere else in the code. You can test it by placing a print right underneath the function descriptor. However, when working with other components and the OnUpdate function; it always gets called periodically. 2 minutes ago, Codesmith512 said: So the locomotor isn't an entity (I guess) so I can't use 'DoPeriodicTask'.. I'd rather not code a brain just for the update loop for a few cycles, but it may come to that. Locomotor is a component, not an entity, the entity is what the locomotor is attached to. Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-845254 Share on other sites More sharing options...
Codesmith512 Posted December 6, 2016 Author Share Posted December 6, 2016 3 hours ago, Kzisor said: That's strange and it probably is an error somewhere else in the code. You can test it by placing a print right underneath the function descriptor. However, when working with other components and the OnUpdate function; it always gets called periodically. Actually, the locomotor has a call to 'self:StopUpdatingInternal' in a couple of places that look like they intentionally disable the update loop if the entity is not traveling anywhere (they also have the inverse call to 'self:StartUpdatingInternal' when the locomotor is invoked to start traveling), so it seems intentional (to save resources?). 3 hours ago, Kzisor said: Locomotor is a component, not an entity, the entity is what the locomotor is attached to. Unfortunately, the DoPeriodicTask only seems to update 1 time per second tops... I think my next attempt is going to be to tie into the 'Locomotor:OnUpdate'.. tomorrow.. Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-845315 Share on other sites More sharing options...
Serpens Posted December 6, 2016 Share Posted December 6, 2016 (edited) Yes, I'm also sure that onUpdate for locomoter only updates when moving at least one tile. I use it for my "Homebase Bonus" mod, and in this function I do the speed change, if standing on special floor. If only standing there, nothing will happen. If moving small steps, nothing will hapen. Just if moving at least one (or two?) tile, the speed changes. And I'm also quite sure this behaviour is defined anywhere in this component, I think I also searched for this and found it, since I wondered about this behaviour. For DoPeriodicTask there is a "Remove". You make it that way: local mytask = inst:DoPeriodicTask(...) if mytask~=nil then mytask:Cancel() mytask=nil end Edited December 6, 2016 by Serpens Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-845353 Share on other sites More sharing options...
Kzisor Posted December 6, 2016 Share Posted December 6, 2016 7 hours ago, Codesmith512 said: I think my next attempt is going to be to tie into the 'Locomotor:OnUpdate'.. tomorrow.. If that is the case, I haven't looked at the locomotor a great deal, then simply create a new component instead of using the locomotor. Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-845381 Share on other sites More sharing options...
Codesmith512 Posted December 7, 2016 Author Share Posted December 7, 2016 (edited) On 12/6/2016 at 5:09 AM, Serpens said: For DoPeriodicTask there is a "Remove". You make it that way: local mytask = inst:DoPeriodicTask(...) if mytask~=nil then mytask:Cancel() mytask=nil end This and setting the time for the task to .05 or so is the key! I've got a bug right now where sometimes the path just picks a random direction, but as soon as that's sorted out I'll push the concurrency update. Edited December 7, 2016 by Codesmith512 Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-845796 Share on other sites More sharing options...
Codesmith512 Posted December 8, 2016 Author Share Posted December 8, 2016 I think I've fixed the bug, so I pushed the update! Unless it breaks again, I'm hopefully going to fix the smoothing algorithm over the next few days; I'll push that, and if it looks good after a few days, I'll push it as the full release! Thanks @Serpens and @Kzisor for the help! Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-846054 Share on other sites More sharing options...
Codesmith512 Posted December 13, 2016 Author Share Posted December 13, 2016 I've been playing with this mod for several days now with no issues in sight, so I'm confident enough to remove the beta tag! Thanks again for all the help guys! Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-848012 Share on other sites More sharing options...
Traveel Posted May 27, 2020 Share Posted May 27, 2020 Is it possible to make it factor trails/roads/paths into account? Link to comment https://forums.kleientertainment.com/forums/topic/72219-mod-beta-trailblazer/#findComment-1336760 Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now