Announcement

Collapse
No announcement yet.

[SUPPORT] Advanced Turn Based Tile Toolkit

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

  • replied
    Originally posted by leo bar View Post
    hi knut

    ok i get you

    but just for me to understand this - its doesn't make any sense for me. i stored the possible targets set the first time i run the node, so why cant i pull the data from the stored set and instead have to run the all function again?
    why it is not acting like any other variable that you store?is it because it a set?

    anyway thanks for the help

    leo
    You should only have to run it once, so if you are not overriding the Activate or PlayerActivate events calling these nodes again should not be necessary. Maybe you could post a pastebin of the Activate nodes for your custom ability?

    Originally posted by Justo View Post
    Added time stamps to the 3rd Action video in the comments. After rewatching the Action System set of videos, here are the notes I made, in case anyone finds it useful. I like having huge docs and Ctrl+Fing around when I feel like I need refreshing on certain topics. When there's a wiki I can start filling some of those entries with this if you wish Knut. If anyone finds anything wrong, you're more than welcome to correct me guys; I'd love the knowledge. I will update this post with any corrected info.

    I will also take this opportunity to ask you more Qs Knut, on what these videos talked.
    Much appreciated! I'll go through your points and see if I want to make any interjections.

    Originally posted by Justo View Post
    Event MoveToIndex

    -Is generally called from Movement Abilities.
    -Will simulate unit movement behind-the-scenes and then queue an action to animate this.

    Outputs:
    • IndexPathEnd is the destination index where the unit wants to move to.
    • PathsMap is the output of a pathfinding function.
    Yup, you got it right.

    Originally posted by Justo View Post
    Function SimulateMove

    1-Any explanation on this function somewhere? It would be great if you could take us through this function graph and explain us what exactly is happening.
    2-What is the "New Actions Count" output?
    3-It does everything under the hood using a "reference" of the unit. What is this reference exactly?
    I guess I haven't covered this one yet. Might be good to do when I make my pathfinding tutorial. The basic purpose of this function is to move the unit reference between GridUnits indexes and check for any events that happen along the way, including adding and re-adding units to multiple tiles for big units and calling an event dispatcher every tile move. NewActionsCount keeps track of any actions that happen during movement. This can be useful if you have new actions that are called during movement. For instance, if you want to have the unit trigger an explosive half way through its movement you cannot have the whole move action play out and then play the explosion at the end, or the other way around. With this variable you have a way of knowing that new actions have been added to the queue.

    Originally posted by Justo View Post
    Macro QueueAction

    Outputs:
    • Immediate Action: Decides whether the action should be executed and animated immediately, or stacked at the bottom of the action queue if set to false. Most actions have this boolean set to false.
    • Executing Object: Defines the object that should execute the action.
    • Action name: All actions have one. These are used to let other functions identify specific actions and decide how to act accordingly.
    • Instant Deactivate: Decides whether the action is instantly considered as 'Done' by the Action Manager as soon as it starts and if it's okay for the next action to roll out. Usually set to false for actions that are to be animated, since normally animations would play out first and then let the game continue.
    • At Custom Index: 4-In the videos you skipped this one, other than saying it is only used in the MoveToIndex function?
    • With Previous: Decides whether this action should be played simultaneously with the one before it.
    • Activation Delay: How much time should be waited until this new action is activated, from the moment the previous action ended.
    Well explained. For AtCustomIndex, by default an action will be added to the end of the array of actions. If you specify a custom index you can put it earlier in the ordering of actions. For movement, where queuing the movement action is called after SimulateMove (where other actions might be called), but you want movement to start before these actions trigger, this is handy.

    Originally posted by Justo View Post
    Event AnimateAction

    -This event is generally called from the Action Manager. When an action that needs to be animated comes to the top of the Queue, a signal is sent to the Executing Object (defined in the QueueAction macro) to execute this event.
    -This event is contained within BPI Action. Therefore, every BP that should be animated by the action system should have this BPI added.
    -This event is multicast, meaning it is run on every client and should automatically work for displaying correctly in Multiplayer.
    Yep, all correct.

    Originally posted by Justo View Post
    -(Not too sure on this...) In order to save memory and help prevent cheating, it is a good practice to not include any Grid Manager-centered functions in the BP Units, like pathfinding math. It is better to use location vectors instead of grid indices to animate actions for example, because this way there is no need to call upon Grid Manager functions to process the index data.
    Not really a problem for performance. There are a couple of issues with doing game logic type stuff within actions. This stems from how things happen asynchronously. If a unit is killed, for instance, it is instantly removed from the GridUnits TMap. If you then try to access this index during the action where it is killed, it has already been removed, causing the code to fail. If you only work with variables that represent the "plysical" game world, such as locations, actors etc. you can be sure you never have this sort of mismatch. Also, since game logic stuff, such as most of the grid manager stuff, is not replicated, accessing these variables will fail for clients in multiplayer.

    Originally posted by Justo View Post
    [5-In the Teleporter video, grid indices were used extensively in the same Teleporter's Event Graph. Even though it was done in the Teleport Event and not the Animate Action Event, is it not using memory and enabling cheating now just as much as if it was used in the Animate Action event, contradicting this last statement?
    This was lazy of me and I regret doing so, as it is teaches bad practice. As long as you have a perfect overview of how server-side stuff is handled by the toolkit you can get away with using it in actions in some cases for single-player games. That is if you can be sure it will not be manipulated in such a way that there will be a mismatch. I would generally recommend against this, though, and should not have done so in a tutorial.

    Originally posted by Justo View Post
    [Event AnimateMovement

    -Units move through a set of spline points that are generated by the Set Spline Points function, which does so using the given path locations.

    Action Manager
    Event(s) Multicast & InitializeQueuedActions:

    -These events are called periodically throughout the game, generally at the end of the unit's turn.
    -It empties the temporal array filled by QueueAction macros, sending it to all clients and appending it to the CurrentActions array. After this, each client then starts the first action and plays through them in turn.
    Yep

    6-Why is there a need to have two events here? The Multicast event is never even called by other BPs so there is no need to separate it as a function from initializeQueuedActions. Is this due to the way Multiplayer needs client & server communication be written, or just an author's coding habit?[/QUOTE]

    There are two events because the first part of the event (which sorts through actions and stores them in lists) only works server-side, so no need to call it client-side.

    Originally posted by Justo View Post
    Event Dispatcher onUnitEndMovementSimulate

    -An event dispatcher that activates when any unit ends its movement during simulation. It is called at the end of the unit's movement, the Simulate Move function.
    Indeed. Useful if you want stuff to happen at the end of movement.

    Originally posted by Justo View Post
    Other questions:

    8-(Video 3/3; 14:45) You use GetActorLocation to obtain the Teleporter's coordinates, and later on (18:40) the Grid Manager's Grid Locations map, to obtain the grid index' center point. Isn't it faster and simpler to use the Grid Manager's ConvertIndexToLocation function for this?

    {"data-align":"none","data-size":"custom","height":"302","width":"590","data-attachmentid":1595485}
    Finding locations in a map uses UE4's built-in C++ functions and is really fast. Certainly faster than my blueprint function.

    Originally posted by Justo View Post
    9-(Video 3/3; 16:47) Why are only Copies available for the array elements of BP Units, and not References too, like with a vector or integer array?
    This is a C++ thing. For some types of variables it is preferable to create a copy in memory instead of pointing directly to its memory address. Epic have chosen to only allow passing variables referencing blueprints as copies. This is not something you can change in blueprints, but it will generally not matter.

    Originally posted by Justo View Post
    10-Grid Units is a Map array inside Grid Manager. It contains only the grid indices of units. This includes dead units too, right?
    No, they are removed from this array immediately on death. To the grid manager game logic a dead unit means a unit that is neither in the GridUnits TMap or the InitiativeOrder array. If a unit was kept in GridUnits after death, AI units would still try to target them with abilities, and units would not be able to move into the tile they died, for instance.

    Originally posted by Justo View Post
    11-In the BPI Singletons there is a typo in the GetActionManager function, where a "Get Action Manader" output is used.
    Thanks, I'll fix that in the next update.

    Thanks again for doing this. Among other things it helps make it clear to me what subjects I have covered well and what I should revisit in later tutorials. If you don't mind I'll post a link to your post in the description of the relevant video.

    Leave a comment:


  • replied
    Edit 19/03/2019: Completed first revision pass with Monokkel's answers

    Added time stamps to the 3rd Action video in the comments. After rewatching the Action System set of videos, here are the notes I made, in case anyone finds it useful. I like having huge docs and Ctrl+Fing around when I feel like I need refreshing on certain topics. When there's a wiki I can start filling some of those entries with this if you wish Knut. If anyone finds anything wrong, you're more than welcome to correct me guys; I'd love the knowledge. I will update this post with any corrected info.

    I will also take this opportunity to ask you more Qs Knut, on what these videos talked.

    Event MoveToIndex

    -Is generally called from Movement Abilities.
    -Will simulate unit movement behind-the-scenes and then queue an action to animate this.

    Outputs:
    • IndexPathEnd is the destination index where the unit wants to move to.
    • PathsMap is the output of a pathfinding function.

    Function SimulateMove

    This function primarily moves the unit reference between GridUnits indices and checks for any events that happen along the way. This includes adding and re-adding units to multiple tiles for big units and calling an event dispatcher every tile move.

    Outputs:
    • NewActionsCount: Keeps track of any actions that happen during movement. This can be useful if new actions are called during movement. For instance, if you want to have the unit trigger an explosive half way through its movement you cannot have the whole move action play out and then play the explosion at the end, or the other way around. With this variable you have a way of knowing that new actions have been added to the queue.

    Macro QueueAction

    Outputs:
    • Immediate Action: Decides whether the action should be executed and animated immediately, or stacked at the bottom of the action queue if set to false. Most actions have this boolean set to false.
    • Executing Object: Defines the object that should execute the action.
    • Action name: All actions have one. These are used to let other functions identify specific actions and decide how to act accordingly.
    • Instant Deactivate: Decides whether the action is instantly considered as 'Done' by the Action Manager as soon as it starts and if it's okay for the next action to roll out. Usually set to false for actions that are to be animated, since normally animations would play out first and then let the game continue.
    • At Custom Index: Specifies a custom order in the queue for the action. For movement, where queuing the movement action is called after SimulateMove (where other actions might be called), but you want movement to start before these actions trigger, this is handy.
    • With Previous: Decides whether this action should be played simultaneously with the one before it.
    • Activation Delay: How much time should be waited until this new action is activated, from the moment the previous action ended.

    Event AnimateAction

    -This event is generally called from the Action Manager. When an action that needs to be animated comes to the top of the Queue, a signal is sent to the Executing Object (defined in the QueueAction macro) to execute this event.
    -This event is contained within BPI Action. Therefore, every BP that should be animated by the action system should have this BPI added.
    -This event is multicast, meaning it is run on every client and should automatically work for displaying correctly in Multiplayer.

    -In order to prevent logic errors and player cheating, it is a good practice to not include any Grid Manager-centered functions in the BP Units, like pathfinding math. If a unit is killed, for instance, it is instantly removed from the GridUnits TMap. If you then try to access this index during the action where it is killed, it has already been removed, causing the code to fail. If you only work with variables that represent the "physical" game world, such as locations, actors etc. you can be sure you never have this sort of mismatch. Also, since game logic stuff, such as most of the grid manager stuff, is not replicated, accessing these variables will fail for clients in multiplayer.


    Event AnimateMovement

    -Units move through a set of spline points that are generated by the Set Spline Points function, which does so using the given path locations.

    Action Manager
    Event(s) Multicast & InitializeQueuedActions:

    -These events are called periodically throughout the game, generally at the end of the unit's turn.
    -It empties the temporal array filled by QueueAction macros, sending it to all clients and appending it to the CurrentActions array. After this, each client then starts the first action and plays through them in turn.
    -There are two events because the first part of the event (which sorts through actions and stores them in lists) only works server-side, so no need to call it client-side.


    Event Dispatcher onUnitEndMovementSimulate

    -An event dispatcher that activates when any unit ends its movement during simulation. It is called at the end of the unit's movement, the Simulate Move function.


    Other questions:

    8-(Video 3/3; 14:45) You use GetActorLocation to obtain the Teleporter's coordinates, and later on (18:40) the Grid Manager's Grid Locations map, to obtain the grid index' center point. Isn't it faster and simpler to use the Grid Manager's ConvertIndexToLocation function for this?

    Click image for larger version  Name:	bp10.jpg Views:	1 Size:	136.7 KB ID:	1595520
    Monokkel: Finding locations in a map uses UE4's built-in C++ functions and is really fast. Certainly faster than my blueprint function.

    9-(Video 3/3; 16:47) Why are only Copies available for the array elements of BP Units, and not References too, like with a vector or integer array?
    Monokkel: This is a C++ thing. For some types of variables it is preferable to create a copy in memory instead of pointing directly to its memory address. Epic have chosen to only allow passing variables referencing blueprints as copies. This is not something you can change in blueprints, but it will generally not matter.

    10-Grid Units is a Map array inside Grid Manager. It contains only the grid indices of units. This includes dead units too, right?
    Monokkel: No, they are removed from this array immediately on death. To the grid manager game logic a dead unit means a unit that is neither in the GridUnits TMap or the InitiativeOrder array. If a unit was kept in GridUnits after death, AI units would still try to target them with abilities, and units would not be able to move into the tile they died, for instance.
    Last edited by Justo; 03-18-2019, 09:26 PM.

    Leave a comment:


  • replied
    hi knut

    ok i get you

    but just for me to understand this - its doesn't make any sense for me. i stored the possible targets set the first time i run the node, so why cant i pull the data from the stored set and instead have to run the all function again?
    why it is not acting like any other variable that you store?is it because it a set?

    anyway thanks for the help

    leo

    Leave a comment:


  • replied
    Originally posted by leo bar View Post
    hi knut

    i did override the bp_ability

    i have the sprint ability which is my default ability, and its run the regular pathfinding + the FinVisibleUnitsInRange .i made another weapon ability in which i need the value from the possible targets. i dont want to run all over again the finvisibleunitinrange when i run my new ability(i modified it and its pretty big know) .the laser ability is not a good example, its not activate the same way
    no matter what i do, i get null from possible targets in my new ability.
    is there a way to fill it in another way?

    thanks in advance
    leo
    If you want to find possible targets you need to run the appropriate nodes for it. No other way around it. Just add the relevant code from BP_Ability to the end of player activate in your new ability and it should work. The size of a blueprint does not matter much, and a few more nodes should not make any difference.

    Leave a comment:


  • replied
    hi knut

    i did override the bp_ability

    i have the sprint ability which is my default ability, and its run the regular pathfinding + the FinVisibleUnitsInRange .i made another weapon ability in which i need the value from the possible targets. i dont want to run all over again the finvisibleunitinrange when i run my new ability(i modified it and its pretty big know) .the laser ability is not a good example, its not activate the same way
    no matter what i do, i get null from possible targets in my new ability.
    is there a way to fill it in another way?

    thanks in advance
    leo

    Leave a comment:


  • replied
    Originally posted by Locoweed View Post
    Hiya Knut,

    This might be in forum somewhere, but what do I need to set on the AI controlled units that makes every action finish before moving to next? When the AI is controlling units they attack while moving instead of attacking after move finishes, other AI units start moving before the current AI units have finished moving, etc. In my turn-based game I want every AI action complete before next starts. Unless I broke how the AI works somehow, which is possible. Maybe withPrevious, InstantDeactivate, or Immediate set somewhere in AI code?
    Thanks, Loco
    That is a bug and not a feature. It is likely that you are calling EndAction too many times somewhere in your code, causing the action system to skip to the next action before one is done. One of the most common culprits of this behavior is if you have set some of your unit's animation to looping, so that the end action notify keeps repeating. That is the first place I would look.

    Originally posted by leo bar View Post
    hi knut

    I'm trying to get access to "possible target" set from bp_ability to other ability I made, but for some reason I get noting in return. what am I missing?

    cheers
    leo
    By default, if you do not override Activate or PlayerActivate, BP_Ability uses FinVisibleUnitsInRange with the range defined in the ability to fill PossibleTargets. If you override this you'll have to fill it some other way. What are you doing at the moment?

    Leave a comment:


  • replied
    Good evening all,

    I am new to this forum, and just an hobbiyst, I am making (trying...) a game based on that superb turn based toolkit, but I am facing the same problem with touch input.As far as I only want to make it for android, i have an issue.

    My question is, how can I validate the move / attack using a button like the end turn. Hover is working fine, also the idea is we keep the position and validate with one button.

    I am sorry, but I didn't succes in making it.

    If you can help, I will appreciate a lot.

    Kind regards.

    Leave a comment:


  • replied
    hi knut

    I'm trying to get access to "possible target" set from bp_ability to other ability I made, but for some reason I get noting in return. what am I missing?

    cheers
    leo

    Leave a comment:


  • replied
    Hiya Knut,

    This might be in forum somewhere, but what do I need to set on the AI controlled units that makes every action finish before moving to next? When the AI is controlling units they attack while moving instead of attacking after move finishes, other AI units start moving before the current AI units have finished moving, etc. In my turn-based game I want every AI action complete before next starts. Unless I broke how the AI works somehow, which is possible. Maybe withPrevious, InstantDeactivate, or Immediate set somewhere in AI code?
    Thanks, Loco
    Last edited by Locoweed; 03-14-2019, 08:38 PM.

    Leave a comment:


  • replied
    Originally posted by Justo View Post
    Click image for larger version Name:	bp9.jpg Views:	1 Size:	40.1 KB ID:	1593499

    This is the internet ha, of course the community will tell you that. I don't know how wikis work to be honest - if possible I think whoever is allowed to edit should always have their content Awaiting Approval, or sth alike, from you, right? People (I for example) could make a honest mistake editing sth and until you come in and correct it yourself, someone else could have read that and went off misinformed to do who knows what devilry.
    Haven't made a wiki before, so I'm not 100% sure how it all works, but I think it should be a good fit. Having edits pending approval could be a good way to do things, but if it is possible it might be better to give the possibility to post freely, but to add a header signifying if I have read through it or not.

    Originally posted by Justo View Post
    Speaking of mistaken edits, if I heard you correctly what you just said was...
    Hehe, some slight misquotation going on there, but point taken. Making tutorials on the grid arrays is the most pressing, I think, and most support request I've gotten in the last couple of weeks are tied to such things. It is also a prerequisite to be able to explain the big unit functionality.

    Originally posted by Illusive_S View Post
    It does, i am trying to do that like in the photo, but it does not work. Is there something else im supposed to do?
    Good start, but some changes need to be done. The biggest issue is how edge costs are normally handled by the toolkit. The cost to enter a tile is stored in the tiles that can enter the tile (normally the tiles that surround it). So the GridEdges TMap for a single grid index really stores the cost it takes to leave the tile, but not to enter it. To do this you need to get all the surrounding tiles and modify their edges (using GetIndexesInRange, for instance). Then you would need to store the costs of all of these tiles before modifying them so you can restore these costs later.

    This is a tiny bit cumbersome, but not terribly difficult to set up. However, it becomes more challenging as soon as you have multiple corrupted tiles at the same time. Say you have two corrupter units that corrupt tiles that are adjacent. The first spawned corrupt tile modifies the edges of all surrounding tiles, which will overlap several tiles modified by the other corruptor's corrupt tile. When the second corrupt tile is spawned it stores the current state of the GridEdges TMap for all tiles, which includes those modified by the first corrupt tile. When it is destroyed it will thus use these values for the edges of surrounding tiles, meaning that the surrounding tiles that overlapped would never be restored to their original value.

    This is basically the same problem as I faced when I added big units to the game. These units modify a GridBigIndexes TMap whenever they move, and the tiles they modify in this fashion can be modified by multiple units at once, which might die or move in any order. I solved this through a fairly complex solution, where I also store the number of units that modify a specific tile and keep track of which units modify each tile in what way.

    As you see in your case this creates lots of complications for what should ideally be a pretty trivial thing to do (temporarily modifying the cost of a tile). Luckily for you I added a feature a few updates ago to simplify exactly these sorts of problems. If you set bUseSimpleCosts in BP_GridManager to true and set the PathfindingType of all your units to Simple it will allow you to use so called simple tile costs. These are a single integer for each tile that represents the cost of entering this tile from any direction (zero being impassable), and are stored within the relevant grid index itself and not the neighbors. If you use the Simple PathfindingType the cost of entering the tile will be whatever is higher of the cost stored in GridEdges and GridSimpleCosts. Now for your corrupted tiles you can quite easily modify the GridSimpleCosts TMap and hopefully get the result you are after.

    Since you aren't modifying tile costs in the normal way I would recommend basing your corrupted tiles on BP_GridActor (the parent of BP_GA_Tile) and not BP_GA_Tile. I tested this out, and here is how I set my corrupted tile up:



    I set the SimpleCost to ExposeOnSpawn and did the following to test if it worked:



    Note that if you have already activated a unit so that RunPathfinding has already finished and then add a corrupted tile it will not affect the current pathfinding, which was calculated with the state of the edge array when it was run. To have the corrupted tile affect the currently active pathfinding you would have to run RunPathfinding again.

    Hope this gets you close to what you're after. Note that if you want your units to modify specific edges and not the cost of an entire tile you'll have to go with the more complex solution outlined above.

    Leave a comment:

Working...
X