• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

I need help with JASS...

Status
Not open for further replies.
Level 8
Joined
Jun 26, 2019
Messages
318
Hello. Anybody with good at coding. I need help to adding few configurations and few conditions to the fixed JASS system. Anybody familiar with this system?

JASS:
//TESH.scrollpos=291
//TESH.alwaysfold=0
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    = 0
       
        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.9
       
        //A CONSTANT MULTIPILER TO THE UNIT SPEED, TO CIRCUMVENT THE HARDCODED SPEED LIMIT OF WC3. 
        private constant real SPEED_FACTOR      = 4.0
       
        //MAX DISTANCE TO MAP BORDER WHERE PLANES CAN TRAVEL
        private constant real BORDER_WIDTH      = 0
        //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

JASS:
//TESH.scrollpos=8
//TESH.alwaysfold=0
library ListModule
//===========================================================================
// Information:
//==============
//
//     This library provides the List module, which allows you to easily create
// a linked list of all of the allocated instances of a struct-type. Iterating
// through a linked list is about 12% faster than iteratating through an array
// in JASS. There is no faster method to iterate through a list of structs than
// the method used by this module. Aside from the marginal speed gain, the best
// use of this library is to hide some ugly low-level code from your structs.
// Rather than manually building and maintaining a list of struct instances,
// just implement the List module, and your code will become much prettier.
//
//===========================================================================
// How to use the List module:
//=============================
//
//     Using the List module is pretty simple. First, implement it in your
// struct (preferably at the top to avoid unnecessary TriggerEvaluate calls).
// In the struct's create method, you must call listAdd(). In the onDestroy
// method, you must also call listRemove(). An example is shown below:
/*
    struct Example
        implement List
       
        static method create takes nothing returns Example
            local Example this = allocate()
                call listAdd() //This method adds the instance to the list.
            return this
        endmethod
       
        method onDestroy takes nothing returns nothing
            call listRemove() //This method removes the instance from the list.
        endmethod
    endstruct
*/
//     The requirement to call listAdd() and listRemove() will be done away
// with once JassHelper supports module onDestroy and module onCreate, but
// for now, it is not too much of a burden.
//
//     Once this is done, your struct will gain all of the methods detailed
// in the API section. Below is an example of how to iterate through the list
// of allocated structs of the implementing struct-type:
/*
    function IterationExample takes nothing returns nothing
        local Example e = Example.first
            loop
                exitwhen e == 0
                //Do something with e here.
                set e = e.next
            endloop
        //Use .last and .prev instead to iterate backwards.
    endmethod
*/
//
//===========================================================================
// List module API:
//==================
//
// (readonly)(static) first -> thistype
//   This member contains the first instance of thistype in the list.
//
// (readonly)(static) last -> thistype
//   This member contains the last instance of thistype in the list.
//
// (readonly)(static) count -> integer
//   This member contains the number of allocated structs of thistype.
//
// (readonly) next -> thistype
//   This member contains the next instance of thistype in the list.
//
// (readonly) prev -> thistype
//   This member contains the previous instance of thistype in the list.
//
// listAdd()
//   This method adds this instance to the list of structs of thistype.
//   This should be called on each instance after it is allocated (within
//   the create method).
//
// listRemove()
//   This method removes this instance from the list of structs of thistype.
//   This should be called on each instance before it is destroyed (within
//   the onDestroy method).
//
// (static) listDestroy()
//   This method destroys all the structs of thistype within the list.
//
//===========================================================================

module List
    private static boolean destroying = false
    private boolean inlist = false
   
    readonly static integer count = 0
   
    readonly thistype next = 0
    readonly thistype prev = 0
   
    static method operator first takes nothing returns thistype
        return thistype(0).next
    endmethod
   
    static method operator last takes nothing returns thistype
        return thistype(0).prev
    endmethod
   
    method listRemove takes nothing returns nothing
        if not inlist then
            return
        endif
        set inlist = false
        set prev.next = next
        set next.prev = prev
        set count = count - 1
    endmethod

    method listAdd takes nothing returns nothing
        if inlist or destroying then
            return
        endif
        set inlist = true
        set last.next = this
        set prev = last
        set thistype(0).prev = this
        set count = count + 1
    endmethod
   
    static method listDestroy takes nothing returns nothing
        local thistype this = last
            set destroying = true
            loop
                exitwhen this == 0
                call destroy()
                set this = prev
            endloop
            set destroying = false
    endmethod
   
endmodule

endlibrary
 
Status
Not open for further replies.
Top