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

IsUnitEngageable

Level 29
Joined
Mar 10, 2009
Messages
5,016
This s a simple one function that undetects un-engageable(non-attackable) units...
It's main purpose is for AI making...e.g. if an AI searches an enemy target, it will filter out non-attackable units,
thus not wasting time to lock to the unit that cannot be attacked...

Used by my AI systems:
EngageSystem
StrikeForce

JASS:
library IsUnitEngageable /* v1.2
************************************************************************************
*   by mckill2009
************************************************************************************
*
*   Installation:
*       - Copy this script to your trigger editor via custom text
*       - Copy the custom abilty from the object editor named 'IsUnitEngageable' to your map
*       - Make sure you change also the rawID below (SPELL_ID) if you change the rawID of your imported ability
*
************************************************************************************
*
*   function IsUnitEngageable takes unit u returns boolean
*        Undetects units that is:
*          - Invulnerable
*          - Burrowed
*          - Invisible
*          - Ethereal
*          - Have locust
*
************************************************************************************/

globals
/************************************************************************************
*
*   Change the SPELL_ID according to the ability object named 'IsUnitEngageable'
*
*************************************************************************************/
    private constant integer SPELL_ID = 'A000' //based on chain lightning 
/************************************************************************************
*
*   Never touch anything below this block
*
*************************************************************************************/
    private constant integer DUMMY_ID = 'hmpr'
    private unit DUMMY
endglobals

struct onInit
    static method onInit takes nothing returns nothing
        set DUMMY = CreateUnit(Player(15), DUMMY_ID, 0,0,0)
        call UnitAddAbility(DUMMY, SPELL_ID)
        call UnitAddAbility(DUMMY, 'Aloc')  
        call ShowUnit(DUMMY, false)
    endmethod
endstruct

function IsUnitEngageable takes unit u returns boolean
    call SetUnitPosition(DUMMY, GetUnitX(u), GetUnitY(u))
    return IssueTargetOrderById(DUMMY, 852119, u) and not IsUnitType(u,UNIT_TYPE_ETHEREAL)
endfunction

endlibrary


JASS:
scope DEMO initializer init

globals
    group grp = CreateGroup()
endglobals

function fil takes nothing returns boolean
    call GroupAddUnit(grp,GetFilterUnit())
    return false
endfunction

function grploop takes nothing returns nothing
    local unit u = GetEnumUnit()
    local texttag tag
    if IsUnitEngageable(u) then
        set tag = CreateTextTag()
        call SetTextTagPosUnit(tag, u, 0)
        call SetTextTagText(tag, GetUnitName(u), 0.025)
        call SetTextTagPermanent(tag, false)
        call SetTextTagVelocity(tag, 0.03, 0.03)
        call SetTextTagLifespan(tag, 3)
        call SetTextTagFadepoint(tag, 0.01) 
    endif
endfunction

function grplooper takes nothing returns nothing
    call ForGroup(grp,function grploop)
endfunction

function init takes nothing returns nothing
    call GroupEnumUnitsInRect(grp,bj_mapInitialPlayableArea,Filter(function fil))
    call TimerStart(CreateTimer(),1.0,true,function grplooper)
endfunction

endscope



v1.2
- Object ability Unholy Frenzy is replaced by Chain Lightning due to unwanted sound

v1.1
- I've decided to remove the LUA object since it's difficult for me to make a good instruction on how to import it
 

Attachments

  • IsUnitEngageable.w3x
    16.2 KB · Views: 102
Last edited:
You should issue a stop order to the dummy.

You can do this efficiently by returning this:

return IssueTargetOrderById(DUMMY, 852209, u) and IssueImmediateOrderById(DUMMY, 851972) and not IsUnitType(u,UNIT_TYPE_ETHEREAL)

Also, you don't really need to modify the Unholy Frenzy ability.
Actually, if you keep the modification to it and change the cast range to 92083, you won't have to move the dummy unit to the target unit at all.

This way, your function would be inline friendly.

edit
How can't Unholy Frenzy work on Invulnerable units? o_O
Wouldn't a simple attack order be better?
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
This isn't really acceptable

JASS:
//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i setobjecttype("abilities")
    //! i createobject("ACuf","eng0")
    //! i makechange(current,"anam","IsUnitEngageable")
    //! i makechange(current,"ansf","")
    //! i makechange(current,"Uhf1","1","0")
    //! i makechange(current,"Uhf2","1","0")
    //! i makechange(current,"abuf","1","")
    //! i makechange(current,"acdn","1","0")
    //! i makechange(current,"ahdu","1","0.01")
    //! i makechange(current,"adur","1","0.01")
    //! i makechange(current,"amcs","1","0")
    //! i makechange(current,"atar","1","")
//! endexternalblock

Either do cnp of the object from a map to ensure a unique id or use LUA_OBJECT_ID or both.
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
@Mags
Unholy frenzy can't target structures that's why I modified it to target ALL units...also, I already tried attack
order before and it doesnt work coz it will still return true if the first unit it encounters returns true...
You're right about the XY but the stop order is just a waste/slow since it will automatically stop if unit is NOT engageable...

@Nes
I just know the basics of this LUA, so I dont need to complicate things, this for me is very much readable...
 

Zwiebelchen

Hosted Project GR
Level 35
Joined
Sep 17, 2009
Messages
7,236
@Mags
Unholy frenzy can't target structures that's why I modified it to target ALL units...also, I already tried attack
order before and it doesnt work coz it will still return true if the first unit it encounters returns true...
You're right about the XY but the stop order is just a waste/slow since it will automatically stop if unit is NOT engageable...

@Nes
I just know the basics of this LUA, so I dont need to complicate things, this for me is very much readable...
Just one hint: the "smart" order returns false if the unit can not be reached by the dummy (for example when the dummy is stunned, entangled, etc.) - the attack order doesn't return false in this case - so I am pretty sure you can also use "smart" to detect orders on your "untargetable" units.
No ability required in this case.
 
Unholy frenzy can't target structures that's why I modified it to target ALL units...also, I already tried attack
order before and it doesnt work coz it will still return true if the first unit it encounters returns true...

That's why the stop order is required.
You order the unit to attack, and if he does, you stop him.

return Something and SomethingElse
will first look at "Something". If "Something" is false, it will just return false and avoid SomethingElse.
If "Something" returns true, it will continue.
That's how the line I gave you is functional ;)
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
you have a good point there edo494, unfortunately this system is from Player15's point of view, not the engaging player or the player that has the true sight and I made this for AI's coz in the system I made (EngageSystem), if not for this, AI unit still locks the target even if it's 'really' invisible to them, therefore they cant attack another potential target...
 
Level 2
Joined
Feb 27, 2021
Messages
10
You should issue a stop order to the dummy after you issue the ability order to prevent the dummy from actually casting the ability. Otherwise the ability would cause the dummy to pause for almost half a sec and make all the IsUnitEngageable function called during that period return false.
 
Top