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

Limited unit attack angle

Status
Not open for further replies.
I'm trying to make a system that forbids units to attack enemies that are not standing within 150 degrees infront of it.

For this i am using Vexorians "GetAngleDifference" system:

JASS:
function GetAngleDifference takes unit u1, unit u2 returns real
     local location l1 = GetUnitLoc(u1)
     local location l2 = GetUnitLoc(u2)
     local real a1 = AngleBetweenPoints(l1, l2)
     local real a2 = GetUnitFacing(u1)
     local real x
     call RemoveLocation(l1)
     call RemoveLocation(l2)
     set l1 = null
     set l2 = null
        // The Modulo will get the co-terminal angle if the angle is less than -360 or greater than 360.
        set a1=ModuloReal(a1,360)
        set a2=ModuloReal(a2,360)
        // makes sure angle 1 is the smaller angle.  If it isn't it switches them.
        if a1>a2 then
            set x=a1
            set a1=a2
            set a2=x
        endif
        // Subtracts 360, to get the first negative co-terminal angle, this is then used in a comparison to check if the angle is greater than 180
        set x=a2-360
        if a2-a1 > a1-x then
            //  If it is, use the negative angle instead
            set a2=x
        endif
        //  Now, get the difference between the 2 angles.
        set x=a1-a2
        //  If the difference is negative, make it positive and return it.  If its positive, return it.
        if (x<0) then
            return -x
        endif
     return x
    endfunction

Combined with this trigger:


  • Attack Angles
    • Events
      • Unit - A unit Is issued an order targeting an object
    • Conditions
      • (Issued order) Equal to (==) (Order(attack))
    • Actions
      • Custom script: local Parent P = Parents[GetUnitUserData(GetTriggerUnit())]
      • Custom script: if not(GetAngleDifference(P.controller, GetOrderTargetUnit()) >150.) then
      • Unit - Order (Triggering unit) to Stop
      • Custom script: endif
(I replaced the struct/array names to "parent" since that's basically what you need to know - it retrieves a "parent unit", which is what we get the facing angle from. Otherwise, the unit would procedurally spin around since he changes facing everytime he attacks a units within the allowed field thus changing the field itself.)

I was told by a friend that the "unit is issued an order" event also detects auto-attacks caused by aquisition range.
The problem is, obviously, that it doesn't work. I would be very thankful if someone helped me out on this.

EDIT: +2 rep to whoever solves this for me. :O
 
Last edited:
  • Attack Angles
    • Events
      • Unit - A unit Is issued an order targeting an object
    • Conditions
      • (Issued order) Equal to (==) (Order(attack))
    • Actions
      • Custom script: local Parent P = Parents[GetUnitUserData(GetTriggerUnit())]
      • Custom script: if not(GetAngleDifference(P.controller, GetOrderTargetUnit()) >150.) then
      • Unit - Order (Triggering unit) to Stop
      • Custom script: endif
(I replaced the struct/array names to "parent" since that's basically what you need to know - it retrieves a "parent unit", which is what we get the facing angle from. Otherwise, the unit would procedurally spin around since he changes facing everytime he attacks a units within the allowed field thus changing the field itself.)

I was told by a friend that the "unit is issued an order" event also detects auto-attacks caused by aquisition range.
The problem is, obviously, that it doesn't work. I would be very thankful if someone helped me out on this.

EDIT: +2 rep to whoever solves this for me. :O

You should add these debug messages and test it to see exactly what the problem is:
  • Attack Angles
    • Events
      • Unit - A unit Is issued an order targeting an object
    • Conditions
      • (Issued order) Equal to (==) (Order(attack))
    • Actions
      • Custom script: local Parent P = Parents[GetUnitUserData(GetTriggerUnit())]
      • Custom script: call BJDebugMsg("Struct: "+I2S(P))
      • Custom script: call BJDebugMsg("AngleDiff: "+R2S(GetAngleDifference(P.controller,GetOrderTargetUnit())))
      • Custom script: if not(GetAngleDifference(P.controller, GetOrderTargetUnit()) >150.) then
      • Unit - Order (Triggering unit) to Stop
      • Custom script: endif
If the messages are shown, that means the event is being registered. Otherwise, the trigger is not being fired.

If the "Struct: #" shows a number greater than 0, then the struct instance is fine. If it is 0, then it isn't retrieving the proper instance for some reason.

If the "AngleDiff: #" shows properly and doesn't return 0, then it should work fine. Else, it might be not functioning or one of the input values are null.

Runs those tests and that will help us figure out what is wrong. :)
 
LOL!!

I tried using "a unit is attacked" instead, and it worked much better.
However, the trigger was fired like.. every second for each some 100 units fighting, since the aquisition range will cause untis to be given attack orders constantly as long as there is a unit within range. It caused massive lag and i was forced to shut the game down.

Is there any way to trigger the aquisition range instead? I mean, if you set it to 0. and have a trigger that register units coming within range of another, and then order the unit to attack it? Or will that also cause lag?
It would be good if it did, since i could integrate it with many other systems in the map.
 
Level 3
Joined
Dec 9, 2009
Messages
35
I have done some test, and unit will attack even if you set aquisition range to 0. You can create loop trigger that will check if there are units in front of your unit. If there are nor units then make unit unable to attack (I think if you add ability from Orc Burrow they will not be able to attack). If there are units then make your unit able to attack ( just remove ability) and order him to attack unit. Also add 2 more triggers :
1. When your unit attack check if unit is in front of unit (because when it's able to attack mby it will attack enemy that is not in range.
2. Use if unit is in order, and in loop check if ordered unit is in front of your unit and then order your unit to attack ordered unit (because if player ordered to attack some unit)

I hope you have understand this, if you need i will make triggers for you
 
Sounds good, but adding "battle stations" (assuming that's teh ability you meant) to a unit caused the game to crash for me. Perhaps it is because it requires a cargo hold. Let me know if you were refering to some other ability (would love to know an ability that disarms a unit without having to be cast).

EDIT: @Bribe: why would i want the attacker to move to the target? I just want it to be unable to attack it.
 
Status
Not open for further replies.
Top