Announcement

Collapse
No announcement yet.

[SUPPORT] Advanced Turn Based Tile Toolkit

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    hi PanAtoman

    i hope i can help you (probably knut will do a better job)

    but if you want to change your Default Move Marker Mesh, then just do it in the ability blueprint (for example if you use the move\attack ability - change the mesh in there) you are using not in the grid manager

    hope its help
    leo

    Comment


      Originally posted by Justo View Post
      Monokkel Thank you for answering!



      No, atm it does not work. My intent was to try and leave your code untouched as much as possible for now, so that future updates are as easy as possible, but my lack of knowledge in some areas leads to lots of mistakes as I learn more about blueprints. What you see is a child blueprint of your Player Controller that you made, as you previously suggested, and my intention was to put in there all custom events like the topdown player controller stuff, and then link to your code once Combat Entered was activated. I'm spawning a Grid Camera because that BP is no longer the Default Pawn Class, so I should make one. Parent: Begin Play executes automatically for now haha, which is something I need to fix somehow. Docs dont say much about that, so I'm still digging on how to fix it.

      I was wondering though why the SpawnActor pin does not spawn the camera after the press F event is executed, whereas other pins, like simple Print functions, do so without a problem.

      You mean make the camera spawn in the Setup Core Blueprints function, right? Yeah, that totally works, and I think it's the more logical and organized solution, looking at it as a finished product. I was trying to not do that though to keep your BPs as unmodified as possible, in case I replace them in the future with updates, and put all my dirty pleb code in one place for now for convenience sake.

      But yeah, I say it makes sense, and yet I'm confident that you know mountains more than I do, so what you say is most likely what I need to do ha...Thank you for taking the time to reply to me Knut.
      Not sure about your spawning issue, to be honest. Maybe the unconventional calling of a parent event is screwing something up somehow. When spawning new actors you often have to wait a tick to be able to manipulate it, so if you are checking if it has spawned the same tick as you spawned it, that might also cause it to seem like the camera seemingly hasn't spawned yet. Try using a delay of 0.0 seconds (which defaults to 1 tick) after spawning and see if you can get a valid reference.

      Originally posted by PanAtoman View Post
      hi Monokkel
      Sorry if this issue has been discussed somewhere else but maybe you can point me out where to look. I have a problem with adding custom geometry to the grid manager. This works fine on the hexagonal grid but seems broken in square one. Grid manager ignoring any custom geometry and always using square planar geometry.

      To replicate:

      v UE. 4.21

      add grid manager

      change the geometry in Default Move Marker Mesh

      Play

      Geometry stays unchanged

      See attached image:
      Click image for larger version

Name:	Image01.jpg
Views:	53
Size:	388.3 KB
ID:	1556000
      As leo bar has noted, you can change the meshes in the defaults of the ability. In older versions of the toolkit marker meshes were all set in the grid manager. I changed this so that it is instead set in the abilities themselves to improve flexibility. BP_Ability_Base and BP_Ability are now set up so that they only use the grid manager defaults if there is nothing specified in the abilities themselves.
      The Advanced Turn Based Tile Toolkit (Marketplace page - Feedback thread)

      Comment


        Monokkel , leo bar Thank you, guys. Works perfectly!
        MARKETPLACE
        PERSONAL PORTFOLIO
        <<<<Follow me on Twitter >>>>>

        Comment


          It's too early in development to implement right now, but eventually I think I'm going to want sky tiles and underwater tiles that are over and under the land tiles. How practical do you think this would be? (These would need to be adjacent to the tiles in their own columns, and perhaps diagonally)

          Comment


            Lachnor: Not sure if I follow. Why can't you just use regular multi-level grids for this?
            The Advanced Turn Based Tile Toolkit (Marketplace page - Feedback thread)

            Comment


              Is there a function available that can give me an array of tile indexes that pawn can attack CONSIDERING tiles it can move to from its current position in a single turn? Normally I'd run "Find tiles in range" adding move range to attack range and taking output BUT there may be an obstacle (usually another pawn) in the path of the pawn that won't allow that pawn to move and attack a specific tile. Maybe I could run "Pathfinding" with input of "move range+attack range" but I need to loop through a number of specific pawns on the grid and find that "can attack the tile with this index" array for each.


              Update: I duplicated "patfinding" function and all related variables and I'm using it for my purposes - seems to be working. I'm afraid it could be helluva slow though to loop through all tiles each turn and during each tile check to loop through all pawns to check if they are able to attack this tile during their next turn.

              What I need it for is to add a danger value to each tile based on how many pawns can reach and attack this tile and their damage.
              Last edited by ClaimedInfinity; 11-27-2018, 04:10 PM.

              Comment


                Originally posted by ClaimedInfinity View Post
                Is there a function available that can give me an array of tile indexes that pawn can attack CONSIDERING tiles it can move to from its current position in a single turn? Normally I'd run "Find tiles in range" adding move range to attack range and taking output BUT there may be an obstacle (usually another pawn) in the path of the pawn that won't allow that pawn to move and attack a specific tile. Maybe I could run "Pathfinding" with input of "move range+attack range" but I need to loop through a number of specific pawns on the grid and find that "can attack the tile with this index" array for each.


                Update: I duplicated "patfinding" function and all related variables and I'm using it for my purposes - seems to be working. I'm afraid it could be helluva slow though to loop through all tiles each turn and during each tile check to loop through all pawns to check if they are able to attack this tile during their next turn.

                What I need it for is to add a danger value to each tile based on how many pawns can reach and attack this tile and their damage.
                Both of the features you are asking for are actually already part of the toolkit. Finding all targets that could possibly be in range, taking into account move range, can be found in BP_Ability as the FindAllPossibleTargets function, which itself calls on several functions in BP_GridManager to achieve this end. Take a look at AssessAbilityValue in BP_Ability to see how it is set up.

                The answer to your second question can be found a few nodes further down in the same graph. Namely the EvaluateMoveTargets and GetPregeneratedTileValues functions in BP_Ability. EvaluateMoveTargets is a function meant to be overridden by the specific ability you are using, where you can change the paramaters that determines how much value to assign to moving to a tile. Whether an AI unit decides to move to that tile then becomes a factor of the value of the tile and the value of the targets that can be targeted from that tile.

                In the advanced example map JungleRaid I do something a bit more fancy, where I use the ability system to generate a safety value of each tile based on the cover and distance from enemy units. It is also set up so that it only needs to be set up once each turn for AI units that have multiple different abilities, by storing the values temporarily in the unit's ability system.

                AI is one of the most complicated topics in turn based strategy game design, and are thus some of the more complex systems in the toolkit. So let me know if you get stuck or have any questions.
                The Advanced Turn Based Tile Toolkit (Marketplace page - Feedback thread)

                Comment


                  Originally posted by Monokkel View Post

                  Both of the features you are asking for are actually already part of the toolkit. Finding all targets that could possibly be in range, taking into account move range, can be found in BP_Ability as the FindAllPossibleTargets function, which itself calls on several functions in BP_GridManager to achieve this end. Take a look at AssessAbilityValue in BP_Ability to see how it is set up.
                  Cool, FindAllPossibleTargets could do the trick. By default It gives unit indexes but looking at it I think it would be relatively easy to modify to give tile indexes.
                  I feel stupid missing that but a lot of changes have been made in the updated version with multi tile units and I'm still following the changes.

                  The answer to your second question can be found a few nodes further down in the same graph. Namely the EvaluateMoveTargets and GetPregeneratedTileValues functions in BP_Ability. EvaluateMoveTargets is a function meant to be overridden by the specific ability you are using, where you can change the paramaters that determines how much value to assign to moving to a tile. Whether an AI unit decides to move to that tile then becomes a factor of the value of the tile and the value of the targets that can be targeted from that tile.
                  Well It's a little deeper than that . To give a value of a tile to AI (which is not that hard) I'd need to get that value from somewhere first. In Jungle raid it's based on pregenerated cover array and distance to enemy units. In my case this is where FindAllPossibleTargets (tiles?) comes in (or crudely modified Pathfinding alternative that I made). I'm checking each enemy pawn to see if it is able to attack this specific tile. If yes then danger value of the tile == the damage value of that pawn/or a sum of damage values in case multiple pawns are able to reach the tile.

                  The thing is my project is based on Jungle Raid but it is melee, not ranged - with different weapons equipped by pawns (each weapon activating a specific set of skills) different types of armor protecting from specific types of damage etc. And typical attack range is 1-2 tiles. So there's a need for more complex calculations for AI to keep units in line and not rush into enemy-controlled areas with poor armor and weak weapons. Also a protection bonus comes not from the covers but from friendly pawns at adjacent tiles.
                  Last edited by ClaimedInfinity; 11-28-2018, 12:00 AM.

                  Comment


                    Originally posted by ClaimedInfinity View Post

                    Cool, FindAllPossibleTargets could do the trick. By default It gives unit indexes but looking at it I think it would be relatively easy to modify to give tile indexes.
                    I feel stupid missing that but a lot of changes have been made in the updated version with multi tile units and I'm still following the changes.

                    Well It's a little deeper than that . To give a value of a tile to AI (which is not that hard) I'd need to get that value from somewhere first. In Jungle raid it's based on pregenerated cover array and distance to enemy units. In my case this is where FindAllPossibleTargets (tiles?) comes in (or crudely modified Pathfinding alternative that I made). I'm checking each enemy pawn to see if it is able to attack this specific tile. If yes then danger value of the tile == the damage value of that pawn/or a sum of damage values in case multiple pawns are able to reach the tile.

                    The thing is my project is based on Jungle Raid but it is melee, not ranged - with different weapons equipped by pawns (each weapon activating a specific set of skills) different types of armor protecting from specific types of damage etc. And typical attack range is 1-2 tiles. So there's a need for more complex calculations for AI to keep units in line and not rush into enemy-controlled areas with poor armor and weak weapons. Also a protection bonus comes not from the covers but from friendly pawns at adjacent tiles.
                    Ok, if I understand you right you need to account for both the attack and move range of enemy units to figure out what tiles they threaten. To get perfect information on this I think you would need to run pathfinding for each separate unit and then find tiles in range for each of the tiles they can reach. Those are some very heavy calculations indeed, so lets try to think of ways to reduce this.

                    One very quick way is to simply GetIndexesInRange around each enemy unit, with a range equal to its move range plus its attack range. This will get you a fairly close heuristic for very open maps, but it would quickly break down if the map has a lot of obstacles, so this is unlikely to be what you want.

                    A better way to approach this, if your enemy units have roughly the same move and attack ranges, is to run a single pathfinding where you input the grid indexes as each enemy unit in the Open List of the pathfinding, and run the pathfinding with a move set to the average (or slighly above average) move range + attack range. Any tile found by the pathfinding will on average be attackable by at least one enemy. This will still not give perfect information by any means, but is super quick. Generally AI does not need to be perfect for the AI to provide a challenge and feel like it is making informed decisions.

                    A step up from this is to do the same thing, but separately for each unit. We are still not using FindTilesInRange for every single tile each unit can move to, but instead increasing its move range equal to its range. You can even alter the last steps of the pathfinding to emulate finding tiles in sight range by creating a custom pathfinding type that uses GridBaseEdges instead of GridEdges when finding connected tiles. This should give you pretty good results if you do not have units with attack ranges that are likely to have sight range blocked, but can potentially have some issues if your levels are such that there can often be "islands" within the pathfinding range that can be attacked but not reached through movement. If this is an issue it can be improved by after running the first pathfinding equal to move range, you run a new one that takes the indexes from FindPathfindingEdge as the first grid indexes in the open list and continues movement (using the GridBaseEdges suggestion) from here.

                    Those are the suggestions I can think up on the fly, at least. What can be done depends a bit on your game. How long are the longest move and attack ranges of your units? What is the size of the largest maps and how many units is the maximum amount that would be in one level? Are you using multi-level grids? Do you have many tiles that block sight on your maps? Are the maps single or multi-level? All of these factors will determine how far you can go with your algorithms before performance starts to become an issue.

                    You can of course consider making C++ functions for this AI search instead, though if you use a lot of line traces to check for sight, these will have a bigger impact on performance than the extra overhead from blueprint will.
                    The Advanced Turn Based Tile Toolkit (Marketplace page - Feedback thread)

                    Comment


                      Originally posted by Monokkel View Post
                      One very quick way is to simply GetIndexesInRange around each enemy unit, with a range equal to its move range plus its attack range. This will get you a fairly close heuristic for very open maps, but it would quickly break down if the map has a lot of obstacles, so this is unlikely to be what you want.

                      A better way to approach this, if your enemy units have roughly the same move and attack ranges, is to run a single pathfinding where you input the grid indexes as each enemy unit in the Open List of the pathfinding, and run the pathfinding with a move set to the average (or slighly above average) move range + attack range. Any tile found by the pathfinding will on average be attackable by at least one enemy. This will still not give perfect information by any means, but is super quick. Generally AI does not need to be perfect for the AI to provide a challenge and feel like it is making informed decisions.

                      A step up from this is to do the same thing, but separately for each unit. We are still not using FindTilesInRange for every single tile each unit can move to, but instead increasing its move range equal to its range. You can even alter the last steps of the pathfinding to emulate finding tiles in sight range by creating a custom pathfinding type that uses GridBaseEdges instead of GridEdges when finding connected tiles. This should give you pretty good results if you do not have units with attack ranges that are likely to have sight range blocked, but can potentially have some issues if your levels are such that there can often be "islands" within the pathfinding range that can be attacked but not reached through movement. If this is an issue it can be improved by after running the first pathfinding equal to move range, you run a new one that takes the indexes from FindPathfindingEdge as the first grid indexes in the open list and continues movement (using the GridBaseEdges suggestion) from here.
                      Ok, the first two ways are simple enough but I'm not sure if I got the third right. Are you suggesting we should run Pathfinding (maybe customized) for each unit separately? I'm doing something like that now.

                      As to the details. In my case the average move range is 4 tiles per turn (more likely 2 tiles per turn if you want to move and attack in the same turn) and attack range is 1-2 tiles (except light ranged units but those don't do much damage and it's ok to leave their danger calculations distance-based as it is now). Maps are single-level and no more than 20x20 tiles. There aren't many obstacles but a number of units can be pretty high though, at around 16 units per side, so the units can be obstacles themselves, that is why I'm thinking that GetIndexesInRange is not enough.

                      I had a couple of ideas to speed up the process too. First is to check for danger only the tiles that can be reached through move by a current pawn. Second is to exclude enemy units that cannot attack those tiles by any means. Third is to run pathfinding only for a limited number of pawns (let's say 4) that are closest to the current pawn/or move target tile. It could also emulate imperfect human thinking. I think so at least.

                      I agree that AI doesn't need to be perfect but I'd like to test how it'll work at least. Currently I'm getting perfectly accurate values by running customized Pathfinding for each pawn as I described before. I just don't know how slow It'll be in the end. At worst I have an option of returning to default AI settings of the toolkit with a few light modifications as the units seem to behave themselves fairly good and I can even lose sometimes when the odds are even in terms of numbers.
                      Last edited by ClaimedInfinity; 11-28-2018, 08:48 PM.

                      Comment


                        Originally posted by ClaimedInfinity View Post

                        Ok, the first two ways are simple enough but I'm not sure if I got the third right. Are you suggesting we should run Pathfinding (maybe customized) for each unit separately? I'm doing something like that now.

                        As to the details. In my case the average move range is 4 tiles per turn (more likely 2 tiles per turn if you want to move and attack in the same turn) and attack range is 1-2 tiles (except light ranged units but those don't do much damage and it's ok to leave their danger calculations distance-based as it is now). Maps are single-level and no more than 20x20 tiles. There aren't many obstacles but a number of units can be pretty high though, at around 16 units per side, so the units can be obstacles themselves, that is why I'm thinking that GetIndexesInRange is not enough.

                        I had a couple of ideas to speed up the process too. First is to check for danger only the tiles that can be reached through move by a current pawn. Second is to exclude enemy units that cannot attack those tiles by any means. Third is to run pathfinding only for a limited number of pawns (let's say 4) that are closest to the current pawn/or move target tile. It could also emulate imperfect human thinking. I think so at least.

                        I agree that AI doesn't need to be perfect but I'd like to test how it'll work at least. Currently I'm getting perfectly accurate values by running customized Pathfinding for each pawn as I described before. I just don't know how slow It'll be in the end. At worst I have an option of returning to default AI settings of the toolkit with a few light modifications as the units seem to behave themselves fairly good and I can even lose sometimes when the odds are even in terms of numbers.
                        Ok, the limited move and attack ranges and having a single-level map makes this a lot simpler. I did some quick tests, and running pathfinding with a move range of 2 and a sight range of 2, using GetIndexesInRange to find all tiles in range for each found pathfinding tile, looping over 16 units in a worst-case scenario takes around 0.2ms on my computer. This means you can do this safely without needing to do anything fancy. You can probably also throw some ranged units into the mix without any issues. Come to think of it, for units with a range of 1 you do not need to use GetIndexesInRange, but can instead just add 1 to their move in the pathfinding function, and you should get the same result.

                        If you instead of GetIndexesInRange use FindTilesInRange, that uses line traces to check for visibility, we're up to 3ms for 16 units, at which point you would skip a couple of frames. If you want to go for this you could split the loop up over multiple ticks with my ForLoopPerTickMacro, of course.
                        The Advanced Turn Based Tile Toolkit (Marketplace page - Feedback thread)

                        Comment


                          hi knut

                          if i may ask, how can you get how many ms takes to a specific function to run?

                          leo

                          Comment


                            Originally posted by leo bar View Post
                            hi knut

                            if i may ask, how can you get how many ms takes to a specific function to run?

                            leo
                            The best way is to use UE4's built-in profiler. However, I often use a lazy custom solution I made when I first developed the toolkit for quickly comparing stuff while I am developing. I use the DebugPrintElapsedTime function in BP_GridManager. It displays the time in milliseconds since last time you called the DebugPrintElapsedTime function. So to test a single function I would first call it right before the function (setting DoNotLog to true, since there is nothing sensible to log for the first call) and then another one at the end. It breaks down for delays over a second, and if it outputs negative numbers add 1 to get the correct result. Fairly hacky, but it is quick and gets the job done. Note that packaged builds are faster than Play Standalone which again is faster than Play in Viewport, so keep that in mind when testing. If you package then you are doing so much work that you might as well use the profiler, but I advise at least testing in standalone mode.
                            The Advanced Turn Based Tile Toolkit (Marketplace page - Feedback thread)

                            Comment


                              hi knut

                              thanks !!! yes i am using the profiler, but the truth is that i am bit lazy to go every time when i want to test something and use the profiler. your solution sounds great for quick testing, i will give it a go.

                              hope everything is going well with your phd!

                              leo

                              Comment


                                Originally posted by leo bar View Post
                                hi knut

                                thanks !!! yes i am using the profiler, but the truth is that i am bit lazy to go every time when i want to test something and use the profiler. your solution sounds great for quick testing, i will give it a go.

                                hope everything is going well with your phd!

                                leo
                                Thanks! Yeah, I'm often in the same situation, so this function is very useful for quick testing. You can also chain multiple of them together if you have a sequence of functions or nodes where you want to find out what part of the execution chain takes the most resources.
                                The Advanced Turn Based Tile Toolkit (Marketplace page - Feedback thread)

                                Comment

                                Working...
                                X