FAForever Forums
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Login

    CanPathTo function

    Scheduled Pinned Locked Moved Modding & Tools
    21 Posts 5 Posters 1.8k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • R
      Rama
      last edited by

      @Jip

      Hi Jip, since you wrote the navigation generator function, I feel you are the best to ask about this.

      I've noticed in replays I've watched of players hosting AI Wave Survival games, they are unaware that on water maps, Land waves should be set to amphibious or they get stuck at spawn. I wrote a simple script that uses CanPathTo to check if spawned units can path to players, and if not, with set waves to amphibious.

      Script works, except it generates a lot of false negatives where it says it can't path to players it actually can. This seems to be an issue on maps where spawns are far from each other, like on 20km maps, or have more complex terrain. I've noticed in testing that the CanPathTo function really doesn't test very far across the map.

      Don't know if you have a suggestion for reducing the false negatives rate.

      1 Reply Last reply Reply Quote 1
      • JipJ
        Jip
        last edited by

        @Rama do you have concrete examples for me? Then I can investigate if something is off

        A work of art is never finished, merely abandoned

        1 Reply Last reply Reply Quote 0
        • R
          Rama
          last edited by

          I'm not using your navigation generator, since I haven't figured it out.

          I first noticed the limitation of CanPathTo function when testing the script that finds spawn points for the Rift Orbs. I would generate hundreds of units, randomly over the map, and test if they could path to a player.

          First test showed all units spawning randomly around the entire map.

          On the second test, any units that failed the CanPathTo check would be destroyed. This would only leave the units that could path.

          On the second test, I noticed the units that remained were usually no further than 5km from the player spawns, instead of randomly over the entire map. The CanPathTo script appeared to abort early, causing units too far away from passing the test.

          This wasn't an issue for the Rift Orbs script, as I had intended to limit the max distance Orbs would spawn from players. But this does become an issue when trying to test for pathable players on larger maps, which can cause the script to find none and then default waves to amphibious units on a map that is all land.

          I plan to set the script as being able to be disabled by players, as there may be maps where players are on plateaus and they want all land units. The feature is more for new players who aren't aware they need to switch land waves to amphibious on water maps.

          C 1 Reply Last reply Reply Quote 0
          • maudlin27M
            maudlin27
            last edited by maudlin27

            If you're using the Unit:CanPathTo({X,Y,Z}) function that predated Jip's work on the navigational mesh it's unreliable - I gave up on using it fairly early on with M27 in favour of a homebrew approach (since at the time the navigational mesh work wasn't in place).

            For example, I found that the ACU would return false on being able to path to a destination at the start of the game, and then a short while later would return true to the same location (despite not having moved).

            I'd suggest just using Jip's navigational mesh instead - for example, to check if two locations can be pathed by land units:

            local NavUtils = import("/lua/sim/navutils.lua")
            local iStartLabel = NavUtils.GetLabel('Land', {x1,y1,z1})
            local iEndLabel = NavUtils.GetLabel('Land', {x2,y2,z2})
            if iStartLabel == iEndLabel then
                --you can path from start to end by land
            end
            

            M27AI and M28AI developer; Devlogs and more general AI development guide:
            https://forum.faforever.com/topic/2373/ai-development-guide-and-m27ai-v71-devlog
            https://forum.faforever.com/topic/5331/m28ai-devlog-v150

            JipJ 1 Reply Last reply Reply Quote 1
            • JipJ
              Jip @maudlin27
              last edited by

              @maudlin27 said in CanPathTo function:

              For example, I found that the ACU would return false on being able to path to a destination at the start of the game, and then a short while later would return true to the same location (despite not having moved).

              That's probably because the unit is set to be immobile the first few seconds of the game. It can then naturally not path to anything.

              @Rama I can only encourage you to look into the navigational mesh. It's extremely efficient at various queries; not just limited to navigation. If you need help with it then feel free to approach me on Discord for a voice chat

              A work of art is never finished, merely abandoned

              R maudlin27M 2 Replies Last reply Reply Quote 1
              • R
                Rama @Jip
                last edited by

                @jip

                I'll definitely look into it. Sounds like it can be used as a proper alternative to the CanPathTo function.

                @maudlin27
                Ah, thanks for the guidance! I will test this out later!

                1 Reply Last reply Reply Quote 0
                • maudlin27M
                  maudlin27 @Jip
                  last edited by

                  @jip I’m not sure it would just have been that as the results would change after waiting an amount of time but that time would vary from memory - eg sometimes I recall it mightve been 40s plus into the game that it started to be accurate. Then again it’s been several years since I last looked into it as it had massive performance issues as well (taking ages to calculate) which made it near-unusable for my purposes at the time regardless of its accuracy

                  M27AI and M28AI developer; Devlogs and more general AI development guide:
                  https://forum.faforever.com/topic/2373/ai-development-guide-and-m27ai-v71-devlog
                  https://forum.faforever.com/topic/5331/m28ai-devlog-v150

                  JipJ 1 Reply Last reply Reply Quote 0
                  • C
                    clyf @Rama
                    last edited by

                    @rama

                    I believe there's also a limit (for performance) on the amount of pathfinding that can be done any given tick. Completely speculative, but if you're spawning hundreds of units at once and giving them all simultaneous move orders the CanPathTo function might be timing out. If you haven't already, try cycling through the units that fail the check one at a time and doing it again.

                    1 Reply Last reply Reply Quote 0
                    • R
                      Rama
                      last edited by

                      @maudlin27 @Jip

                      Well, I just tried the new code maudlin27 shared with me, and it works perfect! Really, appreciate the contributions both of you make a lot! This makes things much simpler! I am going to have to get more familiarized with the abilities of Jip's navutility. Opens up some interesting possibilities.

                      JipJ 1 Reply Last reply Reply Quote 2
                      • JipJ
                        Jip @maudlin27
                        last edited by

                        @maudlin27 said in CanPathTo function:

                        @jip I’m not sure it would just have been that as the results would change after waiting an amount of time but that time would vary from memory - eg sometimes I recall it mightve been 40s plus into the game that it started to be accurate. Then again it’s been several years since I last looked into it as it had massive performance issues as well (taking ages to calculate) which made it near-unusable for my purposes at the time regardless of its accuracy

                        Engineers (including the (S)ACUs) are also set to be immobile while constructing.

                        A work of art is never finished, merely abandoned

                        1 Reply Last reply Reply Quote 0
                        • JipJ
                          Jip @Rama
                          last edited by Jip

                          @rama said in CanPathTo function:

                          @maudlin27 @Jip

                          Well, I just tried the new code maudlin27 shared with me, and it works perfect! Really, appreciate the contributions both of you make a lot! This makes things much simpler! I am going to have to get more familiarized with the abilities of Jip's navutility. Opens up some interesting possibilities.

                          The module navutils.lua exists to create a consistent interface for other developers that want to use the navigational mesh. There's also debug tooling that allows you to visualize the output of some of the functions. You can find them through the hotkeys menu:

                          d273e564-0afa-4efd-aa50-61569d28f04f-image.png

                          The highlighted hotkey is the main view for the navigational mesh. You can visualize the navigational mesh itself through the window it creates. It makes it easier to understand some of the utility functions.

                          You're actively discouraged to directly interface with the navigational mesh itself. That involves any function and / or data that directly originates from navgenerator.lua by importing it in your code.

                          How the navigational mesh works is still a work in progress. The interface of the navigational mesh itself can therefore change. As long as you make use of navutils.lua then you can be fairly certain that the interface remains stable.

                          If you'd like more functionality then feel free to discuss that with me. A lot of the functions that exist now in navutils.lua originate from requests by AI developers, specifically by Relent0r the author of RNGAI

                          A work of art is never finished, merely abandoned

                          1 Reply Last reply Reply Quote 2
                          • R
                            Rama
                            last edited by

                            @Jip

                            I was trying to improve the Rift Spawn point generator for maps that have difficult navigation areas. But looks like Rifts are still hitting in unpathable areas. I tried adding a NavUtils.CanPathTo test as a secondary to make sure path was valid. While this script worked in testing with bots (Rift Nukes would launch at start of game), it appeared to not work with actual players online (Rift Nukes never launched). No errors in logs related to the script.

                            This was the code snippet:

                            -startPos = Random location chosen as spawn point for Rift
                            -endPos = Randomly chosen Player start position
                            -StartAmphibious = NavUtils.GetLabel('Amphibious', startPos) --Where units are coming from
                            -EndAmphibious = NavUtils.GetLabel('Amphibious', {randX, terrainAttitude, randZ}) --Where units are trying to reach
                            01 if StartAmphibious == EndAmphibious then
                            02 local AccurateTest = NavUtils.CanPathTo('Amphibious', startPos, endPos)
                            03 if AccurateTest == true then --If Path is true then Position is added as possible Rift spawn point.
                            04 newPos = { randX, terrainAttitude, randZ, type = "VECTOR3" }
                            05 table.insert(validRiftPositions.positions, newPos)
                            06 end
                            07 end

                            Sorry on the ugly code snippet, I don't know how to add in the nice looking snippets.

                            I've since reverted the code in the latest release, AI Wave Survival v260. The prior version, v259, has the script that only appeared to work with bots.

                            1 Reply Last reply Reply Quote 0
                            • JipJ
                              Jip
                              last edited by

                              Did you generate the navigational mesh? If it is not generated, then it won't work. Make sure to call the generate function in NavUtils.lua at the start of the map script

                              A work of art is never finished, merely abandoned

                              1 Reply Last reply Reply Quote 0
                              • R
                                Rama
                                last edited by

                                Yes, I have NavUtilis.lua imported at start. It is also used to test if players can be reached by Amphibious units only, and will change the land units to Amphibious/Hover units only. That script works fine, and I redid the Rift Spawn Points script with it.

                                I checked the map the issue was occurring on, thinking there might be a small pathable route, but the areas were completely isolated.

                                1 Reply Last reply Reply Quote 0
                                • JipJ
                                  Jip
                                  last edited by

                                  Can you give me more context, such as the source code of the mod and the map (Rifts?)? Then I can investigate for you

                                  A work of art is never finished, merely abandoned

                                  R 1 Reply Last reply Reply Quote 0
                                  • R
                                    Rama @Jip
                                    last edited by

                                    @jip

                                    Below are two replays, both using v259 of AI Wave Survival, which used the above Code snippet to spawn the Rifts. The Rifts are a newer addition to the mod. Immediately after build time ends, and then again every few minutes, the AI will launch a Rift Nuke (an EMP nuke) that will land near the players. The nuke, on detonation, will create a Rift Orb. The Orbs are used as spawn points for additional waves of units.

                                    The Rift Script runs at the start of the game, testing random locations near players to see if Amphibious units can path to the player's start locations. If the script finds the units can, it will add the location to a list of possible positions Rift Nukes will be launched at.

                                    The code is in the following directory:
                                    \mods\AI Wave Survival\hook\lua\AI\AIBehaviors.lua

                                    For v259:
                                    Function name is CreateRiftSpawnPoints() on line 8864.
                                    All the functions below that, to line 9272, are part of the Rift Nukes/Orb/Waves scripts.

                                    1st Replay with v259, with Human players, I though I had corrected a potential bug in v258 that broke the Rift Script, as I had not added a "if huBrain and not huBrain:IsDefeated() then" check. First Rift Nuke should be launched immediately after Build Time ends, but no Rift Nukes are ever fired the entire match.
                                    Replay: #21288851

                                    2nd Replay with v259, with bots only, to test if Rift Nukes would work. Rift Nuke launches as it is supposed to, at end of Build Time, and another 4 minutes later (they should come every 4 minutes, increasing to every 2 minutes later in the game).
                                    Replay: #21289283

                                    And a final Replay with v257. This was the game where I noticed Rift Nukes were landing on mountains that were not pathable to the players, causing spawned units to get stuck, and is why I added the above Code Snippet. I have reverted v260 to this code, meaning Rifts function in latest version, but may hit in areas that are not pathable.
                                    Replay: #21277826

                                    1 Reply Last reply Reply Quote 0
                                    • JipJ
                                      Jip
                                      last edited by Jip

                                      It works with bots because the average bot generates the navigational mesh. It doesn't exist by default. You'll need to generate it before using it. See also this snippet. In the first replay (21288851) the navigational mesh was not generated.

                                      To generate it, add it to your simInit.lua hook like so:

                                      local parentBeginSession = BeginSession
                                      
                                      function BeginSession()
                                      
                                              import("/lua/sim/navutils.lua").Generate() -- <-- needs to be called before everything else that may rely on it
                                      
                                      	ScenarioInfo.Options.Victory = "domination" 
                                      	  -- dun break anything!
                                           parentBeginSession();
                                      	 
                                      	
                                      	 LOG("Trying to init survival")
                                      
                                      	--local aiBrain = GetArmyBrain("Army_9")
                                      	local behaviors = import('/mods/AI Wave Survival/hook/lua/ai/AIBehaviors.lua')	
                                      
                                           --behaviors.STRfour()
                                      	 --LOG(" behaviors.STRfour called")
                                      	
                                      	 ForkThread(behaviors.InitSurvival)
                                      	  LOG(" behaviors.InitSurvival called")
                                      	   -- run our own bit of the sim!
                                        
                                      	 LOG("init survival")
                                      	
                                      end
                                      

                                      A work of art is never finished, merely abandoned

                                      1 Reply Last reply Reply Quote 1
                                      • R
                                        Rama
                                        last edited by

                                        Oh, good to know! Yeah, I always test with bots first. Didn't know the navigation mesh didn't generate if no bots in the game. I assume once I add this, I won't need to add the additional code snippet to double check pathing? Is this test sufficient? Or do you think I should include the CanPathTo test? Don't know which function is more accurate/faster.

                                        -StartAmphibious = NavUtils.GetLabel('Amphibious', startPos) --Where units are coming from
                                        -EndAmphibious = NavUtils.GetLabel('Amphibious', {randX, terrainAttitude, randZ}) --Where units are trying to reach
                                        01 if StartAmphibious == EndAmphibious then

                                        1 Reply Last reply Reply Quote 0
                                        • JipJ
                                          Jip
                                          last edited by Jip

                                          I would just use CanPathTo, the definition can be found on Github. It does what you would do manually. Specifically, if the function returns false (can't path) then the last argument tells you why it returns false. You can use that in your code to understand your other options as what to do next.

                                          A work of art is never finished, merely abandoned

                                          1 Reply Last reply Reply Quote 1
                                          • JipJ
                                            Jip
                                            last edited by Jip

                                            @Rama In general - it may be worth your time to familiarize yourself with the functions that are available to you through navutils.lua. They can really help you get around (quite literally, heh) certain problems

                                            A work of art is never finished, merely abandoned

                                            R 1 Reply Last reply Reply Quote 1
                                            • First post
                                              Last post