[SUPPORT] Advanced Turn Based Tile Toolkit

Hey just seen the new video. Are there plans to allow hex shaped tiles follow a terrain map as well, or are you staying with squares only?

That’s already included. Just do the exact same thing with a hexagonal grid. Either replace the decals with the appropriate hex decals or use Grid_Manager_Child_Hex, which has these set up already.

Hey , I just started working on the new version. Unfortunately, I did a some work on a project the day before you announced that the new one was available, so I have added some parts to the blueprint on the first version, where, after the Grid Manager blueprint would start up, it would spawn three characters on random tiles. Obviously, this means none of the characters are being placed manually before pressing “Play”. However, in the new version, I transferred this function and its variables to the same place on the BP_Grid_Manger blueprint and the characters are placed correctly. The problem is that no value is set for “CurrentPawn” in ATBTT_PlayerController or in BP_Grid_Camera. I am assuming this is because where CurrentPawn is set in ATBTT_GameMode, there is nothing to set it to because this is called before that part is in the Grid Manager? I was just hoping you could point me in the right direction towards getting CurrentPawn to be set to perhaps, the last character added to the grid in my function, just so that there is some value there so it will run correctly. Better yet, if there was a way to go without setting current pawn until one of them is clicked, so there can be free camera, since I plan on adding that anyway. Thanks!

Hi Sreno1, that’s a few different things you’re asking. I’ll address them each in turn. First, as you’ve rightly guessed, the order of operations when the game starts up is important. The Game Mode fires before the Grid Manager, so the game mode sorts pawns in initiative order and selects the current pawn before you have spawned any pawns in the grid manager. The simplest way to fix this is to insert a delay in the game mode before the current pawn is selected, so that the pawns will have been placed before they are sorted in initiative. There is in fact already such a delay in the game mode, but it is placed after the pawns are sorted. Move this delay over to before they are sorted, like this:

But of course, you don’t want to have a current pawn at the start of the game at all right? In that case, simply delete the “cast to” and “set current pawn” parts of what’s pictured above and connect up what’s left. Make sure to set the spawn transform of the camera to something appropriate. Then you want to prevent the game mode from running all the nodes activating the current pawn. To do this, simply disconnect all the stuff inside the “Setup actor references” parts of the game mode from the rest by breaking the link after “Set BP Grid Camera Ref”. Also, set the default value of PlayerTurn to “true”.

If you’ve done the above you’ll have something pretty close to what you want. There is no current pawn selected at the start, and clicking any of the player pawns will select that pawn (provided “Player can switch pawns” is set to true). However, a remaining problem is that if you click any other tile than one inhabited by a player pawn the “End Turn” custom event will run and select the next pawn in initiative as the current pawn. Do disable this, include a branch statement at the start of the “End Turn” part of ATBTT_PlayerController to check if “Current Pawn” is empty. If it is, don’t bother ending a nonexistent current pawn’s turn. Like so (the “Select Asset” part of the == statement means the blueprint checks if current pawn is empty):

I think that should solve all of your problems. One last thing you might want to do is to make the current pawn marker invisible at the start of the game and make it visible the first time you click a pawn.

As a bonus, I set up some super simple nodes for spawning a pawn from a blueprint. You’ve figured this out already, but it might be useful for anyone else reading. The blueprint graph in the image below (from the end of the event graph of BP_Grid_Manager) spawns a Unit_Player_Melee pawn at grid index 5 at event begin play. In this case it is important to do this before running the “Add Viewport Pawns To Pawn Array” function. If you do not do this, or want to spawn pawns at any later point in the game, you have to add the pawn at the appropriate index in the Pawn Actor Array and its faction at the same index in the Pawn Array.

I hope this will help you achieve the result you are after.

Wow, thank you so much. This is great, exactly what I was looking for!

No, problem! I was planning to implement what you were asking for pretty soon anyway. You asking just sped me up a bit. I’ll be using some of that code for the first game example I’m working on, showing how you can use 2D with the toolkit and adding touch contols. Here’s a little WIP screenshot of the mobile game map, using my own shoddy pixel art:

JNHKvto.png

I just bought this blueprint pack today, and just fiddling around with it, it’s amazing what you’ve done so far! After watching the tutorial videos and reading this thread, I do have a couple questions I hope you can answer;
I can’t seem to find the option for diamond shaped vision. Maybe I’m just thick and glossed over it, I’m not sure. Can you help me?
Secondly, I want to be able to set a minimum attack range, so a ranged unit can’t attack the tiles immediately adjacent to it, for example. Would that be possible?
Finally, I’d like to have a setup for counter-attacks, so an attacking melee unit also takes some damage from the attacked melee unit. I have a couple ideas on how to implement this, but I figured I’d consult the creator of the blueprint first before tinkering around blindly, or accidentally skipping over a readily available option.

EDIT: I found the diamond shaped vision option! And the minimum range option (though I can’t seem to figure out how to get that to apply on a per-unit basis, so melee units can still attack tiles immediately around them. Some help would be nice but I might figure it out yet) So disregard that, I’m still a noob at this.

Also, something else I can’t seem to figure out in the interim: When the game starts, one of the units is already selected. Would it be possible to have the game start in a “Neutral” state, with no units selected, just a free cursor, before selecting and issuing orders to a unit?

Hi MonkeyPants, glad you figured out the diamond shape/minimum range stuff on your own. It is not set up at a per-unit basis at the moment, but it is very easy to set up. First you should create two new public variables in the Unit_Parent blueprint; one boolean and one integer. You could call the boolean “diamond shaped range” and the integer “min range”. Then in ATBTT_PlayerController go to the Activate Unit part of the blueprint and get those two public variables from current pawn, the same way I get current move, range etc. in that part of the graph. Connect diamond shaped range to the “Diamond Shape” poolean input in the Find Tiles In Range function and min range on the min range integer input and you’re good to go.

It is worth noting one bug, though. If you enable diagonal movement on a pawn, but have diamond shaped vision and a range of 1 it will cause problems. The reason is that when the AI finds a path to a player it naïvely assumes that any tile that is 1 movement away from the player are also in range of the player. If the AI does have diagonal movement it may stop on one of the tiles diagonal to the player and then try to attack. If it has a diamond shaped range of 1 the player will not be in range. When looking for a target this will return 0 and the AI will teleport to index 0 on the grid. To avoid this do not use any units with both diagonal movement, diamond shaped vision and a range of 1. I think this is a corner case as all games I know of with diagonal movement do not have diamond shaped vision. I am nonetheless working on a solution, but it’s actually a somewhat tricky problem to solve.

As for starting the game with no units selected, I solved this for another user a few posts up. Look at my post three posts before your own.

There are a number of different ways to set up counter attacks, and it depends a bit what you’re going for. I would start by looking in the blueprint graph of Unit_Parent in the Receive Damage part of the graph. From there you should fire a new attack target event from the unit receiving damage. There’s a bit more to it than that, but that’s the general idea.

So I’ve been tinkering with getting my ATB style system to work, where each unit has a stat with say 100pts, and each world tick they regenerate some number of those points, and when it reaches the max value they call their turn and act accordingly.

Most “difficult” part is figuring out what blueprint nodes I can safely just delete XD in regards to turn structure and ordering!

Beyond that it’s been a joy working with this.

Any suggestions for how to easily do grid highlighting for things like abilities and spells?(such as a fireball that hits X hexes).

Hi , can’t say I completely understand the first thing you are trying to accomplish. Are you assigning each unit a random initiative value each turn and activating them in that order? Or are they using points from a pool during their turn and how much points they use determine how long until they can act again?

Turn structure and ordering is pretty much exclusively handled in ATBTT_Game_Mode, with the exception of switching between units by clicking on them, which is handled by ATBTT_PlayerController.

If you want to highlight an area a spell hits I suggest you use the Find Tile In Range function and simply call it from the center of the explosion.

Great idea, mind to share how you increase the points of all units and check if they are higher than 100 at the same time? Main problem I see should be to first get all results after a tick, then look which of them are higher than 100 and finally check which one of them is highest.
Are you using a ForLoop with the initiative order array to compare the current points of each pawn to 100? I wouldn’t even know how to compare a value of a group of pawns which is variable in size to get the pawn with the largest value…

@
Could you please briefly explain to me how ranged attacks work? I’m working on activated abilities and I’m struggeling with creating attacks with a different range than the characters ‘Range’ value. Everything works fine for attacks with the same range as the pawns and changing the characters ‘Range’ on activation of the ability works, too. Isn’t there a function I can run to set the attack range to my custom spell range variable without touching the characters ‘Range’ value?

@
Ah yeah, you’re right, it’s weird how I missed that post. Thanks so much for your patience!
And what you described for counter-attacks is almost exactly what I ended up doing. Works great!

There is indeed. Run the function Find Tiles in Range, which is stored in BP_GridManager. It is usually called in ATBTT_PlayerController in the Activate Unit part of the blueprint graph. Here the range value of current pawn is connected to the range input of Find Tiles In Range, which is why visibility works like it does out of the box.

Happy to hear it works!

Second one, essentially, blurring the lines between turn based and real-time a bit. I was just commenting that because my system is so different the hardest part has been having to read your code in depth and figure out which parts I can safely delete without losing other functionality XD. Which is a good thing!

Every unit has an Action Point and Action Point Regen attribute, so in unit parent every tick their AP pool is filled by an amount determined by their APR, and when that threshold hits 100, the unit either takes an action according to its AI, or if controlled by the player, an action going by its list of queued actions, pays the cost of the associated action(which varies) from their AP pool, and then can’t act until it hits 100 again.

When a unit hits 100 they’re added to an array and only take their action if they’re the only member in the array, in the event that two units are in the array(they both hit 100 on the same event tick), they’re sorted by their swiftness attribute and the higher acts first, in the event they have the same swiftness, a random die is rolled for each until the die rolls are not the same and the highest goes first. Basically in this “psuedo-realtime” setup gotta make sure that no two units are ever acting at exactly the same time or else you get weird results(like two units moving to the same valid hex at the same time and such).

Game I’m working on is somewhat a hybrid SRPG and RTS in terms of its system.

We thought about a system like that, too. But we are still not sure if we want to go with something like that. The other idea would be that every character acts when a counter (counting up from 0) is equal to his initiative value or a multiple of that. A random roll when initiative of multiple characters is the same would also be necessary here.
We just want to give characters with higher initiative the ability to act more often than characters with lower initiative.

Is there a way to easily sort an array of actors by one of their values? (Sort all actors with Action Points greater than 100 by their Swiftness)

Thx! Going to look into that right now! :slight_smile:

Edit: Everything worked out quite well! Only thing that seems to be a little more work is getting targeting meshes on enemy as well as player tiles (for abilities that could target either of them).

While I’m at it… Is there an easy way to get all tiles within a non-tile radius?
Let’s say I give an input in UE4 units, like for example 480 units. Now I want to get all tiles whose center is within a 480 units radius and finally get all pawns that are on those tiles.

Ok, I think I understand. That’s a pretty interesting setup, though I would personally do it a bit differently. I would avoid increasing something per tick and instead go for something more predictable. One way could be to have an initiative counter that starts at 0. Units start with different initiative values with 0 being the best and higher values being worse. The game would check if any pawns have initiative 0; and if not would increase the counter by 1 and check again. When a unit takes an action it increases its initiative by a certain amount depending on the action. If a unit has an initiative value equal to the counter, but has not added any actions to its queue yet it would increase its initiative by 1.

So for example, you have two units, one fast with starting initiative 1 and one slow with starting initiative 3. The game initiative counter starts at 0 and checks all units for that value with a foreach-loop. Finding no pawns it increases to 1 and checks again. The unit with initiative 1 has queued an attack action and now gets to act, the attack costing 2 initiative, putting its initiative at 3. The counter increases to 2, finding no pawns. Then it increases to 3 finding two pawns, deciding between them by coin-toss or comparing speed attributes. The slow unit is activated, but has no queued action and gets its initiative increased to 4, and so on.

If I understood your solution correctly, I think this will achieve similar results, but will be more predictable and easier to balance compared to using a PerTick counter, which would be affected by things like the animation and move speeds of units.

Sorting is certainly possible, but a bit tricky to explain. See the function Sort Pawns In Initiative Order Depending On Attribute (Or something similar. Can’t check now) in ATBTT_GameMode for an example sorting algorithm.

Ok, great! As for getting targeting meshes on both players and enemies, there are a couple of ways to do this. One is to modify the function to find both kinds of units (this is done in the last two nested functions inside Find Tiles In Range). If you do this, be sure to make it an option to only look for one type of pawn. Another way to do it is to run a ForEach-loop on the tiles in range array and compare the index (inside the range struct) of each tile in range with the same indexes of the Pawn Array to see what pawns of what factions are on each tile. This can be done after the Find Tiles In Range function has been run.

Not out of the box, no. Can I ask why you would want to do this? It might be achievable using a tile radius instead. If you are using a hex grid, the XY-distance to a tile will always have a predictable relationship to the number of tiles it is from the starting point. In this case you can just take the distance you are interested in and divide it by NodeGapX (the distance in unreal units between tiles) and use that as the range input for a Find Tiles In Range function. This wouldn’t work with square grids as distances between tiles vary.

Thought I could post a couple of PMs between me and Wisdom- about implementing cover systems, since it might be of interest to more users. I’ve got ’s permission to post this:

Your cover system seems reasonable. An adjustment I would probably want to make if you want to be as close to XCOM as possible is to pregenerate all the cover instead of calculating it each time a unit enters a tile that might have cover. This way you can have the option of showing all tiles with cover to the player at any time (possibly when he/she presses a button). To do this, I would follow my example in the “Add Viewport Terrain To Arrays” function in BP_GridManager. In the last part of this function I assign edge costs to all indexes depending on the height difference between each tile and its neighbors. Something very similar could be done with a cover system. An integer storage like you suggest is one possibility here. A slightly less efficient, but more intuitive one is to use structs like I do with edge costs.

As for deciding whether or not a unit has cover depending on where the attacker is standing in relation to the target, there are many ways to do this. If what you want to achieve is simply to for instance give cover bonus to a unit with eastern cover against all units east of that unit, you could simply find the X location of one unit and subtract it from the other. Depending on whether it is negative or positive you know which side of the unit it is. Same for north and south cover, only with the Y location.

Also, you’re saying that you are working on an action point system. I’m unsure if you are asking for my help on this, but if you are, know that the toolkit has a half-way implemented action point system already. If you check “Unit Can Split Up Turns” on a unit, movement can be parceled into multiple moves. This is quite simple to convert to also work for attacks. Rename Current and Max move to current/max action points and check that you have enough before making an attack, subtracting the appropriate number from current action points if you do. Also, disable the part in Receive Damage in Unit_Parent that ends the turn after a unit takes damage.

Those are my suggestions in any case. Looking forward to seeing your game in action!

I thought about creating AoEs like XCom grenades. There you can specify the center of your AoE independent of tile position and enemies that are going to be hit are marked with red color. I wanted to do something similar but show a decal on the tiles that are going to be hit instead of giving the units a red texture (we’re using square tiles by the way).
With this I want to give the player more freedom of how exactly AoEs are placed and introduce an attribute which affects AoE radius with every point instead of increasing the radius by 1 tile every X points.

Maybe I need to get all pawns in a specified radius arround the mouse cursor and then check on which tiles those pawns are? So instead of looking if the radius overlaps with the center of a tile I could check which pawn meshes are overlapping with the radius. This could maybe work by using a sphere trace, unfortunately I have 0 experience with that so now I’ll just continue searching the web for useful information :slight_smile:

Also thanks for sharing the cover discussion! Some interesting stuff there :smiley:

@Hinato: You might consider not bothering querying the tiles at all, then. Simply use a spherical collision volume, enable collision on the skeletal meshes on pawns and see what pawns are overlapping the sphere. When the grenade explodes, run the Recieve Damage event on all units with skeletal meshes overlapping the sphere.

A couple very quick, probably very stupid questions;
So I did what you suggested above, as far as starting the camera free, and it worked, except now when the game starts it hovers over an enemy, and I can’t seem to figure out how to prevent it from doing that.
Also, I would like the camera to be zoomed out a little more than the default when the game starts, but I can’t seem to find that value in the camera blueprint that allows me to do that. I tried simply moving the camera itself in the blueprint viewport, which works, except then I can’t zoom back IN again. I’m wondering if there’s a smoother way to manipulate that in the blueprint itself.