1. Find your way through the deepest dungeon in the 18th Mini Mapping Contest Poll.
    Dismiss Notice
  2. A brave new world lies beyond the seven seas. Join the 34th Modeling Contest today!
    Dismiss Notice
  3. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
Hive 3 Remoosed BETA - NOW LIVE. Go check it out at BETA Hive Workshop! Post your feedback in this new forum BETA Feedback.
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Unit region spawning, help me out!

Discussion in 'World Editor Help Zone' started by Kapharna, Aug 23, 2020.

  1. Kapharna

    Kapharna

    Joined:
    Feb 12, 2020
    Messages:
    29
    Resources:
    0
    Resources:
    0
    Hello!

    I am building an auto-battler map where your units spawn to fight in duels. It's a similar idea to Blood Tournament, but then actually playable and interactive. (still love BT)

    I want units to spawn on a certain region based on the current region it stands on, so players can swap and try out different stances.

    I already have unit variables and 64 regions for each player's spawning base. I can't seem to figure out how to spawn a unit based on its location. Do I have to do variable counting 64 times for each player?
    upload_2020-8-23_12-12-26.png
    <Player spawning base>

    upload_2020-8-23_12-13-24.png
    <Player duel area>

    So I want to mirror these regions, how do I do tha :))
     
  2. DoomBlade

    DoomBlade

    Joined:
    Feb 5, 2018
    Messages:
    383
    Resources:
    0
    Resources:
    0
    So, how many players do you have and how many duel areas do you have?

    At first what came to my mind is setting a region == for example the most top left corner. We will call it TopLeftRegion.

    And to make the regions indicate different things it will be TopLeftPlayerRegion and the other region will be TopPLeFtDuelRegion.

    If unit is in TopLeftPlayerRegion create 1 unit or move unit to --> TopPLeFtDuelRegion.

    But if the map only has one duel area and multiple players are dueling at the same time, this will not work.

    Or if it is mirrored then TopLeftPlayerRegion equals BotLeftDuelRegion.

    Hope this made some sense :D
     
  3. Kapharna

    Kapharna

    Joined:
    Feb 12, 2020
    Messages:
    29
    Resources:
    0
    Resources:
    0
    It's going to be an 8-player gamemode with 8 duel spawning areas. Each player will spawn on one of these areas, which is already set.

    I need the spawn to be based on a variable, as building unit X will give you for of these units. This variable is already set as well. (number of type-x units owned = variable.
    I think it will work. Let me try. I will comment here again how it succeeds or fails :))
    thanks for your help
     
  4. nedio95

    nedio95

    Joined:
    Mar 24, 2011
    Messages:
    1,060
    Resources:
    1
    Spells:
    1
    Resources:
    1
    You can use angle and offset from the corner ? and just modify the angle with 180 when spawning
    Or you can use distance from the corner ? and just reverse them when spawning

    regards
    -Ned
     
  5. [db]east

    [db]east

    Joined:
    Feb 27, 2019
    Messages:
    144
    Resources:
    0
    Resources:
    0
    Thats a great idea!
    Something like this then?
    Pick every unit in Player spawning base
    Set Dist = Distance from Unit to Point
    Set Angle = Angle from Unit to Point
    Set UnitTypeInt = Point Value of Picked Unit
    Create 1 UnitType(UnitTypeInt) for Player at PointDuel offset by Dist towards Angle.
     
  6. Uncle

    Uncle

    Joined:
    Aug 10, 2018
    Messages:
    2,483
    Resources:
    0
    Resources:
    0
    Here's a little something I threw together using everyone's ideas.

    It requires the latest patch to open. If you can't open it and you're interested I can post the triggers here.

    Basic idea:
    I use a Hashtable to save information regarding the Player's Regions/Units.
    -Each Player's Regions are saved in the Hashtable at 1 to X using their Player Number as the Key
    -Each Player's Region State (Region is Occupied/Unoccupied) is saved in the Hashtable at -1 to -X using their Player Number as the Key
    -Each Unit's current occupied Region # is saved in the Hashtable at 0 using the Unit as the Key
    X = Total number of Regions in a Player's base

    So using Kapharna's picture as an example and assuming that is Player 1's base:
    The top left Region would be saved as 1 of 1 (Player Number) in the Hashtable
    The Region to the right of it would be saved as 2 of 1 (Player Number) in the Hashtable
    This pattern continues from left to right, top to bottom.
    The bottom right corner Region would be saved as 64 of 1 (Player Number) in the Hashtable.

    Whenever a Unit enters a Region I determine which Region it was and save that Region # to the unit.
    A unit entering the top left Region of Player 1's base: Save 1 (Region #) as 0 of Key(Triggering Unit) in the Hashtable.
    A unit entering the bottom right Region of Player 1's base: Save 64 (Region #) as 0 of Key(Triggering Unit) in the Hashtable

    We can always save this data at the 0 Index in the Hashtable since we're saving this information directly to the Unit. This leaves room to use the other Indices for anything else you might like to save directly to the unit.

    Duel Arenas:
    When a Duel starts I Pick all units owned by a given player and then load those Unit's values in the Hashtable to get their Region #. With this information you can use Point offsets to determine where the units should be created inside the Arena. If a unit's loaded Region # is 1, then we know it was in the top left corner region, therefore when creating it in the Arena it should be in the top left corner as well.

    Here's an example of me setting up Player 1's position in the Arena:
    • Actions
      • -------- Setup First Player --------
      • Set VariableSet R_Player = Player 1 (Red)
      • Set VariableSet PN = (Player number of R_Player)
      • -------- Setup points --------
      • Set VariableSet X = 0.00
      • Set VariableSet Y = 0.00
      • Set VariableSet TempPoints[1] = (Center of Duel Top <gen>)
      • For each (Integer R_Loop) from 2 to R_Count, do (Actions)
        • Loop - Actions
          • Set VariableSet X = (X + 128.00)
          • Set VariableSet TempPoints[R_Loop] = (TempPoints[1] offset by (X, Y))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (R_Loop mod 3) Equal to 0
            • Then - Actions
              • Set VariableSet X = -128.00
              • Set VariableSet Y = (Y - 128.00)
            • Else - Actions
      • -------- Create units --------
      • Unit Group - Pick every unit in P_Units[PN] and do (Actions)
        • Loop - Actions
          • Set VariableSet R_RegionNumber = (Load 0 of (Key (Picked unit).) from R_Hashtable.)
          • Unit - Create 1 (Unit-type of (Picked unit)) for R_Player at TempPoints[R_RegionNumber] facing P_Angle[PN] degrees
      • -------- Clean up point leaks --------
      • For each (Integer R_Loop) from 1 to R_Count, do (Actions)
        • Loop - Actions
          • Custom script: call RemoveLocation (udg_TempPoints[udg_R_Loop])

    I'm using a 3x3 setup in my map, so there's 9 (R_Count) Regions in total per Player's base . That's why I loop from 2 to R_Count (9), and I skip 1 in the Loop since that's the starting point which is already set beforehand. Note that P_Angle is a Real variable that is set for each Player, this determines the Angle that the player's units are facing. This way opposing units in the Arena spawn facing one another.

    This line here may confuse some: (R_Loop mod 3) Equal to 0
    This is modulo, and it can be used to basically check if a number is a multiple of another number. So i'm checking if R_Loop is a multiple of 3, and if it is, I adjust my X/Y coordinates accordingly since we're now dropping down a Row.

    Unit Placement:
    My setup is a bit different than Blood Tournament, which I did on purpose. In Blood Tournament, you create Buildings with your Worker inside of your Base, which are then referenced and "recreated" in the Arena as normal Units.

    In my example, I figured why use Buildings and have to create an extra version of each Unit (Building Form/Unit Form) when you can just use the Unit form for everything. So you'll see that I made it very simple, just grab one of your units and right click (give it a move order) to some tile in your base, and if that tile is unoccupied, the unit will instantly move there and occupy it.

    I didn't bother making a system for creating these Units, but you could easily come up with something. For example, you buy your Units from a Barracks, which moves them to a Unit Pool area. From there, you can select them and right click where you want to place them. This would be A LOT more hands on in my opinion, and would make moving/adjusting the units positions extremely easy.
     

    Attached Files:

    Last edited: Aug 26, 2020
  7. Kapharna

    Kapharna

    Joined:
    Feb 12, 2020
    Messages:
    29
    Resources:
    0
    Resources:
    0
    (Typing from mobile phone sorry)
    All I know now is that I know nothing xD! I am very happy with all your replies. I am not fimiliar using Hashtables, which soubds like something I could use well and could save me a lot of time too.

    Now I sort of managed to create my spawning trigger to function well. I am going to show the example of spawning levy footman in the topleft of the arena. When you build 1, you will get 4 in the arena. I did the following:

    Needed: regions on map, integer variables.

    Trigger 1:
    Event: Every 1 seconds of game time..
    Action: Set LevyFootman_Region1_1(integer array) for player 1 = number of Levy Footman Units in P1_row1_1 × 4

    Trigger 2:
    Event: Timer expires..
    Action: Spawn LevyFootman_Region1_1 Levy footman units for player 1 at region Arena1_1

    ---

    This is the way I get it working, but the complication is that every different unit needs a different variable for every region which is 64. That is going to be a LOT of triggers. Think this is an okay way of doing things or should I try and do one of your suggestions? In that case I need some discord live aid :))
     
  8. Uncle

    Uncle

    Joined:
    Aug 10, 2018
    Messages:
    2,483
    Resources:
    0
    Resources:
    0
    For the sake of your own sanity I highly recommend avoiding any cases of stuff like this: P1_row1_1

    Your variables should be Arrays and your triggers should be setup in a way that you can just plug in the Player Number in the Index of the Array and get the results you want.

    Also, I could help you on Discord if you'd like. I'm on the Hiveworkshop discord, username is Uncle.

    So here's an example of setting up Unit Types and Unit Count:
    • Setup Unit Types
      • Events
        • Map initialization
      • Conditions
      • Actions
        • -------- Set this to the total number of Unit-Types --------
        • Set VariableSet TotalUnitTypes = 3
        • -------- Footman --------
        • Set VariableSet UnitType[1] = Footman
        • Set VariableSet UnitCount[1] = 6
        • -------- Rifleman --------
        • Set VariableSet UnitType[2] = Rifleman
        • Set VariableSet UnitCount[2] = 4
        • -------- Knight --------
        • Set VariableSet UnitType[3] = Knight
        • Set VariableSet UnitCount[3] = 2

    Now that this information is saved in an Array, it can be referenced with a For Loop. Something like this:
    • Actions
      • -------- PN = Player Number --------
      • Set VariableSet PN = 1
      • Unit Group - Pick every unit in Player_Units[PN] and do (Actions)
        • Loop - Actions
          • For each (Integer Loop) from 1 to TotalUnitTypes, do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Unit-type of (Picked unit)) Equal to UnitType[Loop]
                • Then - Actions
                  • Unit - Create UnitCount[Loop] UnitType[Loop] for Player at Point facing Angle degrees
                • Else - Actions

    ^ In this example I am picking every unit in our designated player's Unit Group. This Unit Group contains the units that the player has trained/constructed so far.

    What happens in the Loop:
    For each Picked unit it loops through ALL of the possible UnitTypes[], comparing them to one another. Once the condition is met "(Unit-type of (Picked unit)) Equal to UnitType[Loop]" we will know the Index of the picked unit, which will be equal to Loop. This gives us access to UnitCount[Loop], which tells us how many of this unit we should create. So using the Knight as an example, in it's case Loop will be equal to 3, and since UnitCount[3] is equal to 2 it will spawn 2 Knights.

    To further break it down, this is what the For Loop is doing:
    Set Loop = 1
    Is our picked unit equal to UnitType[Loop]? If yes, create UnitCount[Loop] units, if no, nothing happens yet

    Set Loop
    = 2
    Is our picked unit equal to UnitType[Loop]? If yes, create UnitCount[Loop] units, if no, nothing happens yet

    Set Loop
    = 3
    Is our picked unit equal to UnitType[Loop]? If yes, create UnitCount[Loop] units, if no, nothing happens yet

    This makes it so that you only need 1 trigger for setting up the variables and 1 trigger for creating the units. This is a major improvement over copy and pasting the same trigger/variables 8 times, once for each player.

    Additionally, adding new units to the Arrays is extremely easy as you only have to update the Setup trigger and nothing more. It's a simple matter of updating/adding variables:
    • Actions
      • -------- Set this to the total number of Unit-Types --------
      • Set VariableSet TotalUnitTypes = 4
      • -------- Footman --------
      • Set VariableSet UnitType[1] = Footman
      • Set VariableSet UnitCount[1] = 6
      • -------- Rifleman --------
      • Set VariableSet UnitType[2] = Rifleman
      • Set VariableSet UnitCount[2] = 4
      • -------- Knight --------
      • Set VariableSet UnitType[3] = Knight
      • Set VariableSet UnitCount[3] = 2
      • -------- Mortar Team --------
      • Set VariableSet UnitType[4] = Mortar Team
      • Set VariableSet UnitCount[4] = 3
     

    Attached Files:

    Last edited: Aug 26, 2020