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

Simple Trigger

Status
Not open for further replies.
Level 14
Joined
Oct 16, 2011
Messages
296
Hey guys. Can someone make me a trigger that detects units in a semicircle (180 degrees) or less around a certain unit.
Ex: Detect units in an area of 180 degrees in front of a casting unit. sadadsa.jpg
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
JASS:
    function GroupEnumUnitsInCone takes group whichGroup, real x, real y, real radius, real direction, real size returns group
        local unit FoG
        local group g = CreateGroup()
        local real x2
        local real y2
        local real difference
        
        call GroupEnumUnitsInRange(g, x, y, radius, null)
        loop
            set FoG = FirstOfGroup(g)
            exitwhen FoG == null
            call GroupRemoveUnit(g,FoG)
            
            set difference = DeNormalizeAngle(AngleBetweenCoordinates(x, y, GetUnitX(FoG), GetUnitY(FoG)) - direction)
            if difference > -size and difference < size then
                call GroupAddUnit(whichGroup, FoG)
            endif
        endloop
        
        call DestroyGroup(g)
        set g = null
        return whichGroup
    endfunction

Pick all units in range and filter out who are not in the given cone.
To filter them out, we have to find the angle between the source and the target location (coordinates), then we substract the angle that the cone is aiming to and we finally denormalize the angle (>-180 <180), then we check if the difference in the angle is lower than the size and larger than the minus size and if that is true, the unit is in the cone.


You need a few functions and place them anywhere in your code so they will be available to you at any time.

If you have NewGen 2.0, you can do it with library tags and place them in any script.
If you don't, then place them in the header of your map.
JASS:
    function AngleBetweenCoordinates takes real x1, real y1, real x2, real y2 returns real
        return bj_RADTODEG * Atan2(y2 - y1, x2 - x1)
    endfunction
    function DeNormalizeAngle takes real angle returns real
        loop
            if angle <= -180 then
                set angle = angle + 360
            elseif angle > 180 then
                set angle = angle - 360
            else
                return angle
            endif
        endloop
        return 0.
    endfunction
    function GroupEnumUnitsInCone takes group whichGroup, real x, real y, real radius, real direction, real size returns group
        local unit FoG
        local group g = CreateGroup()
        local real x2
        local real y2
        local real difference
        
        call GroupEnumUnitsInRange(g, x, y, radius, null)
        loop
            set FoG = FirstOfGroup(g)
            exitwhen FoG == null
            call GroupRemoveUnit(g,FoG)
            
            set difference = DeNormalizeAngle(AngleBetweenCoordinates(x, y, GetUnitX(FoG), GetUnitY(FoG)) - direction)
            if difference > -size and difference < size then
                call GroupAddUnit(whichGroup, FoG)
            endif
        endloop
        
        call DestroyGroup(g)
        set g = null
        return whichGroup
    endfunction

Now you can use this code anywhere in your map:
  • Actions
    • Custom script: set udg_TempGroup[0] = GroupEnumUnitsInCone(CreateGroup(), x, y, r, d, s)
    • Unit Group - Pick every unit in TempGroup[0] and do (Actions)
      • Loop - Actions
        • -------- Kill unit: --------
        • Unit - Add a 0.01 second Generic expiration timer to (Picked unit)
This action will kill all units in an 2*"s" sized cone of "r" radius into "d" direction from point ("x", "y")...
Aka, you need some variables:
  • Actions
    • Set TempUnit[0] = (Triggering unit)
    • Set TempLocation[0] = (Position of TempUnit[0])
    • Set TempReal[0] = (X of TempLocation[0])
    • Set TempReal[1] = (Y of TempLocation[0])
    • Custom script: call RemoveLocation(udg_TempLocation[0])
    • Set TempReal[2] = 450.00
    • Set TempReal[3] = (Facing of TempUnit[0])
    • Set TempReal[4] = 90.00
    • Custom script: set udg_TempGroup[0] = GroupEnumUnitsInCone(CreateGroup(), udg_TempReal[0], udg_TempReal[1], udg_TempReal[2], udg_TempReal[3], udg_TempReal[4])
    • Unit Group - Pick every unit in TempGroup[0] and do (Actions)
      • Loop - Actions
        • -------- Kill unit: --------
        • Unit - Add a 0.01 second Generic expiration timer to (Picked unit)
    • Custom script: call DestroyGroup(udg_TempGroup[0])
This script will kill all units in 450 range in 90*2=180 degrees in the facing angle of the triggering unit.
Be aware that this will most probably also kill the unit itself.
You would have to create an If/Then/Else inside the loop to filter out allies/enemies/etc.
 
Status
Not open for further replies.
Top