Search Unity

[RELEASED] Turn Based Strategy Framework

Discussion in 'Assets and Asset Store' started by michal-zetkowski, Jul 2, 2019.

  1. Megalogue1

    Megalogue1

    Joined:
    Dec 17, 2020
    Posts:
    134
    The next stage of my project needs the new AI functionality, so I'm on the edge of my seat!
     
    michal-zetkowski likes this.
  2. Liberation85

    Liberation85

    Joined:
    Apr 16, 2019
    Posts:
    65
    @michal-zetkowski got a few questions for you.

    1. Will the new version allow cells and units to have 0,0,0 rotations, ie flat as opposed to everything being on the 90 degree angle?

    2. I would like to be able to stop units from entering or exiting tiles from certain directions.

    upload_2021-12-18_12-53-15.png

    So green being valid paths, red not allowed. I was thinking of having 6 bools for directions on the cells, but I'm not sure how I would implement this with get neighbour.

    Any ideas?

    EDIT: Think I might of sussed this.
     
    Last edited: Dec 18, 2021
  3. Neil2TheKing

    Neil2TheKing

    Joined:
    Sep 14, 2017
    Posts:
    15
    Liberation85 For your use case I recommend adding a height parameter to the cell class and modifying the GetNeighbors function. Essentially set the height of each cell to 0, 1, 2 etc. Then in the GetNeighbor method change it so that a cell is added as a neighbor if the neighbor's height is within 1 of the original cell. So for example if you are on a cell with height 2, then cells with heights 1-3 get considered neighbors.
     
  4. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
  5. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282

    Attached Files:

  6. BehindScheduleDev

    BehindScheduleDev

    Joined:
    Apr 29, 2021
    Posts:
    2
    I just tried updating my TBS framework in my unity project to 2.1. The update succeeded, but I am not seeing the new scripts and the FAQ file is still saying 2.0.1. Am I doing something wrong or is there some place I need to look besides the TBS Framework folder for the new scripts?
     
  7. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Hey, I just tested it and it works fine for me. Can you see the updated files in the import window? Why don't you try importing it into a fresh project?
     
  8. pzolla

    pzolla

    Joined:
    Apr 21, 2020
    Posts:
    19
    Worked ok for me. I was able to pull in 2.1 and compile without error the new scene 5
     
    michal-zetkowski likes this.
  9. BehindScheduleDev

    BehindScheduleDev

    Joined:
    Apr 29, 2021
    Posts:
    2
    Looks like after manually deleting my TBS Framework folder then re importing the issue is fixed.
     
    michal-zetkowski likes this.
  10. Liberation85

    Liberation85

    Joined:
    Apr 16, 2019
    Posts:
    65
    I did use something like this, it's more directional based rather than just height, so I numbered each side of a hex and checked which ones matched with the neighbouring tile and didn't include them. It was a bit janky at first but I got it working pretty well in the end.

    @michal-zetkowski Well.. New update! Certainly worth the wait, the new features are excellent although will take some reading to get my head around fully. But the modular system is really nice. Great work mate, this is awesome.

    Also, looking at how the factories work in example 4, this same idea could be used for a pregame deployment, with the deployable areas being units (like factories), spawn a unit on top of them and then destroy them when the 1st game turn begins.

    Cracking stuff, really excited.
     
  11. GermiyanBey

    GermiyanBey

    Joined:
    Aug 18, 2017
    Posts:
    68
    I am dreaming if Hexes in TBS could be created in a way more relevant to terrain instead of 'always-flat-surface' limitation. But maybe I am dreaming so much, yet maybe this can be considered as a user suggestion for the future.

     
    Last edited: Dec 22, 2021
  12. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    @Liberation85 Thanks, really happy to hear that people like the update, getting a lot of positive feedback.

    About unit deployment, you got that right. I implemented it in a simillar manner in one of the projects I co-worked on in the last few months. The unit that I used for deployment was just a button that triggered unit selection menu and spawned selected unit when a cell was clicked on. Kind of awkward to have to add Unit script to such object, when it is just the ability that I need. I'll try to come up with some way to make it feel more intuitive.

    @GermiyanBey In one of the projects I worked on I made the grid "project onto" a terrain. I will probably perfect this solution and include it in one of the updates, don't hold your breath though :)
     
    Liberation85 likes this.
  13. PolygonPros

    PolygonPros

    Joined:
    Apr 11, 2020
    Posts:
    34
    Questions about grids: I see that XY is the default for 2D, and XZ is the default for 3D. So...

    1) Is it possible to easily change these settings, if I want a grid to align to XY in a 3D game? For example, like a fighting game where characters can move forward and back and jump, but on a grid (see attached image)

    2) Is it okay/possible to create and use a 2D grid in a game that uses 3D characters/animations/environments/etc., as long as all unit movement sticks to XY coordinates?

    Thank you!
     

    Attached Files:

  14. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Hey :)

    1) The short answer is YES, in Grid Helper you can select to generate the grid in XY orientation (regardless if you're using sprites or 3D models). The game will be playable.

    Longer answer is that in Grid Helper you can select what orientation you want to generate the grid in. If you use tile based cells with 2D colliders, only XY will work (2D colliders don't work with XZ). If you use 3D models, XZ will be the better choice (you'll have issues with methods like transform.LookAt in XY). That being said, I'm not entirely sure how the game that you mention will work so I can't predict what other issues you might get. Let me know if you have more questions.

    2) The short answer is, YES, it works :) Take a look at the screenshots.
     

    Attached Files:

    • scr3.png
      scr3.png
      File size:
      385.8 KB
      Views:
      335
    • scr1.png
      scr1.png
      File size:
      411.4 KB
      Views:
      325
    • scr2.png
      scr2.png
      File size:
      318.6 KB
      Views:
      327
    PolygonPros likes this.
  15. Megalogue1

    Megalogue1

    Joined:
    Dec 17, 2020
    Posts:
    134
    Hi Michal,

    I've been getting acquainted with the update, and I noticed that the Cell class no longer has a CurrentUnit property. It does, however have a CurrentUnits property, which is actually a List<Unit>. What's going on here? Is there still a way to check what unit is on a cell at any time? And when I spawn a unit during runtime, do I need to manually tell the target cell what unit is being placed there? As in,
    cell.CurrentUnit = unit;
     
  16. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Hey,

    The idea is that there can be more than one unit on a given cell at the same time. If in your scene there's just one unit on any cell, you can reference it simply like this:
    Code (CSharp):
    1. if(Cell.CurrentUnits.Count > 0)
    2. {
    3.    var currentUnit = Cell.CurrentUnits[0];
    4.    //Do something with currentUnit
    5. }
    When spawning on runtime, use
    Code (CSharp):
    1. Cell.CurrentUnits.Add(SpawnedUnit)
    Let me know if you have more questions :)
     
  17. Megalogue1

    Megalogue1

    Joined:
    Dec 17, 2020
    Posts:
    134
    Thanks for the quick reply!

    I actually came up with that question while trying to make my unit spawning function work in the new update. I don't need anything fancy--basically just a function that works exactly like the unit painter, but during runtime. I need to be able to pass in a Unit prefab, a set of coordinates, and a player number, and a unit will be created. It will immediately be able to move, attack, etc.

    But the function I'm using isn't working right. The unit is instantiated and positioned fine, but when I click on it, nothing happens. It's unable to move or do anything. I confirmed that my unit class itself is set up correctly by using the unit painter outside of play mode to instantiate the same unit prefab in the scene. The unit created by the painter works just fine.

    Here's the function I'm using:
    Code (CSharp):
    1.  
    2.     private void SpawnFriendly()
    3.     {
    4.         Cell cell = helper.GetCellAt(7, 7);
    5.         Unit unit = Instantiate(unitPf, cell.transform.position + Vector3.back, Quaternion.identity, unitsParent);
    6.         unit.PlayerNumber = 0;
    7.         unit.Cell = cell;
    8.         cell.IsTaken = true;
    9.         unit.Initialize();
    10.         cell.CurrentUnits.Add(unit);
    11.         helper.CellGrid.AddUnit(unit.transform);
    12.     }
    The name "helper" refers to a CellGridHelper class I use. Among other things, it allows me to grab a reference to any cell based on its coordinates, as seen here. It also holds a reference to the CellGrid in the scene, and I use this reference to call the AddUnit function.

    And the TestUnit script I have on the unit prefab is just an empty class that implements Unit:
    Code (CSharp):
    1. public class TestUnit : Unit
    2. {
    3. }
    What's missing in my SpawnFriendly function that prevents the created unit from working right?
     
  18. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    I assume that your unit prefab has MoveAbility and AttackAbility attached to it, right? (I guess it does if it works when spawned in edit mode, just want to double check)

    Is the unit able to move on the next turn after it is spawned? If it does, this is an issue with the new Turn Resolver. The resolver selects the next player and what units can be used in given turn. By default, the Grid Helper adds SubsequentTurnResolver to cell grid when generating the map.

    When the turn starts, SubsequentTurnResolver selects all units that belong to given player, and only those units will be allowed to be used this turn. A unit that was spawned during the turn will not be included in the list.

    For now, the fix would be to make CellGrid.PlayableUnits field public and add the unit to this list from your spawn method.

    I'll be collecting feedback from users and probably in a couple of months I'll release a minor update with some tweaks. I would appreciate if you could share some insights after playing around with the update for some time :)

    Regarding a permanent fix for this particualr issue - how about TurnResolver returning a function instead of a static list of playable units? The function would create a list dynamically, this way units spawned during the turn could be included.
     
    Deleted User likes this.
  19. Megalogue1

    Megalogue1

    Joined:
    Dec 17, 2020
    Posts:
    134
    EDIT: Forgot to mention--yes, just like you predicted, the spawned unit is able to move on the next turn.

    I'm still a beginner programmer, all things considered, so I'm not exactly sure what you're talking about in your last paragraph. From my less experienced perspective, I would honestly like to see a simple ForcePlayableUnitsUpdate() function or something like that. Something that can be called from the outside at any time to force an update to the PlayableUnits list. That way you don't have to expose the list itself, but users also aren't forced to wait until the next turn for units to become playable.

    I also think it would be good to have some kind of UnitSpawnHandler somewhere in the framework. This is something I've wanted since I started using TBS. As far as I can tell, right now, I have to go through a lot of steps manually just to spawn a unit during runtime. Set the unit's position, tell it what cell it's on, set that cell's IsTaken field, etc. Wouldn't it make sense to have all of this taken care of within the framework already? Seems like spawning units during the game would be a common enough need that it would be worth the addition.
     
    Last edited: Dec 25, 2021
    michal-zetkowski and PolygonPros like this.
  20. Megalogue1

    Megalogue1

    Joined:
    Dec 17, 2020
    Posts:
    134
    My next issue: I want players to be able to switch between different battlefields at any time. For instance, suppose there are 5 sectors available to fight in, and the player decides to view sector 1, then sector 3, then sector 2, etc.

    I tried a naive approach first--a ClearBoard() method that simply loops through all children of the Units gameobject and destroys those units. Units are then spawned on the board according to data I stored for the sector previously. This makes it seem like the player has switched to viewing a different part of a larger battlefield, but without actually using different instances of CellGrid.

    This doesn't work well with the framework, though. After the first time I switch to a different sector and try to end a turn, I get a null reference error on this line of CellGrid.EndTurn():
    Code (CSharp):
    1. PlayableUnits.ForEach(u => { u.GetComponents<Ability>().ToList().ForEach(a => a.OnTurnStart(this)); u.OnTurnStart(); });
    It's one of those errors that complains about trying to access an object that's been destroyed.

    It's pretty clear that this is caused by the naive approach in my ClearBoard() method. Can you think of a better approach to this? I don't think I can just use separate scenes for different sectors, because the sectors are randomly generated, and there's no way to know ahead of time how many there will be.
     
  21. Liberation85

    Liberation85

    Joined:
    Apr 16, 2019
    Posts:
    65
    @michal-zetkowski Something I've noticed so far is that the MarkAsReachableEnemy works a bit different,

    If you're in range of a attackable enemy the unit highlighter changes colour as expected, however unlike the previous version it doesn't show you this when the unit is selecting a path.

    Pictures are worth a 1000 words and all that.

    upload_2021-12-26_12-26-38.png
    Previous version, green line indicating the different range from the path point.

    upload_2021-12-26_12-28-42.png
    New version, showing that MarkAsReachableEnemy is not being used with the path system.
     
    GermiyanBey likes this.
  22. PolygonPros

    PolygonPros

    Joined:
    Apr 11, 2020
    Posts:
    34
    Thank you very much for the prompt answers!

    Okay, so it sounds like I should use tile based cells with 2D colliders on the XY plane, with 3D models representing the characters, like in the screenshots you attached.
     
  23. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    @Megalogue1 How about deactivating unit gameobject instead? I'll think about your use case
    @Liberation85 Yes, that's because MoveAbility and AttackAbility are completly separated now, which is good. I didn't want to have any references to one another in any of them.

    Instead, check out this new ability (also replace MoveAbility, I had to expose one field there). Let me know if it works.
     

    Attached Files:

    Liberation85 likes this.
  24. Liberation85

    Liberation85

    Joined:
    Apr 16, 2019
    Posts:
    65
    michal-zetkowski likes this.
  25. Megalogue1

    Megalogue1

    Joined:
    Dec 17, 2020
    Posts:
    134
    Hey, I might have found a small bug. It seems that if you create a basic scene with the GridHelper and then call EndTurn before creating any units, the editor freezes.
     
  26. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Confirmed :) Thanks.
     
    Megalogue1 likes this.
  27. Megalogue1

    Megalogue1

    Joined:
    Dec 17, 2020
    Posts:
    134
    Also, for my battlefield-switching mechanic, I liked your idea of deactivating GameObjects, instead of destroying them. So I'm keeping them in a pool, only setting them active when they're "spawned" on the board. They also get set inactive when killed by an attack, instead of being destroyed.

    I think it's a step in the right direction. But now I have a different problem. The whole idea of the pool is that I can keep recycling the same units whenever a "new" one needs to be spawned in. But now, when my friendly unit is killed, it doesn't work properly when recalled from the pool. I try to spawn it back in as a different unit, but it's no longer clickable.

    Any suggestions here? What's the proper way to reset a unit to the way it was before being killed?

    EDIT: On second thought, I think I'm fighting against the framework a bit too much here. So many parts of it assume that when a unit is killed, the gameobject is destroyed. I think I should just let that happen, instantiate new units when needed, and only use the pool for objects that don't get destroyed.
     
    Last edited: Dec 30, 2021
  28. GermiyanBey

    GermiyanBey

    Joined:
    Aug 18, 2017
    Posts:
    68
    I have a different approach in spawning. When I create the Grid + Units the first time, I spawn the max number of Units via Grid Helper. The prefab unit you spawn should have their Mesh Renderers off, but they can work as placeholder for the units (I removed their Capsule Collider of Example1 units, instead added Mesh Collider and Mesh is a Hex that is a little up, so it can be clicked with mouse instead of cell Hexagon on the below).
    Then, when I want to spawn Game units, I spawn them as Child of what were already generated as units. If they die, I call the method OnDestroyed() of Unit.cs (Actually, I duplicated it as public void, I use it that way). And I edited it further, I don't destroy the object but Turn it Off or keep the units died on the battlefield (after death animation plays, they stay in their places without removing bodies).

    Long story short, maybe you can make use of vanilla Units and instantiate your units as child objects under them. So visually, only what you instantiated will be seen, not the framework Units (you make them transparent). I hope I explained my point well.
     
    Megalogue1 likes this.
  29. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Hey, I wouldn't drop that idea this easily. I don't know what modifications you made and what is your gemplay mechanism, but my guess is that the unit that "died" gets removed from CellGrid.Units list and because of that it is never considered a playable unit again (therefore not clickable)

    If you could export your project, send it to me by email and describe what exactly you're trying to achieve, I'll check it out.
     
  30. Megalogue1

    Megalogue1

    Joined:
    Dec 17, 2020
    Posts:
    134
    To clarify, I didn't drop the multiple battlefield idea. I just decided to be a little more relaxed about the pooling. I got things to work pretty well by allowing the unit gameobjects to be destroyed like normal when killed, and only deactivating gameobjects when they're temporarily unnecessary (like if you go from a battlefield with 15 units to one with only 5). I also figured out that adding/removing things in the PlayableUnits list helps a lot.

    I always appreciate your willingness to dive into another person's project, though. You never know what kind of mess you might have to wade through. :)
     
    michal-zetkowski likes this.
  31. Megalogue1

    Megalogue1

    Joined:
    Dec 17, 2020
    Posts:
    134
    By the way, could you clarify the difference between HitPoints and TotalHitPoints? I see them both being set and used in different contexts. And am I missing a serialized field for hit points? The public field HitPoints doesn't have this attribute, so does that mean my hit points settings won't persist the next time I open Unity?
     
  32. Liberation85

    Liberation85

    Joined:
    Apr 16, 2019
    Posts:
    65
    Same deal as MovementPoints and movementPoints, so you always have a reference to the default value.

    Just have to be a bit mindful when doing save/load game stuff. See Unit.Initialize().

    I made some hardcoded values for those, seemed the quickest and easiest way to get round it.
     
  33. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
  34. Artyom203459

    Artyom203459

    Joined:
    Oct 5, 2021
    Posts:
    2
    Here I go again. I would like to ask if I want to change the quad grid in example scenario 4 to a hexagonal grid similar to the one in example 2 in the original version, how do I do it? After I tried the conversion, I ended up not being able to move the units after clicking on them, and the attack range of the units is not normal
     
  35. GermiyanBey

    GermiyanBey

    Joined:
    Aug 18, 2017
    Posts:
    68
    Unfortunately Prefab replacing method is not working well with TBS. I was also frustrated by the exact same problem before. So, I strongly believe you have to manually remake the scene by using Grid Helper as a remedy. I know it is difficult, but I had to pass this stage too. I hope Michal can create a better convenience for Prefab Replacing.

    If Michal is interested, here I share my Prefab-Replacing script so he can test (After placing the script in an 'Editor' folder for it to work without problem, you can start using it via: Tools>Prefab Replacer on the top bar, then simply add the prefab you want to replace to the slot, then select the gameobjects you want to replace with.)

    For reproduction of the issue, replace current tiles (of an Example) with another tile prefab by using the script I provided. Hit Play. Battle will play as @Artyom203459 reported, no unit movements + full attack ranges.
     

    Attached Files:

  36. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Can you post a screenshot of what you're trying to achieve? How exactly are you trying to convert the grid? Do you mean generating a new map using cell prefabs from Example2 and units from Example4?
     
  37. Untrustedlife

    Untrustedlife

    Joined:
    Apr 21, 2020
    Posts:
    78
    Megalogue1 and michal-zetkowski like this.
  38. Liberation85

    Liberation85

    Joined:
    Apr 16, 2019
    Posts:
    65
    Untrustedlife likes this.
  39. Untrustedlife

    Untrustedlife

    Joined:
    Apr 21, 2020
    Posts:
    78
    Thanks :D
    Steam release is on the 15th!
     
    Liberation85 likes this.
  40. dbugger

    dbugger

    Joined:
    Jan 10, 2013
    Posts:
    55
    I do not get how the "Selected" state for units work. Whenever I select a unit, it looks completely normal. And looking at the code, seems like that is the intended behavior.

    upload_2022-1-13_13-3-3.png

    Here we see the method that is called the instant that the unit is selected, but at the end of the method, we can see that it immediately get changed into either "Finished" or "Normal".

    My understanding of this is state is that it should be active from the moment the unit gets click on, until the moment it either a) cannot do anything else (finished) or b) another unit is selected (normal / friendly).

    Am I misunderstanding how this state works?
     
  41. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Wow, nice catch, thanks. Your understanding is correct. I don't know how I could have missed it, I played all the demo scenes countless times. It seems that removing the "else" part solves it.

    Let me know if you have more doubts.
     
  42. dbugger

    dbugger

    Joined:
    Jan 10, 2013
    Posts:
    55
    It does, but there are some behaviors, that I was wondering if they are also intentional.

    For instance, I have my units set with 2 movement points and 2 actions points. But if the unit takes 1 movement, and executes the 2 actions, the chance to realize the remaining movement point becomes unavailable. I realize that this is the case in many games, but would it be possible to be able to move, after executing the action.

    Also, I realize that after moving 2 tiles, the "finished" state does not get activated, even if there is actually no possibility of realizing any action (due to not having any enemy units in reach).

    I am guessing that the criteria that you are following to determine the "finished" state is "if all the action points have been consumed", no?

    EDIT:
    Another weird behavior, if I remove that "else". The "Selected" state is fixed EXCEPT when the unit is moving. During the transition, the unit gets highlighted again as "friendly". This is not intended, no?
     
  43. Tadamkain

    Tadamkain

    Joined:
    Jan 4, 2022
    Posts:
    1
    Hi, I am completely beginner. I got acquainted with the tutorial and examples for a few days. I changed the parameters etc. Using the helper I learned Map square, but I can't hex. I am using hexagon .prefab of example 1 to create 2d. I also tried the x90 rotation. I am asking for a hint of the branch. Written by google translator :)
     

    Attached Files:

  44. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Thanks for bringing this up :)

    The "finished" state is determined in the method that you quoted before (CellGridStateAbilitySelected.OnStateEnter). In the method there is a loop that iterates over all unit abilities and checks if they can be used, the result is stored in canPerformAction field. If no action can be performed, unit is marked as finished.

    Going back to your example: check out MoveAbility.CanPerform method. The method return false when there are no action points. This is why you cant move after all action points are spent (also check out MoveAbility.Act, it checks for action points again, I guess I should use CanPerform directly in Act method)

    I tried moving units to a field where they can't attack from and they are marked correctly. Could it be the case that your unit has some other abilities attached to it that still can be used?

    Regarding the selected state, you are correct, I was able to reproduce it. It is not intended, I'll fix it in the next update.

    Let me know if it cleared things up :)
     
  45. dbugger

    dbugger

    Joined:
    Jan 10, 2013
    Posts:
    55
    Thanks, it cleared things up.

    Another issue that I have seen is the "Speed Turn Resolver". It sounds like something that takes the speed of a unit as parameter, to determine what is the next unit that should move, but that does not seem to be EXACTLY the case. What this resolver seem to do is to use the "Speed" as some sort of "priority" value, and the order in which the turns are sorted repeats itself over and over, always.

    For instance, let's say that I have a unit "Swordman" with speed 10, and a "Knight" with speed 50.

    The knight is 5 times faster than the swordsman, so it should really have 4 or 5 turns before the swordsman can move. Something like this:

    #1 - Knight
    #2 - Knight
    #3 - Knight
    #4 - Knight
    #5 - Knight
    #6 - Swordsman
    #7 - Knight
    #8 - Knight
    #9 - Knight
    #10 - Knight
    #11 - Knight
    #12 - Swordsman

    But this is not really what happens. Instead what we got is this:

    #1 - Knight
    #2 - Swordsman
    #3 - Knight
    #4 - Swordsman
    #5 - Knight
    #6 - Swordsman

    Which means that "Speed" is not really speed. Like I said, it seems more of a "priority" in the turn order, that repeats itself indefinitely.

    Is this the expected behavior?
     
  46. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Hey, rotate the prefab -90 degrees on X axis and change the return value from GetCellDimensions to new Vector3(2.2f, 1.9f, 1.1f);
     
    Tadamkain likes this.
  47. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Well, you got me again... I guess I misunderstood how speed system should work. I'll change the name to priority resolver and implement it properly next time.
     
    PolygonPros likes this.
  48. dbugger

    dbugger

    Joined:
    Jan 10, 2013
    Posts:
    55
    In case you are interested, I already did it. I made my base class "TamaUnit : Unit", which has a "RemainingCooldown" to know how long until its turn come, and also a method "AddTurnCooldown" to increase its cooldown, once its turn is consumed. How this method works I guess it would change for every game, depending on how you calculate the "TurnCooldown" amount.

    Feel free to use it as inspiration.

    And by the way, be careful with changing the name of a MonoBehavior, it may break things for people who have been already using it, if they do an update.

    By the way, have you thought of a Discord server for support?

    Code (CSharp):
    1.  
    2. using System.Collections.Generic;
    3. using System.Globalization;
    4. using System.Linq;
    5. using TbsFramework.Grid;
    6. using TbsFramework.Grid.TurnResolvers;
    7. using TbsFramework.Units;
    8. using TMPro;
    9. using UnityEngine;
    10.  
    11. namespace TamaTactics
    12. {
    13.     public class BattleTurnResolver : TurnResolver
    14.     {
    15.         private List<TamaUnit> units;
    16.    
    17.         public override TransitionResult ResolveStart(CellGrid cellGrid)
    18.         {
    19.             cellGrid.Units.ForEach(u => u.UnitDestroyed += OnUnitDestroyed);
    20.        
    21.             units = new List<TamaUnit>(cellGrid.Units.Cast<TamaUnit>());
    22.             units.Sort((unit1, unit2) => unit1.RemainingCooldown >= unit2.RemainingCooldown ? 1 : -1);
    23.  
    24.             return ResolveTurn(cellGrid);
    25.         }
    26.  
    27.         public override TransitionResult ResolveTurn(CellGrid cellGrid)
    28.         {
    29.             var nextUnit = units.First();
    30.             var timeToTurn = nextUnit.RemainingCooldown;
    31.             units.ForEach(unit => unit.RemainingCooldown -= timeToTurn);
    32.  
    33.             units.RemoveAt(0);
    34.             nextUnit.AddTurnCooldown();
    35.  
    36.             var index = units.FindIndex(x => x.RemainingCooldown > nextUnit.RemainingCooldown);
    37.             units.Insert(index < 0 ? units.Count : index, nextUnit);
    38.  
    39.             var nextPlayer = cellGrid.Players.Find(p => p.PlayerNumber == nextUnit.PlayerNumber);
    40.             var transitionResult = new TransitionResult(nextPlayer, new List<Unit> { nextUnit });
    41.             return transitionResult;
    42.         }
    43.  
    44.         private void OnUnitDestroyed(object sender, AttackEventArgs e)
    45.         {
    46.             units = new List<TamaUnit>(units.Where(u => !u.Equals(e.Defender)));
    47.         }
    48.     }
    49. }
     
    Last edited: Jan 14, 2022
  49. dbugger

    dbugger

    Joined:
    Jan 10, 2013
    Posts:
    55
    What would be the best way to autoselect a unit (let's say the first one, of all the "friendly" ones), at the beginning of a turn?
     
  50. michal-zetkowski

    michal-zetkowski

    Joined:
    Mar 11, 2015
    Posts:
    282
    Thanks! Regarding Discord - I would probably need to close this forum thread, do you think Discord would be better?


    The cleanest way I can think of is subclassing HumanPlayer and selecting the unit in Play method.