• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Simple Unit Floating System v1.1

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
- This system allows you to float your unit in mid-air.


External Instructions
- Open World Editor - File - Preferences... - General Tab - Tick the Automatically create unknown variables while pasting trigger data
- Copy the Simple Floating Unit System folder.
- YOU'RE DONE !

Internal Instructions (CONFIGS)
- You have 5 variables that you can manipulate:
FU_FloatingSpeedSet (per second travel from max to min or vice-versa)
FU_FloatingSpeedDecelerateSet(per second decelerate)
FU_MaxHeightSet (maximum height of floating range)
FU_MinHeightSet (minimum height of floating range)
FU_UnitSet (which unit)

- After you have set all these variables, run this trigger;
  • Trigger - Run FU Event <gen> (ignoring conditions)
- To stop the unit from further floating (comes back down), just set which unit (FU_UnitSet) and run this trigger;
  • Actions
    • Set FU_UnitSet = (Target unit of ability being cast)
    • Trigger - Run FU Cancel <gen> (ignoring conditions)
Internal Instructions (EVENTS)
- FU_Event = 1 (MaxHeight has reached)
- FU_Event = 2 (Unit has re-entered the normal speed (from MaxHeight))
- FU_Event = 3 (MinHeight has reached)
- FU_Event = 4 (Unit has re-entered the normal speed (from MinHeight))
- FU_Event = 5 (Removing the unit from the system)
- FU_Event = 6 (Unit is removed from the system)

- Use the FU_UnitEvent to refer to the unit manipulating the event(s).

- To see on how to use it, see the EXAMPLE folder.


  • FU Setup
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set FU_Interval = 0.03
      • Trigger - Add to FU Loop <gen> the event (Time - Every FU_Interval seconds of game time)
  • FU Event
    • Events
    • Conditions
    • Actions
      • Set TempInt = (Custom value of FU_UnitSet)
      • Set FU_FloatingSpeedInterval[TempInt] = (FU_FloatingSpeedSet x FU_Interval)
      • Set FU_FloatingSpdIntervalOriginal[TempInt] = FU_FloatingSpeedInterval[TempInt]
      • Set FU_MinHeight[TempInt] = FU_MinHeightSet
      • Set FU_MaxHeight[TempInt] = FU_MaxHeightSet
      • Set FU_IsFloating[TempInt] = True
      • Set FU_IsGoingUp[TempInt] = True
      • Set FU_FloatingSpeedDecelerate[TempInt] = ((FU_FloatingSpeedDecelerateSet x FU_Interval) x FU_Interval)
      • Unit Group - Add FU_UnitSet to FU_Group
      • Trigger - Turn on FU Loop <gen>
  • FU Cancel
    • Events
    • Conditions
    • Actions
      • Set FU_Event = 0.00
      • Set FU_Event = 5.00
      • Set FU_Event = 0.00
      • Set TempInt = (Custom value of FU_UnitSet)
      • Set FU_IsFloating[TempInt] = False
  • FU Loop
    • Events
    • Conditions
    • Actions
      • Unit Group - Pick every unit in FU_Group and do (Actions)
        • Loop - Actions
          • Set FU_UnitEvent = (Picked unit)
          • Set TempInt = (Custom value of FU_UnitEvent)
          • Set TempReal = (Current flying height of FU_UnitEvent)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (FU_UnitEvent is alive) Equal to True
              • FU_IsFloating[TempInt] Equal to True
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • FU_IsGoingUp[TempInt] Equal to True
                • Then - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • TempReal Less than FU_MaxHeight[TempInt]
                    • Then - Actions
                      • Animation - Change FU_UnitEvent flying height to (TempReal + FU_FloatingSpeedInterval[TempInt]) at 0.00
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (Current flying height of FU_UnitEvent) Greater than or equal to FU_MaxHeight[TempInt]
                        • Then - Actions
                          • Set FU_Event = 0.00
                          • Set FU_Event = 1.00
                          • Set FU_Event = 0.00
                        • Else - Actions
                    • Else - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • TempReal Greater than or equal to FU_MaxHeight[TempInt]
                        • Then - Actions
                          • Set FU_FloatingSpeedInterval[TempInt] = (FU_FloatingSpeedInterval[TempInt] - FU_FloatingSpeedDecelerate[TempInt])
                          • Animation - Change FU_UnitEvent flying height to (TempReal + FU_FloatingSpeedInterval[TempInt]) at 0.00
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • (Current flying height of FU_UnitEvent) Less than or equal to FU_MaxHeight[TempInt]
                            • Then - Actions
                              • Set FU_Event = 0.00
                              • Set FU_Event = 2.00
                              • Set FU_Event = 0.00
                              • Set FU_IsGoingUp[TempInt] = False
                              • Set FU_FloatingSpeedInterval[TempInt] = (FU_FloatingSpdIntervalOriginal[TempInt] x -1.00)
                            • Else - Actions
                        • Else - Actions
                • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • TempReal Greater than FU_MinHeight[TempInt]
                    • Then - Actions
                      • Animation - Change FU_UnitEvent flying height to (TempReal + FU_FloatingSpeedInterval[TempInt]) at 0.00
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (Current flying height of FU_UnitEvent) Less than or equal to FU_MinHeight[TempInt]
                        • Then - Actions
                          • Set FU_Event = 0.00
                          • Set FU_Event = 3.00
                          • Set FU_Event = 0.00
                        • Else - Actions
                    • Else - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • TempReal Less than or equal to FU_MinHeight[TempInt]
                        • Then - Actions
                          • Set FU_FloatingSpeedInterval[TempInt] = (FU_FloatingSpeedInterval[TempInt] + FU_FloatingSpeedDecelerate[TempInt])
                          • Animation - Change FU_UnitEvent flying height to (TempReal + FU_FloatingSpeedInterval[TempInt]) at 0.00
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • (Current flying height of FU_UnitEvent) Greater than or equal to FU_MinHeight[TempInt]
                            • Then - Actions
                              • Set FU_Event = 0.00
                              • Set FU_Event = 4.00
                              • Set FU_Event = 0.00
                              • Set FU_IsGoingUp[TempInt] = True
                              • Set FU_FloatingSpeedInterval[TempInt] = FU_FloatingSpdIntervalOriginal[TempInt]
                            • Else - Actions
                        • Else - Actions
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • FU_FloatingSpeedInterval[TempInt] Greater than 0.00
                • Then - Actions
                  • Animation - Change FU_UnitEvent flying height to (TempReal - FU_FloatingSpeedInterval[TempInt]) at 0.00
                • Else - Actions
                  • Animation - Change FU_UnitEvent flying height to (TempReal + FU_FloatingSpeedInterval[TempInt]) at 0.00
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Current flying height of FU_UnitEvent) Less than or equal to 5.00
                • Then - Actions
                  • Set FU_Event = 0.00
                  • Set FU_Event = 6.00
                  • Set FU_Event = 0.00
                  • Unit Group - Remove FU_UnitEvent from FU_Group
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Number of units in FU_Group) Equal to 0
                    • Then - Actions
                      • Trigger - Turn off (This trigger)
                    • Else - Actions
                • Else - Actions
- Bribe (Unit Indexer)
- Magtheridon (GUI Auto-Fly)


v1.0
- Initial release

v1.1
- Changed from Hashtable -> Custom Value (Unit Indexer)
- Supports smooth floating (deceleration)
- Added EVENTS manipulation
- Added additional CONFIG (FU_FloatingSpeedDecelerateSet)
- Uses Integer to check if the trigger should be turned off or not instead of using IsUnitGroupEmpty


Keywords:
simple, floating, float, unit, system, defskull, hashtable, indexing, unit, indexer, deceleration, acceleration, accelerate, event, cancel, going, up,
Contents

Just another Warcraft III map (Map)

Reviews
19 Oct 2015 07:07 Bribe: I really like the smoothness of the floating and would be good to make a non-floating model into one that does float. A couple of things: When I set the minimum height to 100, the unit would still touch the ground...

Moderator

M

Moderator

19 Oct 2015 07:07
Bribe: I really like the smoothness of the floating and would be good to make a non-floating model into one that does float. A couple of things:

When I set the minimum height to 100, the unit would still touch the ground.

Turning on the loop trigger is only necessary if the floating unit count is equal to 1. That's why Purge and the others recommended using a FloatCount integer so you can keep track. This way, you don't have to use CountUnitsInGroup when you remove a unit from a group - just check if FloatCount is equal to 0.

20:55, 9th May 2013
PurgeandFire111:

The variables FU_MaxHeight and FU_MinHeight aren't needed. Just save the values of FU_MaxHeightSet and FU_MinHeightSet directly.

As Maker said, you shouldn't check if the group is empty every loop. It means an extra enumeration per loop (which is a drag on performance). I recommend using an integer variable -> increase it by 1 every time FU Event is ran, then decrease by 1 every time the unit is removed from the group. Then you can replace the condition for "<Unit Group> is empty" with "SomeInt Equal to 0".
 
instead of making a Simple Auto Fly System, put it in the event...

not Unit Indexer but make a global integer variable, when system runs, add an instance, then when it's cancelled reduce the instance, if it reaches zero off the FU_Loop trigger coz emptying a group in jass contains at least 8 lines of code...

You mean I should just put 0.03 in the FU Loop trigger ?
yes
 
Level 33
Joined
Mar 27, 2008
Messages
8,035
Is checking isUnitInGroup is same (efficient-cost) as isUnitGroupEmpty ?
If it's the same, then no point.

Because if a unit is already affected by this system, and another function tries to insert that unit into this system once more, it will perform isUnitInGroup check to either add 1 of that global integer, or just do nothing to it.
 
You can use the concept of the birthday attack to figure out the variation of the speed of a hashtable.

As more and more hash collisions occur, the hashtable gets slower and slower because the O(n)-complex component of the hash function would begin to emerge (A hashtable is implemented commonly as an array of lists or an array of arrays. An array of arrays is faster than an array of lists because an array of arrays avoids cache misses. Lists access memory addresses in no particular order as the nodes are all over the place in memory. When the arrays get larger and larger, a hashtable lookup starts to have O(n) complexity. This is when a Binary search tree with an algorithm that has O(log n) complexity becomes more advantageous. They could also be using a binary search tree of binary search trees, a binary search tree of arrays or a binary search tree of lists. I don't know what Blizzard does internally, but one of these is the ideal solution for a hashtable.)

Refer to this table from Wikipedia:

attachment.php


We can assume that their key space is 2^16 or 2^32. If their implementation is an array of something, then 2^16 is more likely because all keys can be assumed equi-probable, so logarithmic memory allocation is useless (This explains the 256 limit - too much memory required). If they're using an O(log n) search algorithm via a map for the hashtable, then they can use pretty much anything they want for the key space. In that case, 2^32 makes more sense. We can test for this by creating 255 hashtables and filling them with random data while monitoring memory usage. I have no idea about their implementation, but we can make a very good guess by looking at memory usage and speed variation of 1 hashtable with a ton of data vs. 255 hashtables with the same amount of data spread across. If their key space is 2^16, hashtables will only BEGIN to get slower at an ever increasing rate (still pretty low though) after about 500-600 storages. This is one of the reasons I suspect the 2^16 key space. People have reported different speeds all the time (2x slower, 4x slower, 16x slower, you name it)
 

Attachments

  • hashtabletable.PNG
    hashtabletable.PNG
    17.1 KB · Views: 211
Last edited:
Under some conditions, we can measure the speed of a hashtable, but I'm not saying we're going to get accurate results :p

My point in the above post is that hashtables get slower as you add more values.
They are pretty fast at first, but after you start getting collisions, they only BEGIN to get slower. They're slow after you've put so much data, that there are hash collisions everywhere, and you'd still only notice this speed difference in time critical environments.
 
Level 33
Joined
Mar 27, 2008
Messages
8,035
mckill meant specifically for this system as it doesn't require overloads of data, you get it Almia ?
Mag said it himself, the hash loading will be slower and slower due to increasing amount of data, by the look of it, this system doesn't handle that kind of amount of data so it's fine.
 
Level 33
Joined
Mar 27, 2008
Messages
8,035
^
But Mag has a point because in a long-run program (such as OS in Windows or any platform), the program needs to be as efficient as possible and tends to degrade linearly with the increasing time-usage.

But in this case, I could consider it as "negligible" case as it doesn't deal with massive amount of data so it'll be fine.
 
defskull said:
How much ?

It will vary depending on how lucky you are and what indexes you're using, but on average, you can measure lookup times between 2 and 4 times slower
There exists a set of indexes that can be used so that the hashtable will be as fast as possible 100% of the time even as you add hundreds of thousands of values, but getting these would require a ton of work O:
 
Level 33
Joined
Mar 27, 2008
Messages
8,035
When I set the minimum height to 100, the unit would still touch the ground.

Been thinking about this before I posted the updated version, let me explain to you something.

When you descend by using a jetpack (assuming jetpack technology has arrived and pretty much can be explained mathematically logic to be done) and at altitude of 200m (moving at 200m/s), you press the "deceleration pedal" to land exactly on the ground with 0m/s (which thrust the jetpack upwards) and your deceleration is 50m/s-2, now let's calculate the distance traveled.

a = (vf^2 - vi^2) / 2s

Where,
a = deceleration
vf = final velocity
vi = initial velocity
s = distance traveled

-50 = (0 - 200^2) / 2s
-50 = -40000/ 2s
2s = 800
s = 400

In this case, you would need a 400m of distance to cover up before having your velocity reduced to 0m/s, so that's why you ended up hitting the ground.

BUT, the trigger does not stops there, the velocity will go back upwards after you have reached the point of nonnegative velocity (defined by calculating velocity per interval in the trigger) - then the unit will continue to float upwards, then the cycle continues.

This decision should be made by the coder themselves to determine which properties are suitable to be set for each variables, after all, we're dealing with physics formula - real life.

Or do you think I should put a SimError to warn the user (and possibly, terminate the Event creation) if they reach the limit when setting the variables ? I could do that, I guess.
 
Level 33
Joined
Mar 27, 2008
Messages
8,035
The thing is, user is able to set both Speed and Boundary (Min/Max) - and this would actually affect the "unit hitting the ground" issue.

I can't take away those settings fron users as those variables are what the user would like to manipulate, not dictated by the system itself.

I'll do the "showing msg upon reaching limit" in the next version, something like:
"Given for all the variables that you have set, the minimum allowed value for FU_MinHeightSet is " + distanceTraveled + " .Else, your unit will hit the ground"

This way, users will be able to re-assess the values that they set and adjust accordingly.
 
I am trying to make a unit hover at 100 height, teetering between 75 and 125. You said that the speed is the amount traveled in seconds and the deceleration is how much the speed decelerates per second. What do I need to configure it to to make it take 2 seconds to go down and 2 seconds to go up? I've tried even setting the speed high and the decel to 0 and that made it extremely slow for some reason.
 
Top