-
Notifications
You must be signed in to change notification settings - Fork 224
Fix determining relative entity positions, angles, and conal attacks #1402
Conversation
…ese to fix breaths, Sneak Attack, Overwhelm, Ambush, Yonin, Innin, and Closed Position
…on + increase allowable breath attack arc (based on Fafnir retail capture)
Hitting target at almost 90 degrees to the right ("360 scale"): Exact cone angle (two Dragon Breaths back-to-back): |
Nice stuff!
I'm not sure if this is different for each type of breath attack, or maybe it's a difference based on if it's a mob conal vs a player conal, but I tested this extensively with BLU spells, and found that the cone does have its center at the face of the caster -- not the primary target like you have concluded. I'd love to compare notes and go through the data together! |
Looking like we'll have to define and use flags to determine the center of a cone~ |
After talking it over with Ino a bit (and seeing a very illuminating video), I've set conal centers back to be mob facing. They'll still hit off-face primary targets like in the Fafnir video, but additional targets will treat the mob's rotation as the center. More Fafnir testing may be in the future. |
I wanted to open this as a Pull Request to have more eyes on checking it. But what I haven't mentioned until now is that the explicit purpose of this rework was initially to resolve an exploit in which players could cause HNM wyrms to deal almost no damage from breaths. According to wikis, breath attacks are supposed to deal less damage depending on the target's distance from the center of the cone. These breaths were previously implemented like so: local angle = mob:getAngle(target)
angle = mob:getRotPos() - angle
dmgmod = dmgmod * ((128-math.abs(angle))/128)
dmgmod = utils.clamp(dmgmod, 50, 1600) Let's take a step though this, referencing the image on the old getangle above. Remember that rotations start at 0 and wrap around back to zero at 255, going clockwise. So let's say that you're fighting Fafnir, and knowing this exploit, you cause Fafnir to face roughly due E (rotation zero). This can be precisely rotation zero, but for safety you can have it be a little south, so let's say rotation 1. If you then stand slightly north of due east, relative to Fafnir, you'll be at angle 255, since the return of Fafnir is facing 1, you're at 255. Well, that's bad. Fafnir is going to be healing you for just about the full amount of damage it's trying to do! We're "saved" by the clamp though: So instead of outright healing you - and being a much more obvious bug - Dragon Breath instead does only 50 damage. I know players encourage Dragon Breaths instead of Spike Flails, but this isn't quite the reason why. 😉 Public server operators should have been informed that this was an exploit fix. If you're a public server operator who didn't know this comment was coming, get in touch with either zach2good or myself on Discord. |
^ No really, you don't stand a chance of understanding the changes in this PR until you have~!
Currently, everything relating to positions will encounter issues at Rotation 0 (due East). This all stems from one little lie told in the documentation for
getangle
:That is not what getAngle did at all.
What
getangle
was returning was the "world angle" between two entities - not a facing angle. It was also using a different scale than advertised. This leads to some problems:We also had places which weren't even using getangle - but instead subtracting two raw rotations from each other - which caused them to suffer from the "rotation overflow" problem above.
(Note: This was reported in DarkstarProject/darkstar#6415)
Naturally, this is all very no bueno. So I made
getangle
into the more specificgetWorldAngle
, which serves the same functional purpose thatgetangle
actually did. As a nice bonus I threw in, it now lets you optionally pass in a custom number of degrees to scale to, provided that they're a multiple of 4.BOLD FOR EMPHASIS: You can now get the world angle between two entities on a custom scale. 4 = NESW, 8 adds NE, SE, SW, and SE. Increase for additional cardinal axis. This means you, Ballista Rooks, VWNMs, and Geomancer!
Afterwards I added
getFacingAngle
to do what the previousgetangle
advertised, and several positioning arc functions likeisInfront
,isBeside
, andisBehind
. Each of the positioning functions can take a custom angle (always 256 scaled), but will otherwise use a default of 64 (equivalent to 90 degrees on "360 scale").So then came changes to conal attacks. Wikis claim that damage drops from the center line of the cone. So I wrote a new lua utility function to handle that. It takes a "minimum percentage" argument, which is, well, the minimum damage you'll take if you're hit with that breath attack at its farthest end. The closer you are to the damage line of the attack, the closer you'll get to taking the passed-in max damage.
I couldn't find any sources on how this "damage reduction if you're farther away" is calculated. I'm a skeptic, so at the moment I'm not convinced it's real. So I set all dragon breath attacks to have a minimum percentage of 90% because I'd rather damage be overtuned than undertuned! Normally in this circumstance I'd keep it at 100%, but I wanted to illustrate that the damage adjustment function works and how. Servers can set each breath's minimum percentages to their taste.
Due to what has been ingrained in all of us - "stand on the paws" - there were some questions to how these breaths worked. Why are we standing on the paws? Do we dodge damage? Do we reduce damage? Hopefully by now everyone knows the dangers of myths. @zach2good and @UynGH did a video test on retail, and they produced this one beautiful image which shows a lot.
That's Nyu, who had hate, getting hit with Dragon Breath while almost 90 degrees ("360 scale") to Fafnir's right. You can see it targeting him in Zach's log, and Nyu being on fire from the animation. Also notice that Zach wasn't hit.
Dragon Breath can be used on someone so long as they're within the front 180 degrees ("360 scale") of the mob.
Additional targets are based on the conal fan from the primary target - not the mob's face. This matches a TODO in targetfind's findWithinCone.(There is a video of this, but I won't publicly link it here. You might be able to ask Zach on Discord if you don't believe me.)
With the help of a new additional utility function (relativeAngle
), targets are now hit based on the primary target instead of where the mob is facing.(Edit: See later comments; I reverted the above back to additional targets from the mob's face.)
This presented a problem for breath damage reduction, which will need to be solved later. It'd require a pretty massive restructuring of how mob skills work. When targets get hit with a skill, the lua script is executed individually on each one, with no methods of storing arbitrary data about what the skill did to others - like the primary target's world angle. So while the targets hit are correctly selected, the "center damage line" used for breath damage reduction is unfortunately still the mob's face. Keep this in mind when adjusting minimum damage percentages.
I affirm: