• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Mass Teleport find target building

Status
Not open for further replies.
Level 16
Joined
Jun 24, 2009
Messages
1,409
  • Untitled Trigger 001
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Mass Teleport
    • Actions
      • Custom script: set udg_TempUnit = GetSpellTargetUnit()
      • Set TempLocation = (Position of TempUnit)
      • Unit - Create 1 Dummy for Neutral Passive at TempLocation facing Default building facing degrees
      • Unit - Add a 10.00 second Generic expiration timer to (Last created unit)
      • Custom script: call RemoveLocation (udg_TempLocation)
 
Level 37
Joined
Mar 6, 2006
Messages
9,243
You don't need custom script for the target :)

I tried a trigger like this and it worked fine:
  • Untitled Trigger 002
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Mass Teleport
    • Actions
      • Set unit = (Target unit of ability being cast)
      • Game - Display to Player Group - Player 1 (Red) the text: (String((Unit-type of unit)))
 
Same thing for me. But the problem is that Mass Teleport can be cast on a unit or point area, and then it will choose the closest unit if there are any. (Target point of ability being cast) always seems to work for me, but just note that if you use that and create the dummy, it will teleport all the units to the dummy instead of the closest building. The way to find which building is picked is probably to manually group all the units within the area and find the closest one. (I think that is how Mass Teleport works, I didn't test it thoroughly)
 
Level 16
Joined
Jun 24, 2009
Messages
1,409
well, that one works for me:
  • Teleport
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Mass Teleport
    • Actions
      • Set TeleCaster = (Triggering unit)
      • Set TelePoint1 = (Target point of ability being cast)
      • Set TeleGroup = (Units in (Playable map area) matching (((Matching unit) is A structure) Equal to True))
      • Set TeleDist2 = 1000000000.00
      • Unit Group - Pick every unit in TeleGroup and do (Actions)
        • Loop - Actions
          • Set TelePoint2 = (Position of (Picked unit))
          • Set TeleDist1 = (Distance between TelePoint1 and TelePoint2)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TeleDist1 Less than TeleDist2
            • Then - Actions
              • Set TeleDist2 = (Distance between TelePoint1 and TelePoint2)
              • Set TeleUnit = (Picked unit)
            • Else - Actions
          • Custom script: call RemoveLocation (udg_TelePoint2)
      • Set TelePoint3 = (Position of TeleUnit)
      • Unit - Create 1 Dummy for (Owner of TeleCaster) at TelePoint3 facing Default building facing degrees
      • Unit - Add a 2.60 second Generic expiration timer to (Last created unit)
      • Custom script: call RemoveLocation (udg_TelePoint1)
      • Custom script: call RemoveLocation (udg_TelePoint3)
You don't need custom script for the target :)

I tried a trigger like this and it worked fine:
  • Untitled Trigger 002
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Mass Teleport
    • Actions
      • Set unit = (Target unit of ability being cast)
      • Game - Display to Player Group - Player 1 (Red) the text: (String((Unit-type of unit)))

It only works if you target the building itself. If you target the spell on the ground it does nothing.
 
Last edited:
Level 37
Joined
Mar 6, 2006
Messages
9,243
well, that one works for me:
  • Teleport
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Mass Teleport
    • Actions
      • Set TeleCaster = (Triggering unit)
      • Set TelePoint1 = (Target point of ability being cast)
      • Set TeleGroup = (Units in (Playable map area) matching (((Matching unit) is A structure) Equal to True))
      • Set TeleDist2 = 1000000000.00
      • Unit Group - Pick every unit in TeleGroup and do (Actions)
        • Loop - Actions
          • Set TelePoint2 = (Position of (Picked unit))
          • Set TeleDist1 = (Distance between TelePoint1 and TelePoint2)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TeleDist1 Less than TeleDist2
            • Then - Actions
              • Set TeleDist2 = (Distance between TelePoint1 and TelePoint2)
              • Set TeleUnit = (Picked unit)
            • Else - Actions
          • Custom script: call RemoveLocation (udg_TelePoint2)
      • Set TelePoint3 = (Position of TeleUnit)
      • Unit - Create 1 Dummy for (Owner of TeleCaster) at TelePoint3 facing Default building facing degrees
      • Unit - Add a 2.60 second Generic expiration timer to (Last created unit)
      • Custom script: call RemoveLocation (udg_TelePoint1)
      • Custom script: call RemoveLocation (udg_TelePoint3)

Remember to destroy the group. Or rather than using a variable, just use

  • Custom script: set bj_wantDestroyGroup = true
  • Unit Group - Pick every unit in (Units in (Playable map area) matching (((Matching unit) is A structure) Equal to True))
    • Loop - Actions
      • ...
You could filter out dead and enemy structures.

And to add some nitpicking into this post, the max range that there can be is Sqrt(480^2+480^2) * 128 = 86889... -> 87000 so no need to set the TeleDist2 to a very high value :)

It only works if you target the building itself. If you target the spell on the ground it does nothing.

I though you meant that it doesn't work when targeting a building :)
 
Level 37
Joined
Mar 6, 2006
Messages
9,243
Hmm.. how can you know this?
"the max range that there can be is Sqrt(480^2+480^2) * 128 = 86889."

Like baassee explained, the maximum dimensions (in tiles) of a map is 480x480. The sqrt part calculates how many diagonal tiles are needed to form a diagonal line across the map. One tile is 128x128 distance units. Therefore the equation calculates the length of the diagonal of the max sized map.

And max range of what? :O

The trigger finds the closest structure. The distance between. It picks all structures in the map and then compares the distance between the targeted point and a structure. If the distance is less than the current closest structure, then the new shorter distance is stored for the next comparison.

The initial value of the distance is set to a very high value intentionally, so that no matter how far away the targeted point and the structure are, the distance will always be less than the initial value.

However there's no need to set the initial value to a extremely high value, since the max distance can only be about 87000.

In reality the value is even slightly lower than that due to collision and masked map bounds.
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
Are you guys talking about finding a unit nearest the target point? If so, store the first distance and compare it to the remaining units in the group, if the distance of another group member is shorter than that of the first set, then change the stored distance to the new distance.
 
Level 16
Joined
Jun 24, 2009
Messages
1,409
Maaaan it's already solved ~.~

I'll figure something out, give me a day or two.

Well if I insert a boolean that becomes false after the first unit picked from the group and stores it's distance I don't have to set an initial distance. However if I do this I have to reset the boolean ~.~

I don't know what's your problem with this trigger at all Q.o
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
Use the first distance as the initial value and then compare the remaining distances with that.
 
Level 16
Joined
Jun 24, 2009
Messages
1,409
And how about this?
  • Teleport
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Mass Teleport
    • Actions
      • Set TeleCaster = (Triggering unit)
      • Set TelePoint1 = (Target point of ability being cast)
      • Set TeleGroup = (Units in (Playable map area) matching (((Matching unit) is A structure) Equal to True))
      • Unit Group - Pick every unit in TeleGroup and do (Actions)
        • Loop - Actions
          • Set TelePoint2 = (Position of (Picked unit))
          • Set TeleDist1 = (Distance between TelePoint1 and TelePoint2)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TeleDist1 Greater than TeleDist2
              • TeleDist2 Not equal to 0
            • Then - Actions
            • Else - Actions
              • Set TeleDist2 = TeleDist1
              • Set TeleUnit = (Picked unit)
          • Custom script: call RemoveLocation (udg_TelePoint2)
      • Set TelePoint3 = (Position of TeleUnit)
      • Unit - Create 1 Dummy for (Owner of TeleCaster) at TelePoint3 facing Default building facing degrees
      • Unit - Add a 2.60 second Generic expiration timer to (Last created unit)
      • Custom script: call RemoveLocation (udg_TelePoint1)
      • Custom script: call RemoveLocation (udg_TelePoint3)
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
That won't work, just keep it the way it is there's no problem with it. I was answering baassee's question.

@baassee
JASS:
globals
    real TempX=0.0
    real TempY=0.0
    real TempDist=0.0
    unit TempUnit=null
endglobals

function enumGroup takes nothing returns nothing
    local unit u=GetEnumUnit()
    local real x=GetUnitX(u)-TempX
    local real y=GetUnitY(u)-TempY
    local real distance=SquareRoot(x*x+y*y)
    
    if TempDist>distance then
        set TempDist=distance
        set TempUnit=u
    endif
    
    set u=null
endfunction
        
function GetNearestUnitInGroupFromXY takes real x, real y, group g returns unit
    local unit u=FirstOfGroup(g)
    
    set TempX=x
    set TempY=y
    
    set x=GetUnitX(u)-x
    set y=GetUnitY(u)-y
    
    set TempDist=SquareRoot(x*x+y*y)
    
    call GroupRemoveUnit(g,u)
    set TempUnit=u
    call ForGroup(g,function enumGroup)
    
    set u=null
    
    return TempUnit
endfunction
 
Level 37
Joined
Mar 6, 2006
Messages
9,243
That might not be a better solution. You're manipulating the group inside the function (removing a unit from the group).

First of group is slower that group enum if I remember correctly.

And the extra lines of code do not appeal my eye.

Ok, I admit that it can be done without setting the variable into a high value, but I'd still do it that way.
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
Yeah it is if you're going to iterate through all the units inside the group, but it did not, it used ForGroup for that, it was necessary to retrieve the first unit to initialize the distance variable.

Also, FirstOfGroup and ForGroup are not functionally similar so there's no point in comparing them.
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
FirstOfGroup alone does not loop through units, while ForGroup does. FirstOfGroup isn't meant to be used for iterating through units, why the hell would they add the ForGroup if FirstOfGroup was supposed to do that already.
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
Eh?, what are we talking about? I thought you were referring to my script.
I didn't use the FirstOfGroup to loop, I just retrieved the first unit from the group.
 
Status
Not open for further replies.
Top