• 🏆 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!

Escort v1.0

  • Escort by Almia
  • Allows you to apply the unit as an escort of another unit.
  • Requires : UnitIndexer
  • JASS:
    //*************************************************************************************
    //*
    //*    Escort by Almia
    //*
    //*************************************************************************************
    //*
    //*    Artificial Intelligence System Member
    //*
    //*    Allows you to apply an escort to a unit. The system is mainly created
    //*    for summoned AI units. You can use non-summon units if you want(esp. custom
    //*    summon spells such as with the action Create Unit)
    //*
    //*************************************************************************************
    //*
    //*    API
    //*
    //*    function AddEscort takes unit s, unit m returns nothing
    //*        s = summon : summoned unit
    //*        m = master : summoning unit
    //*        - applies "s" as an escort of "m"
    //*        - can also work on other units not just summons.
    //*
    //*************************************************************************************
    //*
    //*    Credits
    //*
    //*    mckill2009 - SummonedEscort, the code where the system was based on.
    //*               - I converted this to JASS and also optimized some parts of it.
    //*
    //*    Sylvenon - GetClosestUnit snippet
    //*
    //*    Bribe - Unit Indexer
    //*
    //*    spasorc and Magtheridon96 - bug and minor mistakes
    //*
    //*************************************************************************************
    //*
    //*    GetClosestUnit
    //*    - retrieves the closest unit from a coordinate.
    //*
    //*************************************************************************************
    function GetClosestUnit takes real x, real y, boolexpr e returns unit
        local real md = 100000
        local real d
        local group g = CreateGroup()
        local unit u
        local real dx
        local real dy
        call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, e)
        loop
            set u = FirstOfGroup(g)
            exitwhen u == null
            call GroupRemoveUnit(g, u)
            set dx = GetUnitX(u) - x
            set dy = GetUnitY(u) - y
            if (dx * dx + dy * dy) / 100000 < md then
                set udg_ClosestUnit = u
                set md = (dx * dx + dy * dy) / 100000
            endif
        endloop
        call DestroyGroup(g)
        call DestroyBoolExpr(e)
        set g = null
        return udg_ClosestUnit
    endfunction
    //*************************************************************************************
    //*
    //*    GetClosestUnitInRange
    //*    - retrieves the closest unit from a coordinate in a given radius/range.
    //*
    //*************************************************************************************
    function GetClosestUnitInRange takes real x, real y, real range, boolexpr e returns unit
        local real md = 100000
        local real d
        local group g = CreateGroup()
        local unit u
        local real dx
        local real dy
        local real r
        call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, e)
        loop
            set u = FirstOfGroup(g)
            exitwhen u == null
            call GroupRemoveUnit(g, u)
            set dx = GetUnitX(u) - x
            set dy = GetUnitY(u) - y
            set r = (dx * dx + dy * dy)
            if  r / 100000 < md and r < range * range then
                set udg_ClosestUnit = u
                set md = (dx * dx + dy * dy) / 100000
            endif
        endloop
        call DestroyGroup(g)
        call DestroyBoolExpr(e)
        set g = null
        return udg_ClosestUnit
    endfunction
    //*************************************************************************************
    //*
    //*                             SETTINGS
    //*
    //*************************************************************************************
    //*
    //*    Escort Periodic Interval value
    //*
    //*************************************************************************************
    constant function EscortInterval takes nothing returns real
        return 1.
    endfunction
    //*************************************************************************************
    //*
    //*    Escort Auto Run
    //*    - if true, automatically applies summoned units as an escort.
    //*
    //*************************************************************************************
    constant function EscortAutoRun takes nothing returns boolean
        return true
    endfunction
    //*************************************************************************************
    //*
    //*    Escort Search New Owner
    //*    - if true, summoned unit who lost its master searches a new owner.
    //*
    //*************************************************************************************
    constant function EscortSearchNewOwner takes nothing returns boolean
        return true
    endfunction
    //*************************************************************************************
    //*
    //*    Escort Allow Ally Player
    //*    - if true, summoned units will find the nearest ally unit owned by an ally
    //*      player or the player that owns it.
    //*
    //*************************************************************************************
    constant function EscortAllowAllyPlayer takes nothing returns boolean
        return false
    endfunction
    //*************************************************************************************
    //*
    //*    Escort Follow Hero
    //*    - if true, summoned units will find the nearest ally unit owned by an ally
    //*      player or the player that owns it that must be a hero.
    //*
    //*************************************************************************************
    constant function EscortFollowHero takes nothing returns boolean
        return true
    endfunction
    //*************************************************************************************
    //*
    //*    Escort Follow Structures
    //*    - if true, summoned units will find the nearest ally unit owned by an ally
    //*      player or the player that owns it that must be a structure.
    //*
    //*************************************************************************************
    constant function EscortFollowStructures takes nothing returns boolean
        return false
    endfunction
    //*************************************************************************************
    //*
    //*    Escort Offset
    //*    - distance of the escort from its master(max). Doesn't affect the summons if
    //*      it has a current order such as attacking.
    //*
    //*************************************************************************************
    constant function EscortOffset takes nothing returns real
        return 200.0
    endfunction
    //*************************************************************************************
    //*
    //*    Escort Closest Ally
    //*    - maximum distance where the summons will search their new owner. Depends on
    //*      the boolean EscortSearchNewOwner.
    //*
    //*************************************************************************************
    constant function EscortClosestAlly takes nothing returns real
        return 400.0
    endfunction
    //*************************************************************************************
    //*
    //*    Escort Closest Enemy
    //*    - range of the escort where it will acquire a target.
    //*
    //*************************************************************************************
    constant function EscortClosestEnemy takes nothing returns real
        return 600.0
    endfunction
    //*************************************************************************************
    //*
    //*    Alive Filter
    //*
    //*************************************************************************************
    function EscortAliveFilter takes unit u returns boolean
        return not (GetUnitTypeId(u) == 0 and null == u and IsUnitType(u, UNIT_TYPE_DEAD))
    endfunction
    //*************************************************************************************
    //*
    //*    Escort Ally Filter
    //*
    //*************************************************************************************
    function EscortAllyFilter takes nothing returns boolean
        local boolean b
        local boolean b2
        set udg_Escort_TempU = GetFilterUnit()
        set b = EscortAliveFilter(udg_Escort_TempU) and udg_Escort_TempU != udg_Escort_Summon[udg_Escort_Data] and GetUnitMoveSpeed(udg_Escort_TempU) > 0
        set b2 = IsUnitType(udg_Escort_TempU, UNIT_TYPE_STRUCTURE)
        if EscortFollowStructures() then
            set b = b and b2
        else
            set b = b and not b2
        endif
        if EscortFollowHero() and not b2 then
            set b = b and IsUnitType(udg_Escort_TempU, UNIT_TYPE_HERO)
        endif
        if EscortAllowAllyPlayer() then
            return b and IsUnitAlly(udg_Escort_TempU, udg_Escort_Player[udg_Escort_Data])
        else
            return b and udg_Escort_Player[udg_Escort_Data] == GetOwningPlayer(udg_Escort_TempU)
        endif
    endfunction
    //*************************************************************************************
    //*
    //*    Escort Enemy Filter
    //*
    //*************************************************************************************
    function EscortEnemyFilter takes nothing returns boolean
        set udg_Escort_TempU = GetFilterUnit()
        return IsUnitEnemy(udg_Escort_TempU, udg_Escort_Player[udg_Escort_Data]) and EscortAliveFilter(udg_Escort_TempU)
    endfunction
    //*************************************************************************************
    //*
    //*    Escort Loop
    //*
    //*************************************************************************************
    function EscortLoop takes nothing returns nothing
        local unit t
        local integer order
        local real a
        local real mx
        local real my
        local real sx
        local real sy
        set udg_Escort_Data = udg_Escort_N[0]
        loop
            exitwhen 0 == udg_Escort_Data
            
            if EscortAliveFilter(udg_Escort_Summon[udg_Escort_Data]) then
    	        // Random attack offset.
                set a = GetRandomReal(0, 6.28318)
                set order = GetUnitCurrentOrder(udg_Escort_Summon[udg_Escort_Data])
                if EscortAliveFilter(udg_Escort_Master[udg_Escort_Data]) then
                    if 0 == order then
    		            // Acquire new attack offset
                        set mx = GetUnitX(udg_Escort_Master[udg_Escort_Data]) + EscortOffset() * Cos(a)
                        set my = GetUnitY(udg_Escort_Master[udg_Escort_Data]) + EscortOffset() * Sin(a)
    		            // Order summon to attack the acquired offset
                        call IssuePointOrderById(udg_Escort_Summon[udg_Escort_Data], 851983, mx, my)
    		            // Get nearest unit and set it as its target.
                        set t = GetClosestUnitInRange(mx, my, EscortClosestEnemy(), Filter(function EscortEnemyFilter))
                        if null != t then
                            if IsUnitType(t,UNIT_TYPE_SLEEPING) then
    			                // if unit is sleeping, attack target.
                                call IssueTargetOrderById(udg_Escort_Summon[udg_Escort_Data], 851983, t)
                            else
    		                    // attack-move to the target.
                                call IssuePointOrderById(udg_Escort_Summon[udg_Escort_Data], 851983, GetUnitX(t), GetUnitY(t))
                            endif
                            set t = null
                        endif
                    endif
                else
    	            // if master is dead, acquire new master.
                    set sx = GetUnitX(udg_Escort_Summon[udg_Escort_Data])
                    set sy = GetUnitY(udg_Escort_Summon[udg_Escort_Data])
                    if EscortSearchNewOwner() then
                        set udg_Escort_Master[udg_Escort_Data] = GetClosestUnitInRange(sx, sy, EscortClosestAlly(), Filter(function EscortAllyFilter))
                    else
                        set udg_Escort_Master[udg_Escort_Data] = GetClosestUnit(sx, sy, Filter(function EscortAllyFilter))
                    endif
                    // if alive and no orders, attack-move to the new master's position.
                    if null != udg_Escort_Master[udg_Escort_Data] and 0 == order then
                        call IssuePointOrderById(udg_Escort_Summon[udg_Escort_Data], 851983, udg_Escort_UnitX[udg_Escort_Data] + EscortOffset() * Cos(a), udg_Escort_UnitY[udg_Escort_Data] + EscortOffset() * Sin(a))
                    endif
                endif
            else
                set udg_Escort_N[udg_Escort_P[udg_Escort_Data]] = udg_Escort_N[udg_Escort_Data]
                set udg_Escort_P[udg_Escort_N[udg_Escort_Data]] = udg_Escort_P[udg_Escort_Data]
                // Move last indexed variables to the to-be-allocated index.
                set udg_Escort_Summon[udg_Escort_Data] = null
                set udg_Escort_Master[udg_Escort_Data] = null
                set udg_Escort_UnitX[udg_Escort_Data] = 0
                set udg_Escort_UnitY[udg_Escort_Data] = 0
                set udg_Escort_Player[udg_Escort_Data] = null
    	        // Decrement count
                set udg_Escort_Count = udg_Escort_Count - 1
    	        // Pause if count is equal to 0
                if 0 == udg_Escort_Count then
                    call PauseTimer(udg_EscortTimer)
                endif
            endif
        set udg_Escort_Data = udg_Escort_N[udg_Escort_Data]
        endloop
    endfunction
    //*************************************************************************************
    //*
    //*    Add Escort
    //*
    //*************************************************************************************
    function AddEscort takes unit s, unit m returns nothing
        local integer i = GetUnitUserData(s)
        set udg_Escort_Master[i] = m
        set udg_Escort_UnitX[i] = GetUnitX(m)
        set udg_Escort_UnitY[i] = GetUnitY(m)
        set udg_Escort_Player[i] = GetOwningPlayer(s)
        if not udg_Escort_IsInLoop[i] then
            set udg_Escort_Summon[i] = s
            set udg_Escort_N[i] = 0
            set udg_Escort_P[i] = 0
            set udg_Escort_N[udg_Escort_P[0]] = i
            set udg_Escort_P[0] = i
            set udg_Escort_Count = udg_Escort_Count + 1
            if 1 == udg_Escort_Count then
                call TimerStart(udg_EscortTimer, EscortInterval(), true, function EscortLoop)
            endif
            call RemoveGuardPosition(s)
        endif
    endfunction
    //*************************************************************************************
    //*
    //*    Escort Run Auto-Add Escort
    //*
    //*************************************************************************************
    function EscortRun takes nothing returns boolean
        call AddEscort(GetSummonedUnit(), GetSummoningUnit())
        return false
    endfunction
    //*************************************************************************************
    //*
    //*    Escort Init
    //*
    //*************************************************************************************
    function EscortInit takes nothing returns nothing
        local trigger t
        set udg_EscortTimer = CreateTimer()
        if EscortAutoRun() then
            set t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SUMMON)
            call TriggerAddCondition(t, Condition(function EscortRun))
            set t = null
        endif
    endfunction
  • Demo for non-Auto version(still can also be used)
    • Escort Demo
      • Events
        • Unit - A unit Spawns a summoned unit
      • Conditions
      • Actions
        • Custom script: call AddEscort(GetSummonedUnit(), GetSummoningUnit())
  • Credits
    - mckill2009
    - Sylvenon
    - spasorc
    - Magtheridon96
    - Bribe
Contents

Escort v1.0 (Map)

Reviews
16:07, 22nd Jun 2013 PurgeandFire: Approved. Nice job. Code looks fine. The test map could certainly be better if you added hostile units or gave instructions. Just a tip for the future.

Moderator

M

Moderator

16:07, 22nd Jun 2013
PurgeandFire: Approved. Nice job. Code looks fine. The test map could certainly be better if you added hostile units or gave instructions. Just a tip for the future.
 
Level 1
Joined
Jan 6, 2020
Messages
1
Great work ! but a little buggy : / When you kill enemy, the unit summoned stay on the corpse : o ... And when the corpse is gone ... unit go back an a point .... frustrating :vw_death:
a fellow this post if you want to fix this maybe I include that on my super custom map :goblin_good_job:....
can you attach this on a skill like defending on footman (skill that you allow to put on/off ? :goblin_yeah:

Like this its look ... Perfect ! :peasant-victory:
 
Top