"Cone" type attack

staind25

TH.net Regular
Reaction score
7
I'm using triggers to try to create a "cone" of damage in front of the caster, much like "Cone of Cold" in World of Warcraft (I don't think such a thing exists in WC3...if it does, please let me know).

Anyways, it's pretty easy to cause damage in a rectangular region, but how do I go about doing a cone? I've tried a ton of different things and can't get it. Basically, I'm using Temp variables, then using a "Pick every unit in region..." etc and dealing damage to that region.

Here are some examples of what I've tried:

Points (Both are used):

Trigger:
  • Set TempPoint = (Position of (Triggering unit))
    • Set TempPoint2 = (TempPoint offset by 200.00 towards ((Facing of (Triggering unit)) + 45.00) degrees)


For TempPoint2, my idea was to create a point at a 45 degree angle away from the caster, then from this point, create a region that goes from the point, to the caster, and then to another point...something that would look like this:

*--------*
.. \ ..... /
.... (c)

With (c) being the caster, the left * being TempPoint2, the lines showing the approximate edge of the region, and the right * being a corner of the region (The periods were used to allow for spacing...without them, the other characters wouldn't space over).

Regions (Only need one, but each goes about creating the region in a different way...neither worked that well):

Trigger:
  • Set TempRegion = (Region centered at TempPoint2 with size (550.00, 400.00))


Trigger:
  • Set TempRegion = (Region((X of TempPoint2), 0.00, (X of TempPoint), ((Y of TempPoint2) + 90.00)))


For the last region, that's the first time I've used the coordinates, so maybe I'm not using it correctly. See my terrible drawing above for a little more clarity in what I'd like, and maybe you could help me get the coords correct :)

And, just for additional clarity, here's where the "Damage" comes from:

Trigger:
  • Unit Group - Pick every unit in (Units in TempRegion matching ((((Matching unit) is alive) Equal to True) and ((((Matching unit) is A structure) Equal to False) and ((((Matching unit) belongs to an enemy of (Owner of (Triggering unit))) Equal to True) or (((Matching unit) belongs to an ally and do (Actions)
    • Loop - Actions
      • Unit - Cause (Triggering unit) to damage (Picked unit), dealing 800.00 damage of attack type Spells and damage type Cold


This problem is difficult to describe, so I apologize if I wasn't clear enough...but let me know if you have any questions.

Thanks for your time!
 

Ashlebede

New Member
Reaction score
43
You don't need regions. When you pick units in range of the caster, you'd need to check the angle between the caster and the Matching unit.

Units Matching (Angle between Caster and Matching unit - Angle between Caster and target point < 22.5) AND (Angle between Caster and Matching unit - Angle between caster and target point > -22.5)

Never tested it. Maybe it doesn't work for directions too close to east (since east in 0 degrees...)
 

staind25

TH.net Regular
Reaction score
7
Edit 3: I discovered a problem. The angle between TempPoint and TempPoint2 changes depending on which way the caster is facing. I would think this angle should always be zero, considering TempPoint2 is directly forward of TempPoint facing the same angle. I either need to fix this (Not sure how), or find a different way of using your "target point" (Didn't know what else to use besides TempPoint2).
 

hopy

Active Member
Reaction score
64
I do believe Flame Breath or Breath of Flames or something like that is a cone, and for lines you could use Impale and pick units with a custom buff.


Another way to do this is:
Trigger:
  • Cone
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Cone
    • Actions
      • Set Point = (Position of (Triggering unit))
      • Set Point2 = (Point offset by 250.00 towards (Facing of (Triggering unit)) degrees)
      • Set Unit_Group = (Units within 300.00 of Point2 matching ((((Matching unit) has buff Invulnerable) Equal to False) and (((Matching unit) belongs to an enemy of (Owner of (Triggering unit))) Equal to True)))
      • Custom script: call RemoveLocation (udg_Point2)
      • Unit Group - Pick every unit in Unit_Group2 and do (Actions)
        • Loop - Actions
          • Unit - Create 1 Dummy Unit for (Owner of (Triggering unit)) at Point facing Default building facing degrees
          • Unit - Add Cone [Dummy] to (Last created unit)
          • Unit - Set level of Cone [Dummy] for (Last created unit) to (Level of Cone for (Triggering unit))
          • Unit - Order (Last created unit) to Human Mountain King - Storm Bolt (Picked unit)
          • Unit - Add a 3.00 second Generic expiration timer to (Last created unit)
          • Custom script: call DestroyGroup(udg_Unit_Group2)
      • Custom script: call DestroyGroup(udg_Unit_Group)
      • Custom script: call RemoveLocation (udg_Point)


This would get you a: (X = Hero, (.) = Targeted area).
..(.)
...X
Shape, not realy a cone but easy enough.

Another way you could use is:
Trigger:
  • Cone
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Cone
    • Actions
      • Set Point = (Position of (Triggering unit))
      • Set Unit_Group = (Units within 400.00 of Point matching ((((Matching unit) has buff Invulnerable) Equal to False) and (((Matching unit) belongs to an enemy of (Owner of (Triggering unit))) Equal to True)))
      • Unit Group - Pick every unit in Unit_Group and do (Actions)
        • Loop - Actions
          • Set Point2 = (Position of (Picked unit))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • And - All (Conditions) are true
                • Conditions
                  • (Angle from Point to Point2) Less than or equal to ((Facing of (Triggering unit)) + 45.00)
                  • (Angle from Point to Point2) Greater than or equal to ((Facing of (Triggering unit)) - 45.00)
            • Then - Actions
              • Unit Group - Add (Picked unit) to Unit_Group2
            • Else - Actions
          • Custom script: call RemoveLocation (udg_Point2)
      • Custom script: call DestroyGroup (udg_Unit_Group)
      • Unit Group - Pick every unit in Unit_Group2 and do (Actions)
        • Loop - Actions
          • Set Point2 = (Position of (Picked unit))
          • Unit - Create 1 Dummy Unit for (Owner of (Triggering unit)) at Point2 facing Default building facing degrees
          • Unit - Add Cone [Dummy] to (Last created unit)
          • Unit - Order (Last created unit) to Human Mountain King - Storm Bolt (Picked unit)
          • Unit - Add a 2.00 second Generic expiration timer to (Last created unit)
          • Custom script: call RemoveLocation (udg_Point2)
      • Custom script: call DestroyGroup (udg_Unit_Group2)
      • Custom script: call RemoveLocation (udg_Point)

Both triggers:
- Cone is the hero ability, based on Flame Breath.
- Cone [Dummy] is the dummy ability based on Storm Bolt.
- Point and Point2 are Point Variable.
- Unit_Group and Unit_Group2 are Unit Group variable.

I haven't tested them, but I'm pretty sure all of the above should work.
 

Ashlebede

New Member
Reaction score
43
Hopy's first solution is still not a cone, though. If you wanted to stun or make the damage depend on stats or something, the second solution wouldn't work, either.

Now, I have here a trigger that does kill every unit in a cone direction. However, unlike what I thought, it does work for the East direction, but not for the West direction...:nuts:

Anyways, I tested it, and that's what I got :

Trigger:
  • MyTrigger Copy
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to MySpell
    • Actions
      • Set loc = (Target point of ability being cast)
      • Set loc2 = (Position of (Triggering unit))
      • Set group = (Units within 800.00 of loc2 matching ((((Angle from loc2 to (Position of (Matching unit))) - (Angle from loc2 to loc)) Greater than or equal to -22.50) and ((((Angle from loc2 to (Position of (Matching unit))) - (Angle from loc2 to loc)) Less than or equal t
      • Unit Group - Pick every unit in group and do (Actions)
        • Loop - Actions
          • Unit - Kill (Picked unit)
      • Custom script: call DestroyGroup(udg_group)
      • Custom script: call RemoveLocation(udg_loc)
      • Custom script: call RemoveLocation(udg_loc2)


Currently trying to find a fix for that West direction.
 

staind25

TH.net Regular
Reaction score
7
Thanks hopy...if I can't get my current trigger to work, I'll check out that base ability :)

Interesting results, Ashlebede. Thanks for taking the time to test and all...I appreciate it. The angle issue is weird...I'm not sure I understand why it doesn't work in a certain direction. It shouldn't depend on which way the unit is facing, because the +/- 22.5 is just a number without a "degrees" quality associated with it...shouldn't the game just measure the actual angle, rather than the angle relative to the way the game interprets direction?

Oh by the way, the spell is an instant (no target) cast...you shouldn't have to click a target...which kind of changes your "loc" variable. How do you get around this?
 

Ashlebede

New Member
Reaction score
43
hmm... yes, it would be [ljass]GetUnitFacing()[/ljass] or its GUI equivalent to find the angle. You could make this, though (custom script) :



Forgetful as I am, there probably is a major error in my script.

+/- 22.5 is just a number without a "degrees" quality associated with it

However, the number goes from 0 to 360. So when you check angles and the substraction/addition gave a number under 0 or over 360, whatever result it gave will be invalid.

350, for instance, will only have 10 degrees up instead of 22.5.
 

staind25

TH.net Regular
Reaction score
7
Is there a GUI equivalent to that? I'm not sure I understand the JASS.

Ah I get it. I just tested that and I see what you mean...

But yeah, it does seem to work for everything except facing exactly west. Since the only unit in my map that'll be using this ability is a boss, I might be able to work with this, actually. It's not perfect, and I want to find a solution, but it would probably work even without a solution.

Thanks for your continued help.
 

hopy

Active Member
Reaction score
64
Ow, I just found another standard ability that IS a cone attack! :D
Forked Lightning:
Calls forth a cone of lightning on a target enemy unit, hitting up to x enemy units for y damage.
 

Ashlebede

New Member
Reaction score
43
Just copy/paste that custom script and it'll set a variable named "loc" to Location of unit + 128 towards where it's facing. (It uses trigonometry. o_O)

It's like "Point with polar offset".

You still have to remove the location to avoid leaks, though.

You could always make a condition for the west... check if ((Angle+22.5>180) and (Angle<180) ) or ((Angle-22.5<180) and (Angle>180)) or something like that works. Maybe replace 180 with 0...

Edit : Just realized there's an easy way... just make a modulo on the result of the substraction/addition and you should have a valid result for any angle... I think...
 

staind25

TH.net Regular
Reaction score
7
Thanks again hopy...I still want to try to figure out the triggered version first (Since I've put like 2 hours into it), but if that doesn't work, I'll try Forked Lightning :)

Alright. My only issue with not understanding the JASS is if something messes up, I don't know how to fix it / don't know what's wrong. I can understand the trig fine, but I can only take educated guesses at the code's meaning. But...with my current trigger...do I even need the custom script? I seemed to make it work as well as you did (Everything except the "west" direction) but without the trig. Do I need the trig?

The +128 makes me curious. Would you mind explaining how you came up with your numbers? It's funny, I was doing something similar for the special effects (Trying to get the effects in the same "cone" shape)...and through a lot of algebra I figured it out, but since the game doesn't register angles over 360 degrees, it didn't work :( Here's what I did there:

Trigger:
  • For each (Integer B) from 4 to 12, do (Actions)
    • Loop - Actions
      • Special Effect - Create a special effect at (TempPoint offset by 500.00 towards (((Real((Integer B))) x 5.00) + ((Facing of (Triggering unit)) + 320.00)) degrees) using Abilities\Spells\Other\CrushingWave\CrushingWaveMissile.mdl


Originally Integer B went from -4 to 4 (The formula was different). My thought process there was that it would go directly out from the caster, then a few degrees clockwise, and a few degrees counter-clockwise...but I found out that it'll only go in the counter-clockwise direction. From there, I discovered the current formula (With a flat sum of +320 degrees) that would include the "clockwise" angles as if they were wrapped around the circle once more...but of course this puts the angle in the 500's and 600's, so it didn't work. The special effects are still just a little bit off-center.

I don't necessarily need a solution for that...I just thought I might've been on the right track but didn't know enough to figure it out entirely.

As for the west issue...I found the modulo, but I have no idea how to use it...I'll experiment a little though. If I can't figure that out though, I could probably manage the whole "reference angle" stuff.

Thanks again. Apologies for this post getting a little long. Feel free to ignore the special effects section...that's more or less curiosity.
 

Ashlebede

New Member
Reaction score
43
If it works fine, don't use it. 128 is simply melee range, a relatively short range that is long enough, nonetheless.

A modulo is what's left after an integer division. In programming, we usually represent it by %. In WC3, there are functions for modulos.

For instance, 5/2 will give 2 if it is an integer. (the smallest integer before the result, which is 2.5)

5%2 will give 1 ; that's how much is left after the division (or 5-2*2=1).

I'm really bad at explaining. >_>
 

staind25

TH.net Regular
Reaction score
7
Ah okay.

Yeah I vaguely remember using it when studying the Python tutorial (I'm brand new to programming...but I'm pursuing a Computer Science major this fall...so it interests me, but I don't know a whole lot), but I don't remember it being referred to as a "modulo"...but just before reading your response, I did some searching and had just figured this much out XD Your explanation is great.

What I'm not sure about though is how the modulo is useful for the angle situation. How does calculating the remainder help fix the west issue? An example would be great :D But who knows, I may figure it out within the next 10 minutes...haven't had too long to look at it yet.
 

Ashlebede

New Member
Reaction score
43
You'd actually have to make an integer division. Let's take our other example where the variation is 350. We'd have to remove (350+22.5)/360 = 1 (as an integer division).

So we have to do 350+22.5-360 = 12.5;

Then we can take all the units with the angle under 12.5 as well as all those that have an angle between 360 and (350-22.5).

That would be a fix.
 

staind25

TH.net Regular
Reaction score
7
Ah that makes sense. Not sure how to put it in WC3 terms though. How do you use the modulo to make an integer division?

If I understand correctly, it would be something like:

If (Angle subtraction) > 360, subtract 360.
If (Angle subtraction) < 0, add 22.5

But somehow that looks too simple.
 

Ashlebede

New Member
Reaction score
43
The simplest way to make an integer division is to store the result in an integer variable. Logically, it can only be floored, since it cannot have any decimal values.
 

staind25

TH.net Regular
Reaction score
7
Would you mind giving me a trigger example of how this would work? I'm not understanding how exactly I need to use the integer division, etc.

Edit: I think I may have found something that will work once I incorporate a modulo into it. I changed the subtraction formula. Now it's:

Angle from TempPoint to (Position of (Matching Unit)) - (Facing of (Triggering Unit))

The only problem is, let's say a matching unit is directly in front of TempPoint, and both TempPoint and matching unit are at 230º. The problem is, the game picks this up as -130º for some reason. Then when it takes -130 and subtracts the 230 off of it, you get -360º. Of course, this is the same as there being a 0º angle between the matching unit and TempPoint, which is true, but I have to tell the game that...and that's when I finally realized why the modulo is useful, haha. No one understands math until it becomes useful to them, eh?

Now I'm just working on the rather complicated list of operations it has to carry out. I know what I want it to do, but getting it in WC3 editor terms is difficult.
 

Ashlebede

New Member
Reaction score
43
Well, let me check if there's a GUI function for Modulo...

Trigger:
  • Set real = ((350.00 + 22.50) mod 360.00)


Yes, there is. It's Math - Modulo.

Trigger:
  • Actions
    • Set group = (Units within 800.00 of (Position of (Triggering unit)) matching (((Angle from (Position of (Triggering unit)) to (Position of (Matching unit))) Less than or equal to ((Angle from (Position of (Triggering unit)) to (Target point of ability being cast)) + 22.5
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • ((Angle from (Position of (Triggering unit)) to (Target point of ability being cast)) + 22.50) Greater than or equal to 360.00
        • (Angle from (Position of (Triggering unit)) to (Target point of ability being cast)) Less than or equal to 360.00
      • Then - Actions
        • Set group2 = (Units within 800.00 of (Position of (Triggering unit)) matching (((Angle from (Position of (Triggering unit)) to (Position of (Matching unit))) Less than or equal to ((Angle from (Position of (Triggering unit)) to (Target point of ability being cast)) mod 360.00))) and ((Angle from (Position of (Triggering unit) to (Target point of ability being cast)) Greater than or equal to 0)
        • Unit Group - Add all units of group2 to group
      • Else - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • ((Angle from (Position of (Triggering unit)) to (Target point of ability being cast)) - 22.50) Less than or equal to 0.00
            • (Angle from (Position of (Triggering unit)) to (Target point of ability being cast)) Greater than or equal to 0.00
          • Then - Actions
            • &lt;Same as other condition&gt;
          • Else - Actions


Edit : Well, wrote that a lil' too late, I guess... ^_^
 

staind25

TH.net Regular
Reaction score
7
Haha, sorry about that...I had just happened to find a way that made more sense in my mind, so I used what I knew how to manipulate, if that makes sense. It's actually pretty short. I just got it to work, and it also works in the west direction.

I actually didn't need the modulo, surprisingly. I could've used it, but I think in the end it would've made the trigger more complicated. Here's what I did, if you're curious:

Trigger:
  • Actions
    • Set TempPoint = ((Position of (Triggering unit)) offset by 0.00 towards (Facing of (Triggering unit)) degrees)
    • Set TempPoint2 = (TempPoint offset by 500.00 towards (Facing of (Triggering unit)) degrees)
    • Set TempUnitGroup = (Units within 500.00 of TempPoint)
    • Unit Group - Pick every unit in TempUnitGroup and do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • Or - Any (Conditions) are true
              • Conditions
                • (((Angle from TempPoint to (Position of (Picked unit))) - (Facing of (Triggering unit))) Greater than or equal to -382.50) and (((Angle from TempPoint to (Position of (Picked unit))) - (Facing of (Triggering unit))) Less than or equal to -337.50)
                • (((Angle from TempPoint to (Position of (Picked unit))) - (Facing of (Triggering unit))) Greater than or equal to -22.50) and (((Angle from TempPoint to (Position of (Picked unit))) - (Facing of (Triggering unit))) Less than or equal to 22.50)
                • (((Angle from TempPoint to (Position of (Picked unit))) - (Facing of (Triggering unit))) Greater than or equal to 337.50) and (((Angle from TempPoint to (Position of (Picked unit))) - (Facing of (Triggering unit))) Less than or equal to 382.50)
          • Then - Actions
            • Unit - Cause (Triggering unit) to damage (Picked unit), dealing 800.00 damage of attack type Spells and damage type Cold
            • Game - Display to (All players) the text: (String(((Angle from TempPoint to (Position of (Picked unit))) - (Facing of (Triggering unit)))))
          • Else - Actions
            • Do nothing
    • Custom script: call RemoveLocation( udg_TempPoint )
    • Custom script: call RemoveLocation( udg_TempPoint2 )
    • Custom script: call DestroyGroup( udg_TempUnitGroup )


It's not complete...I still need to add more conditions and the special effects (Which I'm sure I'll have issues with like I did before), but as far as I can tell, the actual cone works as intended.

Come to think of it, the trigger you came up with looks very similar to mine, haha.

I guess for now all I have to say is thank you very much for your help...I learned a ton because of this topic...and I'm sure I'll have more questions when I get around to the special effects (I need a break first though...been staring at the screen nonstop).
 

Ashlebede

New Member
Reaction score
43
Well, all I have to say is : " Remove that [ljass]Do Nothing[/ljass], since the computer actually searches in the map's script for a function that does nothing. "
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      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