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

How to make a unit damage a cone-shaped area in front?

Status
Not open for further replies.
Level 5
Joined
Jun 15, 2016
Messages
111
Read title. Basically, I want to modify that cone area as well, in degrees or anything.
What I really want it to result to is the only safe area is directly behind the unit.
 
Level 5
Joined
Jun 15, 2016
Messages
111
Sorry, I'm gonna give an example.
A unit casts an aoE spell which is triggered, and in the triggers, it will only affect those in a 180degree area in front of him, or some degree free to modify.
 
Level 5
Joined
Jun 15, 2016
Messages
111
With triggers it is more tricky as you need to filter a large area group enum search using the unit in rage of point native. This is because the standard area enum for units does not factor in collision size but WC3 abilities do.
does it require JASS? Because I'm about to give up on this objective if it does
 
Level 3
Joined
May 12, 2016
Messages
51
A unit group formed with matching units having a distance between it and the casting unit at less than or equal to desired max spell distance, and an angle between them of less than (unit facing + x) and greater than (unit facing - x), where 'x' is 1/2 of your cone vertex angle, then damage the picked units in the group?
 
Last edited:

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,197
A unit group formed at the midpoint of the 'cone' with matching units having an angle between them of less than (unit facing + x) and greater than (unit facing - x), where 'x' is 1/2 of your cone vertex angle, then damage the picked units in the group?
Does not factor in unit collision size, only origin. As I said the "best" solution is unfortunately not so simple. Also in such a case you would use cosine or sine for the comparison to avoid the 0 <-> 360 wrap around.
 
Level 4
Joined
Sep 13, 2014
Messages
106
Just pick every unit in a region in front of it, and then check the angle relative and distance relative to the unit. If it returns an angle between the correct values and a distance within the correct values, then apply the function. I could maybe explain in more detail if you want me to.

Basically how LimitingBounds said.

In reply to Dr Super Good, does it really matter that it only takes into account the origin of the units? Is he really likely to have units with a large enough hitbox that it is noticable? It isn't that hard to get around that, either, take 2arctan(collision radius) * dist and add it to the angle variance. Note: that is collision radius, and not diameter. But doing that is really unnecessary.

Also, to avoid 0 <-> 360, you would just take the angle difference add 180 Modulo 360 subtract 180, returning an equivalent angle difference between -180 and 180.
 
Last edited:
Level 9
Joined
May 21, 2014
Messages
580
Also take note if the spell is a breath-type. You need to use DDS to for this, and correct timing. There are also instances where the pre-picked unit is already out of the way of the breath spell (AKA he dodged it).

Im not great at making spells but... at least this is one factor you should consider.
 
One way in which you can do this without checking for angles is to use a DDS and a spell based on Breath of Frost (like blancfaye7 said). Since BoF applies a debuff to it's targets, you can create a custom buff for it and then check for that buff whenever a unit takes spell damage (Bribe's Damage Engine can detect spell damage). This will give you the units struck specifically by the custom BoF, but make sure to remove the buff, or else any consequent damage spell damage from whatever source will be thought to have come from a BoF.

That being said, checking for angle would be more accurate. It does get trickier if you want the cone damage to expand over time though. BoF can miss some of the units that are directly in front for your caster for some reason, could be a starting area thing.
 
Level 5
Joined
Jun 15, 2016
Messages
111
A unit group formed with matching units having a distance between it and the casting unit at less than or equal to desired max spell distance, and an angle between them of less than (unit facing + x) and greater than (unit facing - x), where 'x' is 1/2 of your cone vertex angle, then damage the picked units in the group?
Tried this, and it becomes sorta buggy and usually covers MORE (i mean MOREEEEE) than the desired angle
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,197
In reply to Dr Super Good, does it really matter that it only takes into account the origin of the units? Is he really likely to have units with a large enough hitbox that it is noticable? It isn't that hard to get around that, either, take 2arctan(collision radius) * dist and add it to the angle variance. Note: that is collision radius, and not diameter. But doing that is really unnecessary.
That is not how you do it... You use IsUnitInRange, IsUnitInRangeXY or IsUnitInRangeLoc to filter a larger search area. These natives factor in collision radius.

It is necessary as otherwise it will hit considerably fewer units than the targeting splat shows.
Also, to avoid 0 <-> 360, you would just take the angle difference add 180 Modulo 360 subtract 180, returning an equivalent angle difference between -180 and 180.
Or you use the properties of sine and cosine to avoid caring about the angle range.

Tried this, and it becomes sorta buggy and usually covers MORE (i mean MOREEEEE) than the desired angle
Which is why you apply a range check on the angle difference after pushing it through cosine or sine. Symmetrical and does not care if the angle wraps around. Also is faster because modulo is an emulated function (not native).
 
Level 4
Joined
Sep 13, 2014
Messages
106
IsUnitInRange, IsUnitI.. blah don't work with a conical area, though. Those only are useful for distance. 2arctan(collision radius) * dist is useful for angles. Although you would have to account for both.

I guess you could use sine or cosine to compare them, but you have to remember that angles behind the caster will return the same values as angles in front of the caster (or something like that, depending on the implementation). The sin method may be shorter, but I think with the modulo method you don't have to take into account as much.

Oops yeah for some reason I thought sin and cos were like tan and could be undefined, which is why quote.

Maybe DrSuperGood's method is slightly faster than this method, but anyway.

This is an example of detection of units in a cone:

  • IsUnitInCone
    • Events
      • Player - Player 1 (Red) types a chat message containing cone as An exact match
    • Conditions
    • Actions
      • -------- --------
      • -------- NOTE: THIS LEAKS A LOT, ITS JUST AN EXAMPLE --------
      • -------- --------
      • -------- Also, this doesn't take into account collision size for the angles --------
      • -------- --------
      • Unit Group - Pick every unit in (Units within 256.00 of (Position of Peasant 0000 <gen>)) and do (Actions)
        • Loop - Actions
          • Set relativeAngle = ((Facing of Peasant 0000 <gen>) - (Angle from (Position of Peasant 0000 <gen>) to (Position of (Picked unit))))
          • Set relativeAngle = (((relativeAngle + 180.00) mod 360.00) - 180.00)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • relativeAngle Less than 45.00
              • relativeAngle Greater than -45.00
              • (Picked unit) Not equal to Peasant 0000 <gen>
            • Then - Actions
              • Animation - Change (Picked unit)'s vertex coloring to (100.00%, 0.00%, 0.00%) with 0.00% transparency
            • Else - Actions
              • Animation - Change (Picked unit)'s vertex coloring to (0.00%, 100.00%, 0.00%) with 0.00% transparency
The result (with a few other minor triggers):

 
Last edited:

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,197
IsUnitInRange, IsUnitI.. blah don't work with a conical area, though. Those only are useful for distance. Mine is useful for angles. Although you would have to account for both.
Actually they do very much work for conical areas. All one needs to do is compute the correct position and correct distance to test.

This is done by performing vector projection of the relative unit vector onto the cone midpoint line to get the relative point to test from. This test point is clamped between the caster origin and the cone length. One then uses the scalar projection result of projecting the relative unit vector onto the cone midpoint line and normalize it by cone length to get the radius multiplier. This multiplier multiplies the end cone radius to get the test radius. IsUnitInRange is then applied on the unit using the calculated test point and test radius to result in collision perfect unit detection within a cone. Obviously the test point and test radius are a function of the unit being filtered so need to be computed for each unit tested. This algorithm performs perfect arc based unit filtering (opposite side is curved), which is often what people desire rather than a cone. For actual conical filtering extra logic is required to generate the flat edge, which involves a 0 test radius test from a test point computed from vector projection of the relative unit vector onto the opposite side of the cone.

I guess you could use sine or cosine to compare them, but you have to remember that angles behind the caster will return the same values as angles in front of the caster (or something like that, depending on the implementation).
Value equality is symmetrical on either side of the caster. Using cosine something behind the caster would return -1 and something in front of the caster would return 1. The symmetry property can be used to create a range test to detect an angle range to either side of the caster. For example testing if the value is greater than 0 will return true for all angles between -90 and 90 degrees of the caster, even if the angle being tested has suffered from wrap around such as -360, 360, 720 etc.

Also I don't know what happens in WC3 when the sine/cosine function returns undefined.
Sine and Cosine implementations are defined for every possible input. Even crazy ones like NaN should still return a value, even if that value is also NaN.

Mathematically both Sine and Cosine are defined for all real numbers. I am unsure about complex numbers but WC3 does not support those anyway. I think you are getting confused with tangent (tan) which is undefined at certain angles.
 
Level 4
Joined
Sep 13, 2014
Messages
106
Changed to cos implementation, yeah I think that is actually more elegant.

  • IsUnitInCone
    • Events
      • Player - Player 1 (Red) types a chat message containing cone as An exact match
    • Conditions
    • Actions
      • -------- --------
      • -------- NOTE: THIS LEAKS A LOT, ITS JUST AN EXAMPLE --------
      • -------- --------
      • -------- Also, this doesn't take into account collision size for the angles --------
      • -------- --------
      • Unit Group - Pick every unit in (Units within 256.00 of (Position of Peasant 0000 <gen>)) and do (Actions)
        • Loop - Actions
          • Set relativeAngle = ((Facing of Peasant 0000 <gen>) - (Angle from (Position of Peasant 0000 <gen>) to (Position of (Picked unit))))
          • Set relativeAngle = (Cos(relativeAngle))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • relativeAngle Greater than (Cos(45.00))
              • (Picked unit) Not equal to Peasant 0000 <gen>
            • Then - Actions
              • Animation - Change (Picked unit)'s vertex coloring to (100.00%, 0.00%, 0.00%) with 0.00% transparency
            • Else - Actions
              • Animation - Change (Picked unit)'s vertex coloring to (0.00%, 100.00%, 0.00%) with 0.00% transparency
The collision size thing still seems more trouble then it is worth.

Oh whoops and also I think I meant 2 arctan(collision radius / length)



So you get the amount of the vector to the affected unit in the direction of the cone (using dist cos angle), clamp it to keep it in the correct radius, save as test point. take the unit vector version by using cos angle, take the scale between 0 and 1 of this by dividing by cone length, then multiply this by some constant, and a test of the unit within the resultant radius of the test point.

Normalize has lots of different definitions o_O. I use the one that seems fitting.

Sounds like it would work. Pseudocode:

var =cos angle

var2 = dist * var

var2 = max(var2,0), min(var2,length)

point = polar(var2,angle)

var = var / length

var = var * constant

UnitWithinPoint(blah)

It's sort of annoying how (I believe) we can't get the collision radius of a unit, because we could skip all that by doing 2 arctan(collision radius / length)

 
Last edited:
Status
Not open for further replies.
Top