[SUPPORT] Advanced Turn Based Tile Toolkit

If I set them to 0 at begin play in the grid manager they are all 0. If I do not then they are all 1. I only checked north for my test but I walked through all the indexes with a key press and print the index and the value of North. Even the top edge which should be 0 is not they are all 1.

Sorry ,

I understood all your message, except this part:
“After you have copied it make sure you get a new reference to the actual event driving these animations and replace the one that reads “copy”.”

Can you explain it better? Should I rename (for example) MoveAnimation_Copy to MoveAnimation in the child event graph?
Or should I do something different?

Hmm, very odd. So you are using your function for getting indexes under a mesh and when you set the edges of these indexes every index in the entire grid switches? Have you made sure your array of integers does contain the right amount of integers?

I’m still not home, but I’ll try just writing the answer again. If it is still unclear I will post a screenshot later. You’re on the right track. Renaming MoveAnimation_Copy to MoveAnimation will probably not work (I assume you will get an error since there already exists such an event. Instead right click the event graph and type in MoveAnimation to get a reference to the actual MoveAnimation event from the parent Anim_BP.

Edit: Here is a screenshot of what you want. When you copy from Pawn_Anim_BP_Parent you get what is in the top of the image. You want to replace MoveAnimation_Copy with Event Move Animation by getting it as shown in the left of the image. The end result should look like the bottom of the image.

Ok Anzak, I’ve replicated your function and for me it seems to work perfectly. Here is my function. It is basically a step-by-step copy of your function, just with some slight modifications, mainly caused by it being a function contained in BP_Grid_Manager. The math should be exactly the same:

For testing I’m activating this function through the level blueprint. This graph makes the tiles underneath the bounds of the actor inputted alternate between walkable and not when T is pressed:

Here is the result in game. Pressing T another time and rerunning pathfinding causes the tiles under the arrow to be walkable again.

Hope this is what you’re going for and that this will help you make it work.

By the way, how do you get the “- -” nodes in your function and the alternate way of getting local variables?

I was able to do something similar in Make Choice Array and get that part to work properly. Need to fix some bugs, but I am almost certain that it is somewhere in my code/code that I have change and not much you can help me with.

And don’t worry about bad naming. That happens to everyone at some point, and mine is probably even worse right now.

Hello!

First of all, let me say that I love the toolkit that you’ve put together. However, I’m currently working on something I was hoping you could perhaps help me with.

I’m trying to make it so that the player units can go into stealth when certain conditions are being met. One of those conditions is naturally dependent on whether or not the player units are visible to an enemy unit. I want to make it so that:

  1. Enemy units can “see” player units within X-range to the front or sides of the enemy unit. This sight will determine whether or not Player Units can enter stealth or not.
  2. Units behind meshes can’t be seen by enemy units.
  3. Units that are above a certain elevation can’t be seen by enemy units.
  4. Player Units who attack Enemy Units and/or cross line of sight lose their stealth status.

I’ve been looking through the Blueprints and haven’t been able to find what I need. I was hoping you could please offer some advice on how best to proceed. If you believe that there is a part of your blueprints that I may have missed that can help me in this task, I would greatly appreciate it if you could point me in the right direction. Or even if you were simply willing to offer some advice I would be quite pleased with any help you could offer. I had tried Raycasting but it always seems to raycast from the unit’s feet and thus doesn’t actually hit any meshes. It just seems to runs underneath everything.

I’m familiar with programming concepts although I haven’t had a great deal of experience with Blueprint itself. Any help you could provide would be appreciated.

Ok, that might be true, but I was also not entirely correct in my suggestion. What I suggested will work in my next update, but not in the version currently on the marketplace. For now do this instead:

Hi there! Seems like you want to take the toolkit in an exciting direction. I’ve been toying around in my head with various stealth mechanics ever since I played Invisible Inc., so I can give you some suggestion. There is of course several ways to do this, and it might not be ideal for you depending on what you’re after, but it should hopefully be enough to get you started.

I would like to use a new grid sized array for stealth which at any time knows every tile on the grid which is watched over by an enemy. This way it can be quickly checked at any time and can even be used to display all such tiles to the player. Add a new integer array to BP_GridManager and resize it to the size of the grid at the end of the startup nodes in the event graph of BP_GridManager like so:

All indexes will have a value of 0 to begin with. This means that it is not watched over by any enemy. A value of 1 will mean it is watched by 1 enemy, 2 that it is watched by 2 and so on.

Next lets add a few variables to Unit_Parent. We will want a float that holds the field of view of a pawn (the number of degrees in front of it that it can see), an integer array that holds all indexes the AI can currently see, a boolean that determines if a unit is currently in stealth mode and an integer for the unit’s maximum sight range. Like so:

Now we will want to make a function for the AI that takes all indexes within its field of view and sight range and stores them in both AI sight array and Index AI sight array (on the unit itself). First we run Find Tiles In Range with range set to the sight range of the unit to get all potential visible tiles (with Max Z Difference set to whatever max height difference we want it to be able to look up and check visibility set to true to account for cover). Like so:

9zYXJ81.png

Then we run a custom function in BP_GridManager that checks all tiles outputted by the Find Tiles In Range function and sees if they are in the unit’s field of view. If they are we store them in our various arrays. Like so:
moRg48i.png

We will need to run this function for all enemy units at the start of the game so we know which tiles they can see initially. I do it at the end of the event graph of BP_GridManager like this:

At this point we have informed the AI sight array of all tiles visible to enemy units. Lets check out if it works by spawning tiles in sight range for all indexes in this array with a value greater then 0. Here is one way to test it in BP_GridManager:

Then place some enemy units in your game (make sure their sight range and field of view are resonably high. I used 90 and 6 for this example) and press “U”. Works like a charm for me:

Ok, so that is all well and good. But we need to make sure this updates when an enemy moves or rotates. This means we need to subtract one from the indexes in AI sight array we added one to previously so that they are back to neutral and then run our Insert Tiles In Sight Into Sight Array from the unit’s new location. Luckily we have stored all indexes we need to subtract in the Index AI Sight Array in each unit, making it easy to know which one we want to subtract. This is something we will want to run whenever the unit moves or rotates, both of which happen inside the event graph of Unit_Parent in ATBTT. Therefore I choose to make a new function for these two operations in Unit_Parent. Like so:

We only need to insert this function two places in the event graph of Unit_Parent since there are only two conditions in ATBTT that causes a unit to rotate or move. So insert the function these two places:


Ok, so now the AI Sight Array will update appropriately. We are still missing our stealth stuff, though. First lets make a very simple way for units to enter stealth. I added this tiny graph to ATBTT_PlayerController for testing. For a real game you would probably run this event from clicking some button in your UI:

Then while a unit is moving we want it to check for every tile it enters whether or not that tile is observed and if it does we want to disable stealth. I have added this to the event graph of Unit_Parent in a pretty lazy way (though one that works):

Now all we have left is to make the AI ignore units that are in stealth. I’ve added this by removing the indexes of any units with stealth from the arrays containing units found during Find Tiles In Range and Pathfinding in ATBTT_AIController:

Ok, I hope I remembered to include everything. This is by far the most time consuming answer I have given to a question. I usually cannot go into such detail since I struggle to get enough time to work on the toolkit as it is, but I intend to make a stealth game example in the future and this allowed me to test out some ideas I’ve had. This is not a complete solution and has some limitations. For instance I have not added a way for the AI to discover hidden units on their own turns. When a unit is hidded it stays hidden until it moves to a tile that is watched by an enemy. This might or might not be what you want, but if you want further I hope I’ve given you enough of a head start to begin experimenting yourself. Good luck!

Hey there sorry if this has already came up before.
For the strategy game im making, its somewhat of a flaw that if you have no units on your team (faction) the game basically breaks.
constantly going through the AI turns.
In the game I want to make, units will not always be there, so I was wondering how I would set it up so the players turn order would be taken into account even if he has no units?

Still giving the player the turn to make new units, build structures etc

This could be something really simple/ you have already sorted out (hopefully)

Here is the macro I made for the – Note the compact node title.

The reason I made this is that I did not see the point to putting an exec pin on the – operator. In fact the default – and ++ are macros as well the difference between the stock version and my version is the exec pin.

I agree this is something I should probably add, and if I make a 4X strategy example it is certaily something I’ll add in. The only way I can think of off the top of my head is a slightly hacky one. Add a new child of Unit_Parent that is invisible and has a move and range of 0. In the player controller you should check if this is the current unit and if so you should refrain from running a lot of the other code that is there, like many of the click actions etc.

Ah, ok. It is a macro you made yourself. Clever :slight_smile: I thought it was something that came with the engine by default. It really should be, though.

Your solution was actually far better then the one that I tried out, so thanks for the suggestion.
The bugs I have now is stuff I created/modified myself

WOW! Thank you so much! Honestly this was way more than I was expecting, and I promise to put it to very good use. Can’t wait to start experimenting and I’ll be certain to be back to let you know what I find in my experimentation and if I have any more questions. Thank you again!

@ I was reading back through the comments you made to me to as I get back to work looking into my problem. I will have to check into the pathfinding that might be my issue. However one comment jumped out at me. You are changing the check on the edge array to the edges of the tile you are leaving? That does not make sense to me. It makes more sense to check the tile you are trying to enter. If I put a block on a tile I would know which tile I put it on and it would make more logical sense to set all the edges of that tile to 0 to block it off. Then to walk an array and change the values of all the tiles around it. It would also mean that north south east and west need to known to know which direction in the array to move to change those. Perhaps a toggle as to which direction to check it might be a better option so depending on what people are doing they can decide how best to manage their edge array.

Ok, awesome! I usually always test out my solutions in the version currently on the marketplace, but I forgot myself here initially. Glad it worked out.

No worries :slight_smile: It was fun to take a break from cleaning up code and bug testing for while. One thing I forgot to add is that you also have to make sure you reduce the integers in the AI Sight array not only when an AI unit moves, but also when it dies. Good luck with implementation!

The reasoning behind this is fairly complex and I agree that it is a bit counter intuitive. Frankly I’ve been testing back and forth with various methods for a long time now, and there are benifts and drawbacks to both solutions. The version you are using (the one on the marketplace) mostly checks the tile you are entering. It does this for both movement cost and edges that are blocked. However, in addition the tile you are exiting is checked for having an edge cost of 0. This was a necessary shortcut when I added walls between edges, as otherwise all such walls would have been single-sided.

As I’ve continued to experiment with the toolkit I’ve slowly been trying to head towards a pathfinding solution that is less dependent on the predictable spatial relationship of a grid. The method of checking the edge of the tile you are entering only works if indexes have a predictable spatial relationship. As an example when going from tile 1 to 2 you know from the grid that 2 should be east of 1, which means we can check the western edge of 2. However, if tiles could for instance be placed freely by the player this predictable relationship would disappear. One solution in this case is to store the indexes a tile is connected to as well as the edge costs to get to those indexes within each array index, which in practice means that you check the edge of the tile you are leaving. This is beneficial as I move on to adding things like true multi-level grids where tiles might have connections to more than 8 neighbors or even to different sub-grids.

This way of making pathfinding grids is whats called a directinal graph in graph theory, which is probably the most flexible and powerful way to represent pathfinding if you want to be able to add things like edges having different costs in different directions (think sloped hills) or one-way doors. Here is what a directional graph looks like:

This is all well and good, but as you have become aware there are some serious drawbacks to this solution. It really makes a lot more sense when you add an impassable wall to simply make the edges of the index where you added the wall 0 instead of the edges facing this tile of all surrounding tiles. To combat this I’ve added some fairly complex functions that let users say that they want to add a tile to an index, but that in practice adds its edges to all surrounding tiles. Here is one of these functions:

These things work under the hood and are run at startup, meaning they will not have an impact on actual game performance. For users who don’t want to tinker with the fundamentals of the toolkit this works great, but for advanced users such as yourself who want to manipulate the grid (as well as myself) it can in some cases become pretty tiresome. I’m debating with myself what solution is the best and if I can find some working middle ground. This is actually one of the main reasons the update has been delayed. Altering the fundamentals of the toolkit takes work, and I’ve been back and forth with several solutions, and now it seems I might do so again. Adding a switch between two methods is not something I would like to do. These changes to the toolkit are so fundamental that there would have to be a lot of switches to clutter up the toolkit, and supporting both methods in all future updates for any additional features would be a nightmare.

I hope I’ve given you some insight into my reasoning. To repeat, though, for the version you have the toolkit checks the edge it is entering, although it also checks if the tile it is leaving has an edge cost of 0. Please let me know what solutions you would find the most intuitive. I welcome any feedback and suggestions :slight_smile:

Thanks the invisible unit worked out pretty well.
I remember earlier in the year I spoke to you about multiple factions,
would one of the ways to do that to add more factions to the enum and add more into the game mode/ai controller?

Yeah, that’s absolutely one way to do it. The relevant places would be where units are added to the Pawns In Sight and Pawns In Range arrays in Pathfinding and Find Tiles In Range respectively, as well as the part of ATBTT_PlayerController that decides what action to perform when a tile is clicked depending on the faction contained in that tile. For the first two you could either make it so only the relevant factions are searched for during these functions or you could add every single unit found of every faction and then afterwards decide to keep only the relevant targets (similarly to how I do it in the last screenshot in post #639)

If i was doing your latter example, would that be essentially removing the faction variable from pathfinding and then doing some switches later into the graph to determine how to act?

Indeed. The player controller doesn’t care about the Pawns in Sight and Pawns in Range arrays, only the regular Pawn Array. For the AI controller you simply add all potential tiles and then sort out which ones you need to keep; probably using for loops like in the post I mentioned above. This way you do not have to add several switches to Pathfinding and Find Tiles In Range, which can quickly become quite a bit slower if they perform several operations for every tile checked.

When your referencing your previous images, is that a for each loop before based on all units in game before pathfinding
or a for each loop after pathfinding based on the reachable pawns array?

The second one. One for each loop for pawns in move range from pathfinding and one for pawns in sight range from Find Tiles in Range.