[SUPPORT] Advanced Turn Based Tile Toolkit

It has been ages since I played Final Fantasy Tactics, so could you tell me how this is different from the default camera functionality? By default the camera in ATBTT rotates 90 degrees when you press Q or E.

Hello @

Since youā€™re currently working on adding multiplayer, I thought I might pick your brain. Iā€™m trying to do the same thing in my project, though Iā€™m having some issues. Maybe you ran into some of them.

One of those issues is that, when a playercontroller ā€œclicksā€, I call ā€œGetHitTileLocationAndIndexā€ from Grid_Manager, as usual. It works for Player 1, but it doesnā€™t work for Player 2. When running the ā€œGetHitResultUnderCursorā€ function (cpp equivalent to ā€œGet Hit Result Under Cursor By Channelā€) with player 2 I always receive a false return value, and location (0,0,0). Iā€™m using your ā€œPathTraceā€ trace channel. When I click with Player 1, I get the normal result - a successful hit and the correct location.

I tried wrapping the entire click event in a replicated event that runs to server. But still no luck. Have you had this issue? Any idea how to solve it?

Thanks

Hey @Bridgeburners. Iā€™ve got it working on my end and Iā€™ll try to give you the steps to replicate it. In my build Iā€™m getting the hit location client side in the player controller first and then converting that location to a grid index server side. A client cannot use the GetHitTileLocationAndIndex function, since it requires access to the Vector Field array, which I am not replicating (and I assume you are not either). So first Get Hit Result Under Cursor By Channel -> pass the Hit Result Location to a custom event which is replicated to server and then use the Convert Location To Index 3D function to get the grid index. Hope that works on your end. Iā€™ve made so many changes that I might be forgetting some other essential step, but I think that should be all you need.

Thank you, that worked. I didnā€™t do it exactly the way youā€™re doing it, because my setup is different. But the main insight I needed was to get the hit result vector on the client side, and then calculate the index server side. Thanks again.

Iā€™m getting an idea of how cumbersome it is to rewrite or change a lot of the functions I wrote, to account for replication, in my humble little project that I only started a couple of months ago. So I certainly donā€™t envy you your task of having to do this for the entire toolkit. Good luck.

Hi ** thanks for the information about the camera movement it helped alot. One thing I did want to ask you could you recommend a save system. I have added in XP system level system and a spell system that unlocks with what level you are each character has there own system. I have tried a few tutorials on saves but it wonā€™t save everyones variables cheers**

Glad it worked :slight_smile: Yeah, getting everything to work with replication is the hardest part of the new update, for sure. I got most basic functionality working with replication fairly quickly, but the skill system is something Iā€™m still having trouble getting to work correctly for multiplayer, though Iā€™m getting there, one function at a time. It is the last major thing I have to do before getting the update done, though (besides commenting and some cleaning up).

I donā€™t know of any particular save systems to recommend. It should be possible to save any variable using UE4ā€™s built-in save features, I believe. Saving and loading is not something Iā€™ve worked a lot with, so you could try to describe your problem in more detail to me, but you might have more luck in the blueprint subforum, since this is something more general, and not specifically related to ATBTT.

Hi @. Sorry to bother you about multiplayer again, but since you have gone into the trenches, I was hoping you could offer some wisdom to help make my path a little easier.

Have you mainly stuck with the classes you made in earlier versions, or did you have to make new classes to account for the changes? For example, I hear that GameState should be used instead of GameMode as only the former exists on the clientā€™s end. Similarly, some say that PlayerState should be used instead of PlayerController, but I havenā€™t really touched PlayerState nor know much about its utility. Have you moved a lot of functionality to those classes, or are you still using the same ones, with clever use of replication and RPC? Is GridManager still the central hub of most of your grid-based functions?

Have you modified a lot of existing functions to be RPC? Or do you leave them as is and wrap them in higher level RPC events?

Also, if there were any major issues that you didnā€™t foresee until you were in the thick of things, Iā€™d love to know about it. You donā€™t have to get too descriptive, I donā€™t want to distract you from all the work you have to do, but any tips you have would be great.

@Bridgeburners: Happy to tell you what Iā€™ve got so far. I am indeed using Game State, though I am also using the game mode and a custom Turn Manager blueprint. The thing with the game mode is that it only exists on the server. That does by no means mean it does not have its place in multplayer games, however. To prevent cheating you generally want to keep all important calculations on the server and have the clients mostly be used for input and anything that can be seen by the players.

Game state can be seen as an extention of Game Mode for anything you want to be replicated. Iā€™m keeping a list of units, initiative order, the active unit and references to several important singleton blueprints in the game state (so that I donā€™t have to keep separate references to all such variables in every blueprint that need them, as Iā€™ve done before)

I now use the game mode mostly for initializing the game, including running start of game events in important blueprint to get more control than just running Event Begin Play for everything. I also use it for handling new players logging in.

The new turn manager blueprint is used for many of the turn order functions I previously used Game Mode for. Game Mode could still be used for this, but with a custom blueprint I have more control over what parts I want replicated, which makes it less awkward to work with.

Many things have been moved away from the player controller. Previously the player controller handled a lot of important calculations. Now it is mostly responsible for input, which is passed to separate Ability blueprints which do all calculations server side.

I mostly keep functions as is and wrap them up in RPC events.

Hope that helps!

Hello again @ ! Iā€™ve encountered another point where Iā€™m stuck probably just due to my lack of knowledge of Unreal. I got the skeleton mesh and most animations working with my units. If I donā€™t change the attack animation it works just fine, but if I change the attack animation then the units get stuck in it and wonā€™t switch back to any other animation. How would I go about fixing this? I imagine thereā€™s just a broken link somewhere in the blueprint after changing the animation but I have no idea where to look. Hereā€™s a fullscreen gif to show whatā€™s happening.

https://giphy.com/gifs/3o7aCQkL8jRFnnY0zm/fullscreen

Edit : Also I did notice that when I finally got the animation_bp working with my custom units, the demo units that you included stopped animating and started T-posing like in the video. No idea how I pulled that off but itā€™s not a major concern. Could be useful info for you though Iā€™m not sure.

@OperatorCrux: The animation blueprint in the included units uses animation notifies to call an event at the end of the animation, that tells the behavior tree to go back to idle. Look at the animation you intend to replace and find the name of the animation notify. Add it to your custom animation and it should work. Odd that the old units started T-posing, though. Did you make a duplicate of the default animation blueprint, a child blueprint or did you make one from scratch?

@ Thanks, that helps a lot!

Just to clarify something.

If I understand you correctly, all your ā€œreferenceā€ variables are now just stored in the game state? So if you want to, for example, spawn move tiles for a unit after the player clicks on that unit, you first get the selected unit after the click and then call GetGameState -> Cast to ATBTTGameState -> GridManagerRef -> Pathfinding from the player controller? (As opposed to the player having their own GridManagerRef.)

I make an exception for the grid manager, as it referenced so often that setting up a reference to it at Event Begin Play makes the graphs cleaner and easier to work with. Other than that I keep references in the game state. though I donā€™t need that much. There is a reference to the active unitand the turn manager, as you can get the grid camera by getting the controlled pawn. However, any future singleton classes Iā€™d add for a specific game Iā€™d probably add to the game state.

I had figured out how to get this far at around two in the morning my time so I probably just retargetted the wrong thing. I believe what I ended up doing was retargeting the Pawn_Anim_BP_Parent, Pawn_Anim_BP_Ranged, and Blend Spaces. What I need to do instead of this is duplicate those, and retarget the duplicates for the custom character? From there replace the anim notifies?

Edit : Can I get away with what Iā€™ve already done if I donā€™t intend on using your units? All of the units I plan on using have the same skeleton as the one that is currently using the animations. If doing this way breaks something I can absolutely go back and duplicate instead but if I can just replace the anim notifies that would be great.

Hi there! Just bought this on the Marketplace, great job!

Iā€™m looking to see if I can modify the setup a bit so that the BP_Grid_Manager and units are generated at runtime. Iā€™m interested in adding some factory/unit construction functionality and I was wondering if you had any tips on doing that. Or is your setup mostly designed to just be dropped into the editor and everything done via construction script, which I think is not fired if spawned at runtime though I could be wrong.

Thank you!

Edit: Iā€™ve determined that the Grid Manager needs to exist when the game starts or a lot of stuff breaks, as far as I can tell. Perhaps Iā€™ll have the grid manager manually placed in ā€“ however, I am having trouble spawning units (Using the Spawn Unit function in the Grid Manager) and having them interactible in the game. The unit spawns but I canā€™t click it or do anything. Any ideas? Thank you!

Slightly unrelated to the spawn unit problem, Iā€™m also unsure of how to change the size of the grid (X and Y) after runtime. For example, Iā€™d like to deploy a saving/loading system where you can load up a map that is say, 5x5. But if the grid manager is the default 3x3 at begin play, Iā€™m not sure if thereā€™s a way to change that dynamically.

Double edit: Sorry for all the edits! It appears the spawned unit behaves normally if there is at least one manually placed unit. Do you know if there is a way to allow a spawned unit to be selected and used when there are no units at all existing when the game starts?

@OperatorCrux: Ok, good you got it working. No, there is no reason to keep the originals of the animated units or animation blueprints. They are mostly examples of one way to animate units, and other blueprints do not depend on their functionality.

Hi ienjoywhiskey, and welcome :slight_smile: You are right in your observation that ATBTT is not ideally set up for spawning the grid manager after setup. Iā€™m meeting the challenge, though, and have hacked together a working solution. Iā€™ll probably add something more robust to the actual toolkit in the future, but this should help you get started. It took some experimentation, but it turned out I didnā€™t need to change all that much.

First Iā€™ve removed the event begin play event of ATBTT_Game_Mode and replaced them with a new event called ā€œStart Gameā€, so we have control on when we want to start it up. Iā€™ve set the default pawn to be something else than BP_GridCamera (I went with spectator pawn) and have made these additions to the event graph of ATBTT_PlayerController:

https://i.imgur.com/7pl2pfv.png

https://i.imgur.com/qJJVZRs.png

With this setup you press 1 to place the grid manager in the game (make sure to set any variables you want to alter when spawning to ā€œExpose on Spawnā€ in their variable properties, which I have done with GridSizeX and GridSizeY in this example). When you press 2 you spawn a melee player unit at the tile you are hovering over. When you press 3 you start the game by calling the Start Game event in ATBTT_GameMode (make sure to remove the call to ActivateGridManager from the event graph of ATBTT_GameMode so you donā€™t do it twice).

This setup is obviously too hardcoded, but you can make it a lot more flexible with a few additions.

Hope I remembered to describe all the steps so you can get it working. Let me know if it works and if it is what you were trying to do :slight_smile:

Awesome! Thank you man. I really appreciate you taking the time to RnD that. Iā€™ll give it a shot later on tonight.

I had one other unrelated questionā€¦
-Is there an easy way to ā€œdeselectā€ units when itā€™s your turn? I know currently you can switch between your units by clicking on them, but Iā€™d like an option to right-click and have no units selected. I tried setting it up myself last night by clearing the current pawn variable but it kinda borked a few things as a result.

Thanks again for your awesome support! :smiley:

Edit: So the runtime setup you taught me worked like a charm! Thanks again. I think I also figured out my above question about deselecting the unit ā€“ basically Iā€™m tweaking the flow of the Mouse click input to allow for deselecting/selecting units. Itā€™s going to be a long road to convert this to more of an Advance Wars - style setup with unit building/capturing but itā€™s a great place to start. :slight_smile:

Double Edit again: So I do have a question that is stumping me currently. Where in the Pathfinding functions would it be best to change out the goal actor/location of the pathfinding? For example, what if I wanted the AI to search for a particular grid/tile index rather than just an enemy with the lowest HP. Something dynamic so I can change the goal tile as needed. Looking through the pathfinding functions, I canā€™t seem to find where that goes and Iā€™m afraid to touch anything :stuck_out_tongue:

Thank you!

@ienjoywhiskey: Glad it worked :slight_smile:

For your question of changing the goal actor/location, I probably would not do that in the pathfinding function itself. Iā€™d run pathfinding as usual, and then loop over the returned tiles to find the desired target. You could do this in the AI controller. The Pathfinding function outputs the CanMoveToArray and IndexCanMoveToArray among others. The CanMoveToArray is the size of the entire grid, while the IndexCanMoveToArray only contains the tiles found in the previous pathfinding function.

For finding a specific tile Iā€™d do a for loop with break on the IndexCanMoveToArray, check the cost value of each array element against the desired index value, and break the loop and return true if the grid index is found. If it returns true, we know that the grid index is within movement reach of whatever unit last ran the pathfinding function, at which point we can order said unit to move to this index.

Ahh, thank you ! That makes a lot of sense. Thanks for the explanation.

Apologies for all the questions, but I ran into another one as a result of moving to a runtime grid generation system.
So Iā€™ve made a Tile_Wall duplicate actor and added a bunch of functionality to essentially turn it into a unit factory. When I click on a Widget I put on top of it, a friendly guy spawns at the index in front of it. No issues there.

But the Tile_Wall can be walked through / into ingame, even though the edge costs are all 0 which should make it a blocker. Iā€™ve made sure all the stuff in the construction scripts is copied over into the event graph and called when the tile is spawned, and it correctly snaps to its nearest tile and assigns that value to the ā€œIndexā€ variable. But it still can be passed through and walked into. Not sure if thereā€™s an additional step I should be taking to make sure it talks to the pathfinding ā€“ any ideas?

Anyways, thanks again for the help my man. I hope I havenā€™t been too annoying with all these questions :slight_smile:

@ienjoywhiskey: Donā€™t worry, Iā€™m not bothered at all. This is something Iā€™d like to support in the future, so thinging through it all now is helpful to me as well.

So the way walkability works in ATBTT is through an array containing the ā€œedgesā€ of all tiles. The Edge Array is a grid sized array of arrays, where each nested array cointains a struct saying which tile a tile is connected to and what its movement cost is. If the Edge Array is not manipulated when you place a unit factory, the pathfinding will ignore it. If your unit factory is a child of the Tile blueprint you can use the function Spawn Tile in BP_GridManager, which will automatically update the edge array with the edge values contained in the tile actor. Try doing this and see if it works.

I
Ohhh, I didnā€™t know there was a Spawn Tile function already set up! I should have looked for that. Yep, works perfectly. Thanks again, you rock!