Add raid_events=absorb#11435
Conversation
4803c2a to
58a8482
Compare
|
Pushed an update: added a This was originally scoped as a follow-up but I'm pulling it into this PR because a planned class-module follow-up (Voidweaver's Devour Matter) needs to gate an APL line on shield presence, and the expression is the cleanest way to expose that. Three lines added next to the No diff impact on the rest of the PR. |
| if ( incoming_state->result_absorbed > 0.0 ) | ||
| { | ||
| actual_amount = resource_loss( RESOURCE_HEALTH, incoming_state->result_amount, nullptr, incoming_action ); | ||
| actual_amount = resource_loss( RESOURCE_HEALTH, incoming_state->result_absorbed, nullptr, incoming_action ); |
There was a problem hiding this comment.
Not related specifically to this change, but the PR in general...
Historically, there were issues where some effects did not proc when the action attempting to trigger the proc was fully absorbed. The most notable case I immediately recall is Slimy Expulsion Boots during Dragonflight, most notably in Underrot (as it was available in M+ and the final boss has an absorb over its entire HP for the entire fight).
More investigation is definitely required before making this change.
| return expr_t::create_constant( "is_enemy", is_enemy() ); | ||
|
|
||
| if ( expression_str == "has_absorb" ) | ||
| return make_fn_expr( expression_str, [ this ] { return has_absorb() ? 1.0 : 0.0; } ); |
There was a problem hiding this comment.
An expression that yields the total amount of absorbs could also be useful, but it will be hard to avoid the trap that UnitGetTotalAbsorbs falls for given that there are multiple types of absorbs.
58a8482 to
54b9ffb
Compare
54b9ffb to
5d04f68
Compare
| if ( absorbed > 0 ) | ||
| credited_amount += absorbed; | ||
| } | ||
|
|
There was a problem hiding this comment.
This (and the following changes at 2171-2179) could be an assessor that enemy_t registers potentially?
There was a problem hiding this comment.
Is a method on enemy ok?
double enemy_t::credited_damage_amount( const action_state_t* s ) const override {
double absorbed = s->result_mitigated - s->result_absorbed;
return s->result_amount + std::max( 0.0, absorbed );
}
There was a problem hiding this comment.
I could make the assessor but I think the functionality would be the same?
There was a problem hiding this comment.
There's no need to inject additional code & calculations into the main codepath that every damage goes through for something that only applies to a niche case. You can contain all the code entirely within raid_events.cpp by utilizing assessors and only have it apply to the player should the profile actually create a shield event.
Since you can't really search for existing assessors, something like raid_event_t::init( sim ) would be a good place to search for the absorb event and add the assessor if necessary.
5d04f68 to
c8e31ab
Compare
A new `absorb` raid event puts an absorb buff on a target enemy (target=, amount=, school= options plus standard timing controls). The raid event creates a real absorb_buff_t so it correctly absorbs damage and influences fight termination — the encounter-modeling use case, analogous to raid_event=vulnerable. When a player damages an enemy with an absorb, the attacker's stats include the absorbed portion as damage dealt (action.cpp), so DPS attribution reflects the rolled damage rather than only the post- absorb HP impact. Adds has_absorb() and current_absorb_amount() (virtual on player_t, defined for enemy_t) plus a target.has_absorb expression for APL queries.
c8e31ab to
47268b2
Compare
| { | ||
| TARGET_MITIGATION = 100U, // Target assessing (mitigation etc) | ||
| TARGET_DAMAGE = 200U, // Do damage to target (and related functionality) | ||
| ABSORB_CREDIT = 250U, // Credit absorbed-on-enemy damage to attacker stats |
There was a problem hiding this comment.
It'd be more common to set the assessor priority to TARGET_DAMAGE+1 if you want the assessor to occur after TARGET_DAMAGE assessors, but beyond that don't mind the exact ordering. That is likely sufficient in this context.
What
raid_events=absorb— new event that puts anabsorb_buff_ton a target enemy. Options:target=,amount=,school=plus standard timing controls. Noamount=means unbreakable for the window.target.has_absorbAPL expression andplayer_t::has_absorb()/current_absorb_amount()helpers (scoped to enemy actors viaenemy_toverrides).credited_damage_amountonplayer_t, overridden onenemy_tto add the absorbed delta.result_amountsemantics are preserved.Use case
Encounter modeling — boss / add mechanics with absorb shields (Aleria-style fights). Analogous in shape to
raid_event=vulnerable; class APLs and class modules can react to shielded targets via the helpers and thetarget.has_absorbexpression.