• 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.

Force unit to attack units within X range

Status
Not open for further replies.
Level 22
Joined
Jun 23, 2007
Messages
3,242
ok, so i have a spell called Accept Any Challenge, No Matter the Odds (yes its long)
anyways, when activated, the caster recieves a rather large armor bonus (20/25/30), but is forced to attack the closest enemy unit within X range of the hero. the player can change the target, cast spells, but the player CANNOT order the hero to move away from combat, (like issuing an order to a point). if he does, the hero will override that order and start attacking the closest unit. the hero is allowed to freely move when the buffs ends. if there are no enemy units within X range of the hero, the buff is removed.

now, i've gotten the armor part, but i have no idea on how to even begin the force attack part. i went to chat, but i feel it's too hard to explain something like this in chat, so i posted it here. can anyone help?
 
Level 37
Joined
Mar 6, 2006
Messages
9,243
Let me know if these triggers work to your liking:

  • SpellUsed
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to MySpell
    • Actions
      • Set TempLoc1 = (Position of (Casting unit))
      • -------- This is the radius inside which the possible tagets are picked from --------
      • Set TempReal1 = 512.00
      • -------- Add matching conditions with AND if needed. I assumed you don't want to attck your own units --------
      • Set TempGroup = (Units within TempReal1 of TempLoc1 matching ((Owner of (Matching unit)) Not equal to Player 1 (Red)))
      • -------- This section picks the closest unit --------
      • Unit Group - Pick every unit in TempGroup and do (Actions)
        • Loop - Actions
          • Set TempLoc2 = (Position of (Picked unit))
          • Set TempReal2 = (Distance between TempLoc1 and TempLoc2)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TempReal2 Less than or equal to TempReal1
            • Then - Actions
              • Set TempUnit = (Picked unit)
              • Set TempReal1 = TempReal2
            • Else - Actions
      • Custom script: call RemoveLocation(udg_TempLoc1)
      • Custom script: call RemoveLocation(udg_TempLoc2)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in TempGroup) Equal to 0
        • Then - Actions
          • -------- If no unit is inside the radius, nothing happens --------
          • Custom script: call DestroyGroup(udg_TempGroup)
        • Else - Actions
          • -------- If there are units inseide the radius, turn on these triggers --------
          • Trigger - Turn on Loop Attack <gen>
          • Trigger - Turn on Change Target <gen>
          • Custom script: call DestroyGroup(udg_TempGroup)
          • -------- The duration of the spell --------
          • Wait 10.00 seconds
          • Trigger - Turn off Loop Attack <gen>
          • Trigger - Turn off Change Target <gen>
          • Unit - Order (Casting unit) to Stop
  • Loop Attack
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • -------- Orders your unit to constantly attack the picked unit --------
      • Unit - Order MyUnit to Attack TempUnit
  • Change Target
    • Events
      • Unit - A unit Is issued an order targeting an object
    • Conditions
      • (Triggering unit) Equal to MyUnit
    • Actions
      • -------- Allows you to change the target --------
      • Set TempUnit = (Target unit of issued order)
This is not MUI or MPI, since you didn't mention needing that. This only works for a single unit, and when the spell's cooldown is shorter than it's duration.
 
Level 22
Joined
Jun 23, 2007
Messages
3,242
well, ur trigger works, but after the duration of the buff/wait, myunit just kinda... slowly slides along the ground, and will only attack properly. it seems that i cannot cast other spells while this is up, and i need the hero to be able to cast other spells.
i would like it for to MPI, but MUI is no neccassary.
sorry if i sound like a really picky prick right now, but i kinda wanna get this right.
 
Level 37
Joined
Mar 6, 2006
Messages
9,243
  • Spell
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to MySpell
    • Actions
      • Set TempLoc1 = (Position of (Casting unit))
      • -------- This is the radius inside which the possible tagets are picked from --------
      • Set TempReal1 = 512.00
      • -------- Add matchinf conditions with AND if needed. I assumed you don't want to attck your own units --------
      • Set TempGroup = (Units within TempReal1 of TempLoc1 matching ((Owner of (Matching unit)) Not equal to (Owner of (Triggering unit))))
      • -------- This section picks the closest unit --------
      • Unit Group - Pick every unit in TempGroup and do (Actions)
        • Loop - Actions
          • Set TempLoc2 = (Position of (Picked unit))
          • Set TempReal2 = (Distance between TempLoc1 and TempLoc2)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TempReal2 Less than or equal to TempReal1
            • Then - Actions
              • Set TempUnitArray[(Player number of (Owner of (Triggering unit)))] = (Picked unit)
              • Set TempReal1 = TempReal2
            • Else - Actions
      • Custom script: call RemoveLocation(udg_TempLoc1)
      • Custom script: call RemoveLocation(udg_TempLoc2)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in TempGroup) Equal to 0
        • Then - Actions
          • -------- If no unit is inside the radius, nothing happens --------
        • Else - Actions
          • -------- If there are units inseide the radius, turn on these triggers --------
          • Trigger - Turn on Loop Attack <gen>
          • Trigger - Turn on Change Target <gen>
          • Trigger - Turn on Do Spell <gen>
          • Set AbilityUnitArray[(Player number of (Owner of (Triggering unit)))] = (Triggering unit)
      • Custom script: call DestroyGroup(udg_TempGroup)
  • Loop Attack
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Set TempInt = 0
      • -------- Orders your unit to constantly attack the picked unit --------
      • For each (Integer A) from 1 to 12, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • AbilityUnitArray[(Integer A)] Equal to No unit
            • Then - Actions
              • Set TempInt = (TempInt + 1)
            • Else - Actions
              • Unit - Order AbilityUnitArray[(Integer A)] to Attack TempUnitArray[(Integer A)]
              • Set TempIntCounter[(Integer A)] = (TempIntCounter[(Integer A)] + 1)
              • -------- 10 seconds per 0.03 seconds is 333 --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • TempIntCounter[(Integer A)] Equal to 333
                • Then - Actions
                  • Set TempIntCounter[(Integer A)] = 0
                  • Unit - Order AbilityUnitArray[(Integer A)] to Stop
                  • Set AbilityUnitArray[(Integer A)] = No unit
                • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • TempInt Equal to 12
        • Then - Actions
          • Trigger - Turn off (This trigger)
          • Trigger - Turn off Change Target <gen>
        • Else - Actions
  • Change Target
    • Events
      • Unit - A unit Is issued an order targeting an object
    • Conditions
    • Actions
      • -------- Allows you to change the target --------
      • For each (Integer A) from 1 to 12, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Triggering unit) Equal to AbilityUnitArray[(Integer A)]
            • Then - Actions
              • Set TempUnitArray[(Integer A)] = (Target unit of issued order)
              • Skip remaining actions
            • Else - Actions
  • Do Spell
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
    • Actions
      • For each (Integer A) from 1 to 12, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Triggering unit) Equal to AbilityUnitArray[(Integer A)]
            • Then - Actions
              • Set AbilityUnitArray[(Integer A)] = No unit
              • Set PlayerIntArray[(Player number of (Owner of (Triggering unit)))] = (Integer A)
            • Else - Actions
      • Wait 0.35 seconds
      • Set AbilityUnitArray[PlayerIntArray[(Player number of (Owner of (Triggering unit)))]] = (Triggering unit)
      • Trigger - Turn on Loop Attack <gen>
      • Trigger - Turn on Change Target <gen>
It should be MPI now. I tested with Player 1 and Player 2 and it seemed to work. You can also cast other spells now, although I didn't test that too much. I tried with Mountai King's Thunder Clap, and he was able to cast it and then returned to normally attack the target. You may need to adjust the wait in the last trigger to be enough for the unit to have time to cast the spell. Let me know if something doesn't work right :)
 
Level 22
Joined
Jun 23, 2007
Messages
3,242
everything looks good, got sufficient time in the wait to cast other spells, very well done. i dont know how you guys do this kind of stuff. +rep
edit: quick question, wheres the variable that determines the length of the forced attack? or did u remove it?
 
Level 37
Joined
Mar 6, 2006
Messages
9,243
The length of the spell is now determined in the Loop Attack trigger.

The trigger runs every 0,03 seconds, and adds +1 to a counter that calculates how many times the trigger is run for every unit that is under the spell. Being run every 0,03 seconds means that it runs 1/0.03=33,333...times per second. After ten seconds, the trigger has ran 333,33...times. So just change that number as you see fit.

TimeInSeconds x (1/0,03) = The number you compare TempIntCounter[(Integer A)] to.

I just noticed a small bug there. If you use other spells, then the duration of the spell is longer than what you set it to. It does not count the time you spend casting other spells.

You can fix it to some extent by using a boolean in the Do Spell trigger, and then checking the boolean in Loop Attack. If some other spell is used, set the boolean (use array) to true in Do Spell. Then in Loop Attack check it with IF/THEN/ELSE, and if it's true, add 0.35/0.03 = 11,666 (The wait time divided by Loop Attack's update time) to the unit's TempIntCounter. And maybe a bit extra to compensate for the casting time.

Another, maybe even better solution is to use

Set AbilityUnitArray[(Integer A)] = DummyUnit
instead of
Set AbilityUnitArray[(Integer A)] = No unit

Make the dummy unit unable to move, and position him somewhere no-one can see or get to. Then the timer counter still updates even when you're using other spells.


I've also used 12 in for loops, but set it to the number of players to save some CPU time.
 
Level 22
Joined
Jun 23, 2007
Messages
3,242
ok, im still a tad confused on the duration thing though. like, what numbers should i put in for, lets say, the duration to be 10?
edit: found out why my hero would "slide", whenever he kills an enemy unit, he'll slide to that corpse if its closer than another unit, and he'll just stay there until manually ordered to attack, or until the buff wears off. i've tried to fix this by checking if tempunitarray has more than 0 health, but i think im doing something wrong cause it doesnt work. also, for some reason, if there are nearby corpses and no alive enemy units, then the hero will move towards some random corpse

edit2: ack, the hero attacks friendlies. even if i change the condition in the main trigger.
 
Last edited:
Level 37
Joined
Mar 6, 2006
Messages
9,243
The loop trigger runs 33 times per second. So ten seconds duration -> 333. 8 seconds duration -> 33*8 = 266. And so on.

I can't test the trigger right now, but try this:

  • Set TempGroup = (Units within TempReal1 of TempLoc1 matching ((((Owner of (Triggering unit)) is an enemy of (Owner of (Matching unit))) Equal to True) and (((Matching unit) is alive) Equal to True)))
It should prevent the unit from attacking allies or corpses.
 
Level 22
Joined
Jun 23, 2007
Messages
3,242
well, i dont really need it to be mui, just mpi. thnx maker, ill test it later.
edit: ok tested, but he still slides whenever he kills a unit and if the corpse is closer than another unit. i think its related to loop attack, since he's not transitioning properly
if you want, ill add a replay to show you what i mean.
 
Last edited:
Status
Not open for further replies.
Top