Units following around other units

M4573R

New Member
Reaction score
1
I asked this question a little bit ago, but I guess the wording was way too confusing, so I'm going to try again.

I have this ability that when you cast it, it makes a dummy unit at the location of the target. This unit must now follow around the target unit. I'm not meaning the WC3 "Follow" command, but every .02 second or something, move the dummy unit to the target unit.
If you need an example, look and Naix's ulti from DotA; it creates a dummy unit above a creeps and it follow it around.

The look I'm trying to go for is like a regular buff. BUT it's actually a dummy unit on top of a regular unit.

Second: I was there be more than one of these. This means that if I cast the spell on another unit, another dummy is created and every .02 seconds is moved to its target.

Third: I was 10 max of these at a time. This means that if you cast an 11th time, the oldest dummy will go away. But the dummy unit will also be removed if another unit gets too close. So the oldest dummy is not always being removed; there are other cases.

My attempt included an array of units for the dummies, and an array of units for the targets. Then every .02 seconds dummy[x] was moved to location of target[x]. This worked, but had the possibly for terrible memory crashes, because it was constantly overrunning the array. This method would need to include a way to removed specific units from the arrays, and resort the arrays. Or, when units are removed, new one are put into the empty spots in the arrays, and a check must be done for the oldest units to be removed when an 11th one needs to be added.

I hope this is somewhat understandable because it is a pretty complicated question. I'm sure this would be much easier in JASS than GUI, and I'm willing to learn JASS to do it. I'm just not looking forwards to having to write a linked list in JASS.
 

The Undaddy

Creating with the power of rage
Reaction score
55
I'll make this in GUI,since I believe you already have a few trigger.Also,if you want to learn jass, read a few tutorials and start making triggers by yourself,because I believe you won't be able to learn if someone makes them for you ;)

I'd go with the dummy[x] and target[x] method.I believe every time you create a dummy you increase an integer that points to the next array?

Code:
set dummy[i] = Last Created Unit
set i = i + 1

We'll remake that trigger in a while.

Now, you'd need an integer array Oldest and a integer counter OldUnits.And a unit TempU.So:

integer array Oldest
integer OldUnits
integer TempU

Idk how you remove the dummies, but I presume you use "Remove Unit" (obviously :D)
In the trigger create:

Code:
E: [A unit comes close etc.]
C: Your conditions
A:
Loop - for each integer A from 0 - 9 do:
     if dummy[Integer A] is [The unit that is going to be removed] //Figure out which array slot this unit is occupying 
     then Remove dummy[Integer A]
          Set dummy[Integer A] = No Unit
     else

So let's remake that trigger now.

Code:
E: Your spell is cast
C: Your conditions
A:
For each Integer A from 0 - 9 do //Check all array slots
    if dummy[Integer A] = No Unit //If there's no dummy at this slot
    then set dummy[Integer A] = Create Dummy unit //Create it
           set target[Integer A] = Target Unit of Ability being cast //Self explanatory
           custom script: exitwhen true //and discontinue the loop
    else
I'll post back after ~half an hour with the triggers how to remove the oldest dummy ;)

All triggers are freehanded
 

The Undaddy

Creating with the power of rage
Reaction score
55
You'll need to further edit the triggers now.

Variables:

integer array Oldest //This variable's values must be initialized 10!
integer OldUnits
integer TempI

First you'll need a trigger to arrange the oldest units:

Rearrange trigger:

Code:
E: None
C: None
A:
Loop - for each Integer B from 0 - 8  //This loop is to rearrange the units,so that Oldest[0] is the oldest,Oldest[1] the second oldest etc.
     Loop - for each integer TempI from Integer B + 1 to 9
          If Oldest[Integer B] equal to 10
                then
                       if Oldest[TempI] not equal to 10
                              then 
                                    set Oldest[Integer B] = Oldest[Temp I]
                                    custom script: exitwhen true
                               else
                                    set OldUnits = OldUnits - 1
                else

Creation Trigger:

Code:
E: Your spell is cast
C: Your conditions
A:
Loop - for each Integer A from 0 - 9 do //Check all array slots
    if dummy[Integer A] = No Unit //If there's no dummy at this slot
    then   set dummy[Integer A] = Create Dummy unit //Create it
           set target[Integer A] = Target Unit of Ability being cast //Self explanatory
           set Oldest[OldUnits] = Integer A //OldUnits should have an initial value of 0.
           set OldUnits = OldUnits + 1
           custom script: exitwhen true //and discontinue the loop
    else
    If Integer A = 9 //If all slots are full
        then
              Remove dummy[Oldest[0]] //Remove the oldest unit
  [B]            set TempI = Oldest[0]  //This will store the spot where the new dummy is created[/B]
              set dummy[Oldest[0]] = Create Dummy unit // Create a new one at it's place
              set target[Oldest[0]] = Target Unit of Ability being cast
              set Oldest[0] = 10 //This is no longer the oldest unit
              [B]set OldUnits = OldUnits - 1 //The units are now 1 less hence they are being moved back in the array[/B]
              Trigger : Run Rearrange ignoring conditions
[B]              set Oldest[OldUnits] = TempI[/B]

And now the unit within range trigger:

Code:
E: [A unit comes close etc.]
C: Your conditions
A:
Loop - for each integer A from 0 - 9 do:
     if dummy[Integer A] is [The unit that is going to be removed] //Figure out which array slot this unit is occupying 
         then 
              Remove dummy[Integer A]
              Set dummy[Integer A] = No Unit
              Loop - for each Integer B from 0 - 9
                    if Oldest[Integer B] = Integer A
                    then
                          set Oldest[Integer B] = 10
                          Trigger : Run Rearrange ignoring conditions
                          custom script: exitwhen true
                    else
     else

PS: There was no need for a TempU variable.The triggers aren't tested.

EDIT:
I found a bug with the creation trigger,add the bolded part.
 

M4573R

New Member
Reaction score
1
Thanks for the reply. I was afraid I'd have to write triggers for sorting the array. I was reluctant because I figures it'd be slow. Glad you understood what I wanted.
 

M4573R

New Member
Reaction score
1
I got most of it working kind of like that. Except instead of keeping track of oldest. I realized that the first unit in the array is the oldest to start, so why not keep it like that? Each time an 11th is created, the first one from the array is removed, and each unit is shifted down one, and the new is added to the end. If on in the middle is removed, then each above that is shifted down.

My problem now lies in detecting when a unit comes close to one of the dummies. When they are created, I can add an event to a trigger that explicitly detects when a unit comes close to the new dummy, but I don't think there's a way you can remove the event once the dummy is removed. Or does this matter? I'd think it'd lag or screw up if the event is for a unit that no longer exists. I also would think it'd be bad to check every fraction of a second if someone is close to any dummy in the array.
 

The Undaddy

Creating with the power of rage
Reaction score
55
Having many in a trigger does not interfere with the game.If it did,respawn trees triggers would make the game lag alot.If you are so much worried you can use a variable to store the events and destroy them when the unit is removed.
 

M4573R

New Member
Reaction score
1
This trigger almost works. I don't know why sometimes it wouldn't.

Code:
Explode
    Events
    Conditions
        ((Triggering unit) belongs to an enemy of (Owner of Saboteur)) Equal to True
    Actions
        Game - Display to (All players) the text: Within range.
        For each (Integer A) from 0 to 9, do (Actions)
            Loop - Actions
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        (Distance between (Position of (Triggering unit)) and (Position of ProximityDummies[(Integer A)])) Less than or equal to 256.00
                    Then - Actions
                        Game - Display to (All players) the text: Found match.
                        Set ProximityPositionTemp = (Position of ProximityDummies[(Integer A)])
                        Special Effect - Create a special effect at ProximityPositionTemp using Objects\Spawnmodels\Other\NeutralBuildingExplosion\NeutralBuildingExplosion.mdl
                        Unit Group - Pick every unit in (Units within 300.00 of ProximityPositionTemp matching (((Matching unit) belongs to an enemy of (Owner of Saboteur)) Equal to True)) and do (Actions)
                            Loop - Actions
                                Unit - Cause ProximityDummies[(Integer A)] to damage (Picked unit), dealing 150.00 damage of attack type Spells and damage type Normal
                        Unit - Remove ProximityDummies[(Integer A)] from the game
                        For each (Integer B) from (Integer A) to 8, do (Actions)
                            Loop - Actions
                                Set ProximityTargets[(Integer B)] = ProximityTargets[((Integer B) + 1)]
                                Set ProximityDummies[(Integer B)] = ProximityDummies[((Integer B) + 1)]
                        Set ProximityTargets[9] = No unit
                        Set ProximityDummies[9] = No unit
                        Custom script:   exitwhen true
                    Else - Actions

Edit: It's gotta be something wrong with how I'm handling the array. I think the first unit in the array is getting cleared out.
 

The Undaddy

Creating with the power of rage
Reaction score
55
What are the events?Because once the condition
Code:
(Distance between (Position of (Triggering unit)) and (Position of ProximityDummies[(Integer A)])) Less than or equal to 256.00
is met,the loop is ended (exitwhen true), and thus no more of the integer A's will be checked.
 

M4573R

New Member
Reaction score
1
Well I changed it to this:

Code:
Explode
    Events
    Conditions
        ((Triggering unit) belongs to an enemy of (Owner of Saboteur)) Equal to True
    Actions
        Game - Display to (All players) the text: Within range.
        For each (Integer A) from 0 to 9, do (Actions)
            Loop - Actions
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        ProximityDummies[(Integer A)] Equal to No unit
                    Then - Actions
                        Custom script:   exitwhen true
                    Else - Actions
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        (Distance between (Position of (Triggering unit)) and (Position of ProximityDummies[(Integer A)])) Less than or equal to 256.00
                    Then - Actions
                        Game - Display to (All players) the text: Found match.
                        Set ProximityPositionTemp = (Position of ProximityDummies[(Integer A)])
                        Special Effect - Create a special effect at ProximityPositionTemp using Objects\Spawnmodels\Other\NeutralBuildingExplosion\NeutralBuildingExplosion.mdl
                        Game - Display to (All players) the text: Explosion.
                        Unit Group - Pick every unit in (Units within 300.00 of ProximityPositionTemp matching (((Matching unit) belongs to an enemy of (Owner of Saboteur)) Equal to True)) and do (Actions)
                            Loop - Actions
                                Unit - Cause ProximityDummies[(Integer A)] to damage (Picked unit), dealing 150.00 damage of attack type Spells and damage type Normal
                        Unit - Remove ProximityDummies[(Integer A)] from the game
                        For each (Integer B) from (Integer A) to 8, do (Actions)
                            Loop - Actions
                                Set ProximityTargets[(Integer B)] = ProximityTargets[((Integer B) + 1)]
                                Set ProximityDummies[(Integer B)] = ProximityDummies[((Integer B) + 1)]
                        Set ProximityTargets[9] = No unit
                        Set ProximityDummies[9] = No unit
                    Else - Actions

But sometimes I'll cast the spell on my hero(puts a ProximityDummy on me) and walk next to a unit, and it will do nothing.

Its such an random glitch that I may have to send you the map.

Also, after the trigger has run a few times, and the dummies are removed, the trigger still runs sometimes because in game it says "Within range." even when there are no dummies left on the map.

If unit[x+1] = no unit, does unit[x] = unit[x+1] run?
 

The Undaddy

Creating with the power of rage
Reaction score
55
If you want,you can send me the map.Or you can post all triggers related to the spell :D.

You can add more messages to see exactly when it goes wrong.

>>If unit[x+1] = no unit, does unit[x] = unit[x+1] run?
Yes. then unit[x] is null and unit[x + 1] = unit[x + 2]

null u1 null u2 u3 -> u1 null u2 u3.
 

M4573R

New Member
Reaction score
1
After I put a bunch of them on myself, and get them to explode, so theres NONE on the map. If I get close to an enemy, it says "Within range." as many times as I've cast the spell.


Casting:
Code:
Cast
    Events
        Unit - A unit Starts the effect of an ability
    Conditions
        (Ability being cast) Equal to Proximity Bomb 
    Actions
        Set Saboteur = (Casting unit)
        For each (Integer A) from 0 to 9, do (Actions)
            Loop - Actions
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        ProximityDummies[(Integer A)] Equal to No unit
                    Then - Actions
                        Game - Display to (All players) the text: (String((Integer A)))
                        Set ProximityTargets[(Integer A)] = (Target unit of ability being cast)
                        Set ProximityPositionTemp = (Position of ProximityTargets[(Integer A)])
                        Unit - Create 1 ProximityBomb for (Owner of Saboteur) at ProximityPositionTemp facing Default building facing degrees
                        Set ProximityDummies[(Integer A)] = (Last created unit)
                        Trigger - Add to Explode <gen> the event (Unit - A unit comes within 256.00 of ProximityTargets[(Integer A)])
                        Custom script:   exitwhen true
                    Else - Actions
                        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            If - Conditions
                                (Integer A) Equal to 9
                            Then - Actions
                                Unit - Remove ProximityDummies[0] from the game
                                Trigger - Run ShiftArrayDown <gen> (ignoring conditions)
                                Set ProximityTargets[9] = (Target unit of ability being cast)
                                Set ProximityPositionTemp = (Position of ProximityTargets[9])
                                Unit - Create 1 ProximityBomb for (Owner of Saboteur) at ProximityPositionTemp facing Default building facing degrees
                                Set ProximityDummies[9] = (Last created unit)
                                Trigger - Add to Explode <gen> the event (Unit - A unit comes within 256.00 of ProximityTargets[9])
                            Else - Actions
        Trigger - Turn on PositionUpdate <gen>

Sort array:
Code:
ShiftArrayDown
    Events
    Conditions
    Actions
        For each (Integer B) from 0 to 8, do (Actions)
            Loop - Actions
                Set ProximityTargets[(Integer B)] = ProximityTargets[((Integer B) + 1)]
                Set ProximityDummies[(Integer B)] = ProximityDummies[((Integer B) + 1)]
        Set ProximityTargets[9] = No unit
        Set ProximityDummies[9] = No unit

Moving the unit:
Code:
PositionUpdate
    Events
        Time - Every 0.02 seconds of game time
    Conditions
    Actions
        For each (Integer A) from 0 to 9, do (Actions)
            Loop - Actions
                Unit - Move ProximityDummies[(Integer A)] instantly to (Position of ProximityTargets[(Integer A)])

Unit comes within range:
Code:
Explode
    Events
    Conditions
        ((Triggering unit) belongs to an enemy of (Owner of Saboteur)) Equal to True
    Actions
        Game - Display to (All players) the text: Within range.
        For each (Integer A) from 0 to 9, do (Actions)
            Loop - Actions
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        ProximityDummies[(Integer A)] Equal to No unit
                    Then - Actions
                        Custom script:   exitwhen true
                    Else - Actions
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        (Distance between (Position of (Triggering unit)) and (Position of ProximityDummies[(Integer A)])) Less than or equal to 256.00
                    Then - Actions
                        Game - Display to (All players) the text: Found match.
                        Set ProximityPositionTemp = (Position of ProximityDummies[(Integer A)])
                        Special Effect - Create a special effect at ProximityPositionTemp using Objects\Spawnmodels\Other\NeutralBuildingExplosion\NeutralBuildingExplosion.mdl
                        Unit Group - Pick every unit in (Units within 300.00 of ProximityPositionTemp matching (((Matching unit) belongs to an enemy of (Owner of Saboteur)) Equal to True)) and do (Actions)
                            Loop - Actions
                                Unit - Cause ProximityDummies[(Integer A)] to damage (Picked unit), dealing 150.00 damage of attack type Spells and damage type Normal
                        Unit - Remove ProximityDummies[(Integer A)] from the game
                        For each (Integer B) from (Integer A) to 8, do (Actions)
                            Loop - Actions
                                Set ProximityTargets[(Integer B)] = ProximityTargets[((Integer B) + 1)]
                                Set ProximityDummies[(Integer B)] = ProximityDummies[((Integer B) + 1)]
                        Set ProximityTargets[9] = No unit
                        Set ProximityDummies[9] = No unit
                    Else - Actions
 

The Undaddy

Creating with the power of rage
Reaction score
55
Code:
Explode
    Events
    Conditions
        ((Triggering unit) belongs to an enemy of (Owner of Saboteur)) Equal to True
    Actions
        Game - Display to (All players) the text: Within range.
        For each (Integer A) from 0 to 9, do (Actions)
            Loop - Actions
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        ProximityDummies[(Integer A)] Equal to No unit
                    Then - Actions
                        Custom script:   exitwhen true
                    Else - Actions
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        (Distance between (Position of (Triggering unit)) and (Position of ProximityDummies[(Integer A)])) Less than or equal to 256.00
                    Then - Actions
                        Game - Display to (All players) the text: Found match.
                        Set ProximityPositionTemp = (Position of ProximityDummies[(Integer A)])
                        Special Effect - Create a special effect at ProximityPositionTemp using Objects\Spawnmodels\Other\NeutralBuildingExplosion\NeutralBuildingExplosion.mdl
                        Unit Group - Pick every unit in (Units within 300.00 of ProximityPositionTemp matching (((Matching unit) belongs to an enemy of (Owner of Saboteur)) Equal to True)) and do (Actions)
                            Loop - Actions
                                Unit - Cause ProximityDummies[(Integer A)] to damage (Picked unit), dealing 150.00 damage of attack type Spells and damage type Normal
                        Unit - Remove ProximityDummies[(Integer A)] from the game
[B]                        Set ProximityTargets[(Integer A)] = No Unit
                        Set ProximityDummies[(Integer A)] = No Unit[/B]
                        For each (Integer B) from (Integer A) to 8, do (Actions)
                            Loop - Actions
                                Set ProximityTargets[(Integer B)] = ProximityTargets[((Integer B) + 1)]
                                Set ProximityDummies[(Integer B)] = ProximityDummies[((Integer B) + 1)]
                        Set ProximityTargets[9] = No unit
                        Set ProximityDummies[9] = No unit
                    Else - Actions

Try this ;)
I don't see anywhere setting the "targets" to null,so even if there is no dummy,there still is a target -> ?! :D
 

M4573R

New Member
Reaction score
1
But the array values at integer A are immediately getting overwritten by the value after it. I still get the same bugs. Its catching the event when units come with range even though the units don't exist anymore.
Perhaps a problem with the fact that I'm adding events dealing with a unit that I then delete?
 

The Undaddy

Creating with the power of rage
Reaction score
55
Actually,you don't remove the unit (target).Maybe you should change the event so that it deals with the dummies, which will then be removed and no longer trigger the event.Also,are you using NewGen?
 

M4573R

New Member
Reaction score
1
I'm using nothing, just pure world editor.

You're right, I changed the event and it fixed that part.

But I'll start up the map, cast on myself, walk next to an enemy, and nothing happens. I can move away and back and set of the trigger over and over, but it won't explode. Then if I'm standing next to someone and cast again, THEN they'll both go off.

EDIT: WOW. ARE YOU KIDDING ME!? Its a damn floating point calculation error. The trigger is for a range of 256, if I then pick all units within 300 instead of exactly 256 again, it works every time. I should have guessed this from the beginning. I normally always account for problems like this to be safe. The one time I don't....
GRRRRRRRRRRRRRRRR! WASTED HOURS!
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    New recipe is another summer dessert Berry and Peach Cheesecake - https://www.thehelper.net/threads/recipe-berry-and-peach-cheesecake.194169/

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top