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

[JASS] Library picking units in straight line until the end of map

Status
Not open for further replies.
Level 11
Joined
Oct 9, 2015
Messages
721
So in the help zone Anitarf lend me this library that can pick units in an straight line (which I need to a spell) and apparently it did work, but in a few angles it is picking units very far from the programed distance, can someone figure what is going wrong here ?

The library:
JASS:
function GroupEnumUnitsInRangeOfSegment takes group whichgroup, real Ax, real Ay, real Bx, real By, real distance, boolexpr filter returns nothing
    local real dx = Bx-Ax
    local real dy = By-Ay
    local real L = ((dx)*(dx) + (dy)*(dy)) // Get quasi length
    local real r = SquareRoot(dx*dx+dy*dy)/2+distance + 400.0 // replace 400.0 with the max collision size in your map
    local unit u
    call GroupClear(whichgroup)
    call GroupEnumUnitsInRange(udg_LineTempGroup, Ax+(dx/2), Ay+(dy/2), r, filter)
    loop
        set u = FirstOfGroup(udg_LineTempGroup)
        exitwhen u == null
        if L == 0 and IsUnitInRangeXY(u, Ax, Ay, distance) then // seg is actually a point so lets return the point
            call GroupAddUnit(whichgroup, u)
        else
            set r = ((GetUnitX(u)-Ax)*(dx) + (GetUnitY(u)-Ay)*(dy))/(L) // get the ratio
            if r > 1 then // split if/thens so that it exists properly
                if IsUnitInRangeXY(u, Bx, By, distance) then // closests point is past seg, so return end point B
                    call GroupAddUnit(whichgroup, u)
                endif
            elseif r < 0 then
                if IsUnitInRangeXY(u, Ax, Ay, distance) then // same as B, but at A instead
                    call GroupAddUnit(whichgroup, u)
                endif
            elseif IsUnitInRangeXY(u, Ax+r*(dx), Ay+r*(dy), distance) then // In the middle of A and B so use the ratio to find the point
                call GroupAddUnit(whichgroup, u)
            endif
        endif
        call GroupRemoveUnit(udg_LineTempGroup, u)
    endloop
    set u = null    
endfunction
function GroupEnumUnitsInRangeOfSegmentLoc takes group whichgroup, location A, location B, real distance, boolexpr filter returns nothing
    call GroupEnumUnitsInRangeOfSegment(whichgroup, GetLocationX(A), GetLocationY(A), GetLocationX(B), GetLocationY(B), distance, filter)
endfunction

The triggers I'm using:

  • y
    • Events
      • Unit - A unit Finishes casting an ability
    • Conditions
      • (Ability being cast) Equal to Attack
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit[(Player number of (Owner of (Triggering unit)))] has an item of type Espada de Bronze) Equal to True
        • Then - Actions
          • Set Loc1 = (Loc1 offset by 200.00 towards ((Facing of Unit[(Player number of (Owner of (Triggering unit)))]) + 90.00) degrees)
        • Else - Actions
      • Unit - Create 1 Dummy Attack for (Owner of (Triggering unit)) at Loc1 facing (Facing of (Triggering unit)) degrees
      • Unit - Add a 0.05 second Generic expiration timer to (Last created unit)
      • Set AttackBegin[(Player number of (Owner of (Triggering unit)))] = (Last created unit)
      • Set AttackingBool[(Player number of (Owner of (Triggering unit)))] = True
      • Set AttackingInteger[(Player number of (Owner of (Triggering unit)))] = 1
      • Custom script: call RemoveLocation(udg_Loc1)
  • x
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • Trigger - Turn off (This trigger)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of (Triggering unit)) Equal to Dummy Attack
          • AttackingBool[(Player number of (Owner of (Triggering unit)))] Equal to True
        • Then - Actions
          • Set Loc1 = (Position of Unit[(Player number of (Owner of (Triggering unit)))])
          • Set Loc2 = (Position of (Triggering unit))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • AttackingInteger[(Player number of (Owner of (Triggering unit)))] Equal to 1
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Unit[(Player number of (Owner of (Triggering unit)))] has an item of type Espada de Bronze) Equal to True
                • Then - Actions
                  • Set Loc3 = (Loc1 offset by 200.00 towards ((Facing of Unit[(Player number of (Owner of (Triggering unit)))]) + 80.00) degrees)
                • Else - Actions
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • AttackingInteger[(Player number of (Owner of (Triggering unit)))] Equal to 2
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Unit[(Player number of (Owner of (Triggering unit)))] has an item of type Espada de Bronze) Equal to True
                • Then - Actions
                  • Set Loc3 = (Loc1 offset by 200.00 towards ((Facing of Unit[(Player number of (Owner of (Triggering unit)))]) + 70.00) degrees)
                • Else - Actions
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • AttackingInteger[(Player number of (Owner of (Triggering unit)))] Equal to 3
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Unit[(Player number of (Owner of (Triggering unit)))] has an item of type Espada de Bronze) Equal to True
                • Then - Actions
                  • Set Loc3 = (Loc1 offset by 200.00 towards ((Facing of Unit[(Player number of (Owner of (Triggering unit)))]) + 60.00) degrees)
                • Else - Actions
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • AttackingInteger[(Player number of (Owner of (Triggering unit)))] Equal to 4
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Unit[(Player number of (Owner of (Triggering unit)))] has an item of type Espada de Bronze) Equal to True
                • Then - Actions
                  • Set Loc3 = (Loc1 offset by 200.00 towards ((Facing of Unit[(Player number of (Owner of (Triggering unit)))]) + 50.00) degrees)
                • Else - Actions
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • AttackingInteger[(Player number of (Owner of (Triggering unit)))] Equal to 5
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Unit[(Player number of (Owner of (Triggering unit)))] has an item of type Espada de Bronze) Equal to True
                • Then - Actions
                  • Set Loc3 = (Loc1 offset by 200.00 towards ((Facing of Unit[(Player number of (Owner of (Triggering unit)))]) + 40.00) degrees)
                • Else - Actions
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • AttackingInteger[(Player number of (Owner of (Triggering unit)))] Equal to 6
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Unit[(Player number of (Owner of (Triggering unit)))] has an item of type Espada de Bronze) Equal to True
                • Then - Actions
                  • Set Loc3 = (Loc1 offset by 200.00 towards ((Facing of Unit[(Player number of (Owner of (Triggering unit)))]) + 30.00) degrees)
                • Else - Actions
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • AttackingInteger[(Player number of (Owner of (Triggering unit)))] Equal to 7
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Unit[(Player number of (Owner of (Triggering unit)))] has an item of type Espada de Bronze) Equal to True
                • Then - Actions
                  • Set Loc3 = (Loc1 offset by 200.00 towards ((Facing of Unit[(Player number of (Owner of (Triggering unit)))]) + 20.00) degrees)
                • Else - Actions
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • AttackingInteger[(Player number of (Owner of (Triggering unit)))] Equal to 8
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Unit[(Player number of (Owner of (Triggering unit)))] has an item of type Espada de Bronze) Equal to True
                • Then - Actions
                  • Set Loc3 = (Loc1 offset by 200.00 towards ((Facing of Unit[(Player number of (Owner of (Triggering unit)))]) + 10.00) degrees)
                • Else - Actions
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • AttackingInteger[(Player number of (Owner of (Triggering unit)))] Equal to 9
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Unit[(Player number of (Owner of (Triggering unit)))] has an item of type Espada de Bronze) Equal to True
                • Then - Actions
                  • Set Loc3 = (Loc1 offset by 200.00 towards ((Facing of Unit[(Player number of (Owner of (Triggering unit)))]) + 0.00) degrees)
                • Else - Actions
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • AttackingInteger[(Player number of (Owner of (Triggering unit)))] Equal to 10
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Unit[(Player number of (Owner of (Triggering unit)))] has an item of type Espada de Bronze) Equal to True
                • Then - Actions
                  • Set Loc3 = (Loc1 offset by 200.00 towards ((Facing of Unit[(Player number of (Owner of (Triggering unit)))]) - 10.00) degrees)
                • Else - Actions
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • AttackingInteger[(Player number of (Owner of (Triggering unit)))] Equal to 11
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Unit[(Player number of (Owner of (Triggering unit)))] has an item of type Espada de Bronze) Equal to True
                • Then - Actions
                  • Set Loc3 = (Loc1 offset by 200.00 towards ((Facing of Unit[(Player number of (Owner of (Triggering unit)))]) - 20.00) degrees)
                • Else - Actions
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • AttackingInteger[(Player number of (Owner of (Triggering unit)))] Equal to 12
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Unit[(Player number of (Owner of (Triggering unit)))] has an item of type Espada de Bronze) Equal to True
                • Then - Actions
                  • Set Loc3 = (Loc1 offset by 200.00 towards ((Facing of Unit[(Player number of (Owner of (Triggering unit)))]) - 30.00) degrees)
                • Else - Actions
            • Else - Actions
          • Set AttackingInteger[(Player number of (Owner of (Triggering unit)))] = (AttackingInteger[(Player number of (Owner of (Triggering unit)))] + 1)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • AttackingInteger[(Player number of (Owner of (Triggering unit)))] Greater than or equal to 13
            • Then - Actions
              • Set AttackingInteger[(Player number of (Owner of (Triggering unit)))] = 0
              • Set AttackingBool[(Player number of (Owner of (Triggering unit)))] = False
            • Else - Actions
  • -------- ---------THIS IS THE FUNCTION USED TO CALL THE LIBRARY----------- --------
    • Custom script: call GroupEnumUnitsInRangeOfSegmentLoc( udg_TempGroup, udg_Loc1, udg_Loc2, 10.0, null )
    • Unit Group - Pick every unit in TempGroup and do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Picked unit) Not equal to (Triggering unit)
            • (Picked unit) Not equal to Unit[(Player number of (Owner of (Triggering unit)))]
          • Then - Actions
            • Unit - Cause Unit[(Player number of (Owner of (Triggering unit)))] to damage (Picked unit), dealing 500.00 damage of attack type Spells and damage type Normal
          • Else - Actions
    • Unit - Create 1 Dummy Attack for (Owner of (Triggering unit)) at Loc3 facing (Facing of (Triggering unit)) degrees
    • Unit - Add a 0.05 second Generic expiration timer to (Last created unit)
    • Else - Actions
    • Custom script: call RemoveLocation(udg_Loc1)
    • Custom script: call RemoveLocation(udg_Loc2)
    • Custom script: call RemoveLocation(udg_Loc3)
    • Trigger - Turn on (This trigger)
    • Set AttackingInteger[(Integer A)] = 0
    • Set AttackBegin[(Player number of (Owner of (Triggering unit)))] = (Last created unit)
    • Set AttackingBool[(Player number of (Owner of (Triggering unit)))] = False
 
Last edited by a moderator:
Level 7
Joined
Oct 19, 2015
Messages
286
  • Set Loc1 = (Loc1 offset by 200.00 towards ((Facing of Unit[(Player number of (Owner of (Triggering unit)))]) + 90.00) degrees)
You do this without first defining Loc1, so you're offsetting an undefined point. That way, your first unit ends up somewhere near coordinates 0,0 (if the point is undefined) or somewhere random (if you used this point variable in another trigger and didn't destroy it). You need to first set Loc1 to the position of triggering unit before doing the offset. Also, you should store the offset into another variable so you can clean up both points afterwards.

Also, why do you have so many copies of effectively the same if statement in the other trigger? Whenever you do something like this, there is guaranteed to be a simpler solution. In this case:

  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • (Unit[(Player number of (Owner of (Triggering unit)))] has an item of type Espada de Bronze) Equal to True
    • Then - Actions
      • Set Loc3 = (Loc1 offset by 200.00 towards ((Facing of Unit[(Player number of (Owner of (Triggering unit)))]) +90.00 - Real(AttackingInteger[(Player number of (Owner of (Triggering unit)))]*10)) degrees)
    • Else - Actions
  • Set AttackingInteger[(Player number of (Owner of (Triggering unit)))] = (AttackingInteger[(Player number of (Owner of (Triggering unit)))] + 1)
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • AttackingInteger[(Player number of (Owner of (Triggering unit)))] Greater than or equal to 13
    • Then - Actions
      • Set AttackingInteger[(Player number of (Owner of (Triggering unit)))] = 0
      • Set AttackingBool[(Player number of (Owner of (Triggering unit)))] = False
 
Level 11
Joined
Oct 9, 2015
Messages
721
Oh I didn't saw that coming, thanks man I'll try to fix that. By the way the function you stated (about the "+real" thing) could really work for me and save some memory would't it ?

EDIT: Anitarf, units are being picked twice times or more, do you know how to make it only be picked once ?
 
Last edited:
Level 7
Joined
Oct 19, 2015
Messages
286
Yes, add them to a group when you pick them for the first time, then ignore any units that are already in the group. When the spell ends, empty the group.
 
Level 11
Joined
Oct 9, 2015
Messages
721
something like this?
  • Unit Group - Pick every unit in TempGroup and do (Actions)
    • Loop - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Picked unit) Not equal to Unit[(Player number of (Owner of (Triggering unit)))]
          • ((Picked unit) is alive) Equal to True
        • Then - Actions
          • Unit Group - Add (Picked unit) to UnitGroup
          • Unit - Cause Unit[(Player number of (Owner of (Triggering unit)))] to damage (Picked unit), dealing 10.00 damage of attack type Spells and damage type Normal
        • Else - Actions
Then
  • Unit Group - Remove all units from UnitGroup
This didn't seem to work :(
 
Level 7
Joined
Oct 19, 2015
Messages
286
You need to put that action in the correct place, so just posting the action doesn't help, you need to post the whole trigger. I wrote more about this in your other thread, so you can post there instead of here.
 
Status
Not open for further replies.
Top