1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  3. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still havn't received your rank award? Then please contact the administration.
    Dismiss Notice
  4. The Lich King demands your service! We've reached the 19th edition of the Icon Contest. Come along and make some chilling servants for the one true king.
    Dismiss Notice
  5. The 4th SFX Contest has started. Be sure to participate and have a fun factor in it.
    Dismiss Notice
  6. The poll for the 21st Terraining Contest is LIVE. Be sure to check out the entries and vote for one.
    Dismiss Notice
  7. The results are out! Check them out.
    Dismiss Notice
  8. Don’t forget to sign up for the Hive Cup. There’s a 555 EUR prize pool. Sign up now!
    Dismiss Notice
  9. The Hive Workshop Cup contest results have been announced! See the maps that'll be featured in the Hive Workshop Cup tournament!
    Dismiss Notice
  10. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Realistic Airplane System

Submitted by Fingolfin
This bundle is marked as pending. It has not been reviewed by a staff member yet.
Requires:
ListModule

Optional:
AutoIndex

This is a lightweight system for adding realistic airplane movement to your map. It also features inertia, which means the airplanes will "slide" more or less depending on how low you set the air resistance to be. Please note that setting the air resistance to values above or equal to 1 will result in your airplanes accelerating out of control, and values below 0.95 might also cause your airplanes to spin out when turning.

To give airplane motion to a unit type, all you need to do is use the following line:

Code (vJASS):

call registerPlaneType('xxxx')
 


Where 'xxxx' is the unit ID of your airplane (you can find unit IDs by pressing CTRL+D in the object editor). This line must be put inside the function named initPlaneTypes, which you can easily find inside the library. The airplanes will use the movement and turning speed that you have specified in the object editor, but the max speed will be scaled by a variable called "SPEED_FACTOR", which defaults to 160%. This variable is used to bypass the hardcoded limit for unit speed that warcraft has.

Some things to keep in mind when creating units to work with this system:
  • It works best with low turning speeds - you may have to shift-click the turning speed field to enter values lower than 0.1. I've found that somewhere around 0.05 is good.
  • You will need to tweak the turning speed together with the movement speed so that the unit has a turning circle that works for doing attack runs. If the turning circle is too large, the unit won't be able to attack, and if it is too small, it will no longer look like a plane. Slower speeds need lower turn rates.
  • It is probably best to put "Animation - damage point" to 0 for all attacks, otherwise there is a risk that the unit doesn't have time to attack.

Code
Code (vJASS):

library AirplaneSystem requires ListModule, optional AutoIndex

    /*
       .~@ FINGOLFINS AIRPLANE MOVEMENT SYSTEM @~.
   
        INSTRUCTIONS:
            - Implement AutoIndex as specified in its description
            - Create your airplane units as you would with any normal unit
            - Set the turn speed of your airplanes to something below 0.1 (use shift-click)
            - Register plane types by adding this line to the initPlaneTypes function:
           
              call registerPlaneType('xxxx')
             
              where 'xxxx' is the id of your airplane.
    */

   
    //=======================//
    //======= GLOBALS =======//
    //=======================//

    globals
        private constant real UPDATE_INTERVAL   = 0.03125 //I SUBMIT TO THIS FOLLY
        private constant real ORDER_INTERVAL    = 1 // HOW OFTEN ORDERS ARE REFRESHED
        private constant real DEFAULT_FACING    = 270
       
        private constant integer MAX_PLAYERS    = 24
       
        //LOWER NUMBERS = LESS INERTIA. SET TO ZERO TO REMOVE INERTIA COMPLETELY. THIS VALUE MUST BE LOWER THAN 1!
        private constant real AIR_FRICTION      = 0.945
       
        //A CONSTANT MULTIPILER TO THE UNIT SPEED, TO CIRCUMVENT THE HARDCODED SPEED LIMIT OF WC3.
        private constant real SPEED_FACTOR      = 1.6
       
        //MAX DISTANCE TO MAP BORDER WHERE PLANES CAN TRAVEL
        private constant real BORDER_WIDTH      = 200
        //MAP BOUNDS
        private real MAP_MAX_X
        private real MAP_MAX_Y
        private real MAP_MIN_X
        private real MAP_MIN_Y
       
        private constant integer ORDER_SMART    = OrderId("smart")
        private constant integer ORDER_MOVE     = OrderId("move")
        private constant integer ORDER_ATTACK   = OrderId("attack")
       
        private constant integer TYPES_KEY      = StringHash("Airplane Types")
        private constant integer INSTANCES_KEY  = StringHash("Airplane Instances")
       
        private hashtable Hash                  = InitHashtable()
    endglobals
   
    native UnitAlive takes unit id returns boolean
   
    //=======================//
    //===== SYSTEM CODE =====//
    //=======================//
   
    function IsUnitPlane takes unit whichunit returns boolean
        return HaveSavedInteger(Hash, TYPES_KEY, GetUnitTypeId(whichunit))
    endfunction
   
    private function RegisterPlaneType takes integer unitid returns nothing
        call SaveInteger(Hash, TYPES_KEY, unitid, 1)
    endfunction
   
    private function InitPlaneTypes takes nothing returns nothing
        //REGISTER YOUR PLANE TYPES LIKE THIS
        call RegisterPlaneType('jetf')
        call RegisterPlaneType('bomb')
        call RegisterPlaneType('rdra')
    endfunction
   
    struct Plane
   
        implement List
   
        unit plane      = null
        unit target     = null
       
        real vx         = 0
        real vy         = 0
       
        real tx         = 0
        real ty         = 0
       
        real speed      = 0
       
        integer order   = 0
       
        private static timer t1
        private static timer t2
       
        private static method get takes unit whichunit returns thistype
            return LoadInteger(Hash, INSTANCES_KEY, GetHandleId(whichunit))
        endmethod
       
        method onDestroy takes nothing returns nothing
            //DON'T GIVE ME CRAP ABOUT USING onDestroy(), IT POSES NO PERFORMANCE ISSUE IN THIS CASE.
            call .listRemove()
            call RemoveSavedInteger(Hash, INSTANCES_KEY, GetHandleId(.plane))
           
            if .count == 0 then
                call PauseTimer(.t1)
                call PauseTimer(.t2)
            endif
        endmethod
       
        private static method updateOrder takes nothing returns nothing
            local thistype this = .first
            local thistype temp
            local real x
            local real y
           
            if .count == 0 then
                call PauseTimer(.t1)
                call PauseTimer(.t2)
            endif
           
            loop
                exitwhen this == 0
                set temp = .next
               
                if GetUnitTypeId(.plane) == 0 then
                    //DESTROY THE STRUCT WHEN THE PLANE NO LONGER EXISTS
                    call .destroy()
                else
                    if .target != null then
                        if UnitAlive(.target) == false or GetUnitTypeId(.target) == 0 then
                            set .target = null
                            set .tx = GetUnitX(.plane)
                            set .ty = GetUnitY(.plane)
                            set .order = ORDER_ATTACK
                        else
                            call IssueTargetOrderById(.plane, .order, .target)
                        endif
                    else
                        if .order == ORDER_MOVE or .order == ORDER_SMART then
                            set x = GetUnitX(.plane)
                            set y = GetUnitY(.plane)
                            if (x - .tx)*(x - .tx) + (y - .ty)*(y - .ty) < 10000 then
                                //ALLOW THE UNIT TO ATTACK ONCE IT HAS REACHED ITS DESTINATION
                                set .order = ORDER_ATTACK
                            endif
                        endif
                       
                        call IssuePointOrderById(.plane, .order, .tx, .ty)
                    endif
                endif
               
                set this = temp
            endloop
        endmethod
       
        private static method updatePosition takes nothing returns nothing
            local thistype this = .first
            local real x         = 0
            local real y         = 0
            local real f         = 0
           
            loop
                exitwhen this == 0  
               
                set f = GetUnitFacing(.plane)*bj_DEGTORAD
               
                //ADD FRICTION FIRST INCASE IT IS ZEROED
                set .vx = (.vx * AIR_FRICTION) + .speed * Cos(f)
                set .vy = (.vy * AIR_FRICTION) + .speed * Sin(f)
               
                set x = GetUnitX(.plane)+.vx
                set y = GetUnitY(.plane)+.vy
               
                //ENFORCE BOUNDS
               
                if x > MAP_MAX_X then
                    set x = MAP_MAX_X
                elseif x < MAP_MIN_X then
                    set x = MAP_MIN_X
                endif
               
                if y > MAP_MAX_Y then
                    set y = MAP_MAX_Y
                elseif y < MAP_MIN_Y then
                    set y = MAP_MIN_Y
                endif
               
                call SetUnitX(.plane, x)
                call SetUnitY(.plane, y)
               
                set this = .next
            endloop
        endmethod
       
        private static method onOrderTarget takes nothing returns boolean
            local thistype this = thistype.get(GetTriggerUnit())
           
            if this == 0 then
                return false
            endif
           
            set .target = GetOrderTargetUnit()
            set .tx = GetUnitX(.target)
            set .ty = GetUnitY(.target)
            set .order = GetIssuedOrderId()
           
            return false
        endmethod
       
        private static method onOrderPoint takes nothing returns boolean
            local real x = GetOrderPointX()
            local real y = GetOrderPointY()
            local thistype this = thistype.get(GetTriggerUnit())
           
            if this == 0 then
                return false
            endif
           
            set .tx = x
            set .ty = y
            set .target = null
            set .order = GetIssuedOrderId()
           
            return false
        endmethod
       
        static method create takes unit whichunit returns thistype
            local thistype this = thistype.allocate()
           
            call .listAdd()
           
            call SaveInteger(Hash, INSTANCES_KEY, GetHandleId(whichunit), this)
           
            //=========SOME MATH TRIVIA!=========//
            //The acceleration is given by the following differential equation:
            // v(t)' = a = v(t) - v(t)*(1-R), where R = AIR_FRICTION
            //And it's solution:
            //v(t) = (a/(1-R)*(1 + e^-(1-R)t)
            //Calculating the limit when (t -> infinity) gives:
            //vmax = a/(1-R)
            //vmax*(1-R) = a (in this case 'vmax' is known and 'a' is unknown)
            //===========END OF TRIVIA===========//
           
            set .plane = whichunit
            set .speed = GetUnitDefaultMoveSpeed(.plane)*(1-AIR_FRICTION)*UPDATE_INTERVAL*SPEED_FACTOR
           
           
            set .tx = GetUnitX(.plane) + 500 * Cos(DEFAULT_FACING*bj_DEGTORAD)
            set .ty = GetUnitY(.plane) + 500 * Sin(DEFAULT_FACING*bj_DEGTORAD)
            set .order = ORDER_SMART
           
            call SetUnitMoveSpeed(.plane, 0.01)
            call SetUnitFacing(.plane, DEFAULT_FACING)
            call SetUnitFlyHeight(.plane, 0, 0)
            call SetUnitFlyHeight(.plane, GetUnitDefaultFlyHeight(.plane), GetUnitDefaultFlyHeight(.plane)/3)
           
            if .count == 1 then
                call TimerStart(.t1, UPDATE_INTERVAL, true, function thistype.updatePosition)
                call TimerStart(.t2, ORDER_INTERVAL, true, function thistype.updateOrder)
            endif
            return this
        endmethod
       
        private static method onUnitEntersMap takes nothing returns boolean
            call thistype.onIndex(GetFilterUnit())
            return false
        endmethod
       
        private static method onIndex takes unit u returns nothing
            if IsUnitPlane(u) then
                call .create(u)
            endif
        endmethod
       
        private static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            local integer i = 0
            local rect r = GetWorldBounds()
            local region map = CreateRegion()
            local group g = CreateGroup()
           
            set MAP_MAX_X = GetRectMaxX(r)-BORDER_WIDTH
            set MAP_MAX_Y = GetRectMaxY(r)-BORDER_WIDTH
            set MAP_MIN_X = GetRectMinX(r)+BORDER_WIDTH
            set MAP_MIN_Y = GetRectMinY(r)+BORDER_WIDTH
           
            set Plane.t1 = CreateTimer()
            set Plane.t2 = CreateTimer()
           
            call InitPlaneTypes()
           
            loop
                exitwhen i > MAX_PLAYERS
                call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, null)
                set i = i+1
            endloop
            call TriggerAddCondition(t, Condition(function Plane.onOrderTarget))
           
            set t = CreateTrigger()
            set i = 0
           
            loop
                exitwhen i > MAX_PLAYERS
                call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER, null)
                set i = i+1
            endloop
            call TriggerAddCondition(t, Condition(function Plane.onOrderPoint))
           
            static if (LIBRARY_AutoIndex) then
                call OnUnitIndexed(Plane.onIndex)
            else
                set t = CreateTrigger()
                call RegionAddRect(map, r)
                call TriggerRegisterEnterRegion(t, map, function Plane.onUnitEntersMap)
               
                set i = 0
                loop
                    exitwhen i > MAX_PLAYERS
                    call GroupEnumUnitsOfPlayer(g, Player(i), function Plane.onUnitEntersMap)
                    set i = i+1
                endloop
            endif
           
            call DestroyGroup(g)
            call RemoveRect(r)
            set g = null
            set r = null
            set t = null
            set map = null
        endmethod
   
    endstruct

endlibrary
 


UPDATE 1:
- Made most struct methods private.
- The system now uses GetUnitTypeId(whichunit) == 0 to check if a unit no longer exists.

UPDATE 2:
- The system now uses AutoIndex instead of AutoDex. Various other fixes to satisfy the moderators demands.

UPDATE 3:
- AutoIndex is now optional.
- Now supports 24 players.

UPDATE 4:
- Removed all custom models from the map, so that people won't be confused as to what to import.
- Map border width is now customizeable.

UPDATE 5:
- Various small changes to conform with moderator's requests


Keywords:
Airplane, inertia, flying, air, fighter, ship
Contents

Realistic Airplane System (Map)

Reviews
Moderator
Realistic Airplane System | Reviewed by BPower | 15.06.2015 Concept[/COLOR]] [IMG]Partly takes over movement controll of units. Is capable of creating a smooth movement for airplanes. [IMG] The target group of map makers is probably very...
  1. Realistic Airplane System | Reviewed by BPower | 15.06.2015
    • Concept[/COLOR]]
      [​IMG] Partly takes over movement controll of units.
      Is capable of creating a smooth movement for airplanes.
      [​IMG]
      The target group of map makers is probably very small.
      However it's an interesting sytem. I like it.
    • Code[/COLOR]]
      [​IMG]
      • The systems is MUI and leakless.
      • I still don't recommend to use it in its current state.
      • I think there is alot of room for improvements.
      [​IMG]
      • Normally systems use a divisor of 1 for their timer timeout. (.03125, .0625, ... )
      • Update order timeout should also be configurable.
      • When deallocating an instance, you could null those two members: unit u and unit target.
      • Plane unit handles are public and therefore should use a reasonable name i.e "plane" and not "u"
      • Encapsulation is very important, so users do not accidently break the system code.
        Everything not ment to be manipulated should be private by default i.e your static timers.
      • OrderId("attack")
        could be stored into a variable or use "851983".
        Same applies for order move, which is 851986.
      • GetWidgetLife(.target) <= 0
        -->
        GetUnitState(target) == UNIT_STATE_DEAD or GetUnitTypeId(target) == 0

        As alternative you could use native
        not UnitAlive(target)
      • Set map bounds -200/200 when you define them in the first place.
        This will prevent unessesary extra computation time.
      • According to the JPAG function names should be written
        IsUnitPlane
        and not
        isUnitPlane
        .
        We use camelCase for locals, non constant globals, struct methods and struct members.
      • struct plane
        -->
        struct Plane
      • According to user reports library UnitDex is currently not working properly.
        You might want to switch to another unit indexing tool.
        Anyway:
        I suggest you go with
        GetHandleId(unit)
        as you already initialize an hashtable.
    • Demo Map[/COLOR]]
      [​IMG]
      • Your demo map is packed with a lot of imported files, which do not relate to the system.
        This can cause confusion for users, as they don't know what to import in the first place.
      • Apart from that it's a nice demo.
    • Rating[/COLOR]]
      CONCEPT CODE DEMO MAP RATING STATUS
      3.5/5
      2/5
      4/5
      3/5
      NEED FIX

    • Links[/COLOR]]
    [/td]
     
  2. Times

    Times

    Joined:
    Oct 22, 2013
    Messages:
    75
    Resources:
    0
    Resources:
    0
    I would have always said a system like that would take much more lines!
    This deserves a 5/5.
    It'd be too much to ask for the GUI version, I guess...
     
  3. Almia

    Almia

    Joined:
    Apr 24, 2012
    Messages:
    4,856
    Resources:
    35
    Spells:
    30
    Tutorials:
    4
    JASS:
    1
    Resources:
    35
    I feel uncomfortable with the name.

    Why not Airplane Simulator?
     
  4. Quilnez

    Quilnez

    Joined:
    Oct 12, 2011
    Messages:
    3,251
    Resources:
    37
    Icons:
    2
    Tools:
    1
    Maps:
    7
    Spells:
    21
    Tutorials:
    2
    JASS:
    4
    Resources:
    37
    It should be Airplane Movement
     
  5. Hayate

    Hayate

    Joined:
    Oct 20, 2010
    Messages:
    2,608
    Resources:
    65
    Models:
    50
    Icons:
    14
    Spells:
    1
    Resources:
    65
    This is PurrFact
     
  6. apcrabnightlive

    apcrabnightlive

    Joined:
    Oct 7, 2014
    Messages:
    1,924
    Resources:
    1
    Maps:
    1
    Resources:
    1
    The title is not a problem. Anyways this system is great.
     
  7. Fingolfin

    Fingolfin

    Joined:
    Jan 11, 2009
    Messages:
    3,191
    Resources:
    153
    Models:
    143
    Icons:
    1
    Packs:
    4
    Skins:
    2
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    Resources:
    153
    I think the word "simulator" would imply that it is a realistic airplane experience (such as bob666's FlightSim), which is not the case here. The title may be a bit uninspired - but on the other hand, there is no other such system available in this section, so this is pretty much "THE airplane system".
     
  8. kellym0

    kellym0

    Joined:
    Nov 28, 2009
    Messages:
    841
    Resources:
    51
    Models:
    49
    Skins:
    1
    Tutorials:
    1
    Resources:
    51
    wow, Amazing.
     
  9. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    6,178
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    I see you also cause an airplane to attack.

    Could you describe what exactly an airplane is supposed to do?
    For example, as mentioned it might be explained that it automatically attacks nearby enemies.
    This influences unit behaviour, for example unit won't move to targeted point,
    or it will stop patroling, once it mentiones an enemy in range and starts attacking.

    In your struct you can make methods private if they should not be touched.
    You can use onInit static method and make all private.

    private constant real INTERVAL          = 0.038

    How you come to this value for interval?

    onDestroy ->
    set planes[GetUnitId(this.u)] = 0


    Use
    UnitAlive
    native over check life > 0.405.

    Ignore an instance in loop if plane (unit) is dead.

    Destroy an instance if plane (unit) is not in game anymore.
     
    Last edited: May 20, 2015
  10. Fingolfin

    Fingolfin

    Joined:
    Jan 11, 2009
    Messages:
    3,191
    Resources:
    153
    Models:
    143
    Icons:
    1
    Packs:
    4
    Skins:
    2
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    Resources:
    153
    Alright, i will change methods to private and use IsUnitAlive. However, i can't skip instances for dead planes, since i want dead planes to keep flying while their death animation is played. This way, users have more freedom in customizing the crash sequence, by manipulating the "art - death time" in conjugation with "can't raise - does not decay" death type. I could use a trigger fired on unit deindex to remove instances, but the performance gain would be debatable as the trigger would be fired everytime any unit exits the map (as opposed to only airplanes, the way the code works now).
     
  11. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    6,178
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    Seems fair maybe for customizing death.

    Instead of using deindex, you also could check in your loop if GetUnitTypeId(planeUnit) == 0, that means the unit doesn't exist anymore.
     
  12. Fingolfin

    Fingolfin

    Joined:
    Jan 11, 2009
    Messages:
    3,191
    Resources:
    153
    Models:
    143
    Icons:
    1
    Packs:
    4
    Skins:
    2
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    Resources:
    153
    Do you mean GetUnitId(planeUnit), as in the UnitDex function? Good idea, i will do that.
     
  13. Fingolfin

    Fingolfin

    Joined:
    Jan 11, 2009
    Messages:
    3,191
    Resources:
    153
    Models:
    143
    Icons:
    1
    Packs:
    4
    Skins:
    2
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    Resources:
    153
    By the way, IcemanBo, is it safe to run the UnitDex initialization stuff within a struct onInit method? Because i know that onInit methods and library initializers are run in different segements during the map load. I was afraid that this would prevent the index event to properly fire, in the event that the NeoDex initializer would be run after the airplane initializer.


    EDIT: Updated. However, i didn't add any UnitAlive native, because it doesn't exist. There is only a BJ for this, which leads to another BJ, which uses the same method as i do.
     
    Last edited: May 26, 2015
  14. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    6,178
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    Sorry man, for lateness.

    If you make your library require an other library, it will be ok.

    UnitDex should not be used, btw. I also tried using it, and mentioned an error onIndex event.
    At this moment we should go with approved indexers, until UnitDex is not ensured to work correctly.

    Yes, you first need to declare it somewhere on top. It does exist in commin.ai.
    Just write this line after the globals for example:

    native UnitAlive takes unit id returns boolean


    ... then you should be able to use it.

    Some members don't need to be public. (if no private is infront, they are public)

    private constant real INTERVAL          = 0.033

    ^In JASS you can be very precise. You can use
    0.031250000
    ,
    it will result in exactly 32 ticks per second.

    I think there should be some deindex event used. onDeindex the player[unitIndex] should be removed from list, as it's index can be recylcled.
    Later a random unit can get the same index again, and it would be identified as a plane, even it would be an other unit type.

    Very interesting system, btw.
     
  15. Fingolfin

    Fingolfin

    Joined:
    Jan 11, 2009
    Messages:
    3,191
    Resources:
    153
    Models:
    143
    Icons:
    1
    Packs:
    4
    Skins:
    2
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    Resources:
    153
    Fair enough, i will fix all this. Keep in mind though, if i am to "bake in" the offset into the world bounds, i won't benefit from using the WorldBounds library as you suggested.

    All three of these statements are integer comparisions, what is the difference?
    Hell, comparing an integer to a global is even slower than comparing it to a value.

    Uugghhh.... why in the world would you change a perfectly readable line of code to something completely unreadable, for a speed gain that is neglible to say the least??? This is so amazingly stupid, i just want to beat my head into the desk.

    Hmm, it seems to be working fine for me, i've used it for multiple different maps. But ok, maybe i will use the hashtable.

    I don't really see the point of this since these members are assigned in the constructor and thus will never hold old values.

    This is completely arbitrary as computers don't care about what kind of fractions you use. I hate it when people try to enforce these kind of useless rules, but i will conform to it just because people here seem to be so damn anal about it.
     
    Last edited: Jul 19, 2015
  16. Fingolfin

    Fingolfin

    Joined:
    Jan 11, 2009
    Messages:
    3,191
    Resources:
    153
    Models:
    143
    Icons:
    1
    Packs:
    4
    Skins:
    2
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    Resources:
    153
    Just updated this, any chance it can be moved back into "submissions"? How does the new system work?
     
  17. Total_Warrior

    Total_Warrior

    Joined:
    Apr 8, 2007
    Messages:
    629
    Resources:
    1
    Maps:
    1
    Resources:
    1
    Tested the uploaded map and it seems to work flawlessly. I'll be using this bad boy.

    Edit: I don't quite understand how the tag "euro" etc that are declared in the trigger match/connect to the units in the object editor? In terms of getting a unit's ID.
     
    Last edited: Jul 8, 2016
  18. Fingolfin

    Fingolfin

    Joined:
    Jan 11, 2009
    Messages:
    3,191
    Resources:
    153
    Models:
    143
    Icons:
    1
    Packs:
    4
    Skins:
    2
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    Resources:
    153
    Press CTRL+D in the object editor and you will see the raw unit IDs. Yours are probably 'h001', 'h002', etc.
     
  19. Ham Ham

    Ham Ham

    Joined:
    Oct 2, 2006
    Messages:
    1,159
    Resources:
    12
    Models:
    9
    Maps:
    3
    Resources:
    12
    Even although I don't understand anything about JASS, I easily implemented it on a map. Thanks! Very nice stuff.