Dendro implementation notes #855
Replies: 3 comments 1 reply
-
On Maybe what we can do is (still not quite modifiers), instead of: r.Durability = make([]combat.Durability, attributes.ElementDelimAttachable)
r.DecayRate = make([]combat.Durability, attributes.ElementDelimAttachable) Where Durability is basically an array of length number of elements, add a new type say type ReactableModifiers int
const (
ModifierPyro ReactableModifiers = iota
// .. regular stuff
ModifierBurning
ModifierBurningFuel
// .. so on
)
func (r ReactableModifier) Element() attributes.element {
return attributes.Pyro // return whatever element each modifier contains underlying
} It's not very different from just adding it as elements but keeps elements pure and a 1:1 match with in game. |
Beta Was this translation helpful? Give feedback.
-
Some additional notes for Burning from Carrier5b5, translated by Koli |
Beta Was this translation helpful? Give feedback.
-
Some additional tests from @k0l11 25 dendro -> 25 pyro -> 50 pyro: https://youtu.be/_ZT07HU81xQ Thoma Q lands roughly at frame 200 and ends roughly at frame 920, lasting ~720 frames aka. the full duration of a 50 pyro modifier. This shows that additional pyro application attaches to pyro modifiers and does not affect the burning modifier. |
Beta Was this translation helpful? Give feedback.
-
This is to keep track Dendro implementation notes/thoughts:
Gadgets
Will need to implement generic gadgets to handle proper interaction with Bloom
All gadgets need to implement
combat.Target
interface. This is to make sure gadgets can be added to the combat system. Gadgets should live for as long as it hasdurability
or unless aduration
is set.Default implementation
Should provide a default template providing common functions that specific gadgets can build upon. Something like:
combat.Target
refactor requiredWe should remove the following methods of
combat.Target
. These methods really aren't useful to gadgets. Only time these methods are used are typically on event hooks, which would check for type == Enemy anyways. In addition,combat.Handler
doesn't actually need to know if a target is alive or how much hp it has.We can refactor
combat.Target
to the following:This way
AttackWillLand
can handle any dead or alive checks. Alternatively change it so that dead targets are removed from the targets array. Only problem with this is that logging needs to be changed to log not by target index but by some sort of target key and target key cannot be duplicates.Also
AuraContains(e ...attributes.Element) bool
can be moved to a different interface in combat, and the absorb check be changed accordingly:Modifiers
In the current implementation, gcsim is treating auras as some sort of array of buckets attached to each target object. In reality, auras are just modifiers, which are fairly generic properties that are attached to just about anything. The name of the modifier forms a unique key, such that each target can only have on modifier of the same name. Depending on the properly set, reapplying a modifier with the same name when one exist can either replace, refresh certain properties, or do nothing.
Historically for each "aura" (or existing element), you just had one modifier. Usually something like
FireModifier
for attached pyro, orElectroModifier
for attached electro. This made our array of whatever buckets sort of work.However with Burning, we are introducing 2 new modifiers (
burning
andburning_fuel
) with elements attached BUT:This throws a bit of a wrench into our implementation because gcsim is treating modifiers as having a 1 to 1 relationshp with element types. To fix this we need to refactor the
reactable.Durability
andreactable.DecayRate
slice to reflect modifiers instead. It should look something like the following:This should allow us to have multiple of the same element. However, this also means that any code checking for existing
pyro
will have to check bothreactable.Modifiers[ModifierPyro]
andreactable.Modifiers[ModifierBurning]
as both can containpyro
Note on multiple of the same element
When a reaction occurs and there are multiple modifiers with the same element present (say
ModifierBurning
andModifierPyro
), all these modifiers will have their elements reduced. The amount of reacted durability is based on the modifier with the max durability.For example, suppose we have a target with the following modifiers:
If we apply 50 anemo to this target, the amount of reacted durability (for the purpose of calculating the resultant swirl attack) is
max(40, 25)
. However, both modifiers will have their durability reduced by50 * 1/2 = 25
(i.e. reaction multiplier for anemo). So the result is, the target will be left with:ModifierPyro
here is fully removed. In addition, we will also get a swirl attack that haspyro
durability of1.25 * 25 + 23.75 = 55
.Currently, we have
ModifierBurning
andModifierBurningFuel
as newly introduced modifiers that have existing elementspyro
anddendro
respectively. These modifiers will be affected accordingly if they are present withModifierPyro
orModifierDendro
QUESTION/TODO: it appears that
ModifierQuicken
gets treated as if it has elementdendro
even though it's technically a new elementquicken
??? Not sure what's going on here.Quicken
Quicken is a new element. It behaves effectively as a
dendro
element for reactions. Can coexist withelectro
,dendro
, andcryo
(because there is nodendro
+cryo
reactions). Can coexist with burning (QUESTION: does it act as burning fuel in this case?).Reaction multiplier
The reaction has a 1:1 multiplier between
electro
anddendro
Duration and durability
Quicken have different formula than normal "attachment". Existing code uses this function to handle attachment:
With Quicken specifically, the duration formula is changed to:
12 * dur + 360
. So the decay rate is actually:Probably best to just not use the
attach
function call and leave as is. Realistically theattach
function should be refactored to handle all cases.Aggravate/Spread
When
quicken
reacts withelectro
ordendro
, aggravate and and spread is triggered respectively. Both reactions adds to theAttackInfo.FlatDmg
of the triggering attack.Special note about aggravate/spread. The triggering
electro
/dendro
attack is buffed, however, no durability is consumed on both thequicken
and the applyingelectro
/dendro
. The applyingelectro
ordendro
will attach to the target normally coexisting with thequicken
.The amount of damage added follows the same base reaction damage formula but uses a different EM multiplier. Calculation should be as follows:
Multiplier for aggravate and spread is 1.15 and 1.25 respectively.
Other
quicken
reactionsquicken
behaves the same asdendro
when reacting withhydro
orpyro
, triggeringbloom
andburning
respectivelyBloom
Bloom is the reaction triggered when
dendro
reacts withhydro
. This one is fairly straightforward. On reaction, a "seed" is generated.The position of the seed (dendro core) appears to be distance 1 from the target, with a random 0 to 60 degree angle. Presuming this is 0 to 60 degree from x-axis on the cartesian plane (in game uses y). The seed then has an initial velocity and a deceleration. Needs more testing on this. For simplicty probably ok to just spawn randomly within 1 radius of target.
Seeds have a lifetime of 5 seconds. From spawn it should be closer to 6 seconds?
Bloom explode
If the dendro core does not come in contact with
pyro
orelectro
(simple attack collision check), it will explode on expiriy. Radius is 5. AttackInfo is as follows:Burgeon
When the dendro core comes in contact with
pyro
,burgeon
is triggered, dealing an attack with radius 5. AttackInfo is the same asbloom
except withcombat.AttackTagBurgeon
,combat.AttackTagBurgeon
andcombat.ICDTagBurgeon
Hyperbloom
When dendro core comes in contact with
electro
,hyperbloom
is triggered, dealing an attack with radius 1. AttackInfo is the same asbloom
except withcombat.AttackTagHyperbloom
,combat.AttackTagHyperbloom
andcombat.ICDTagHyperbloom
Bloom/Burgeon/Hyperbloom self damage
All 3 explosions will trigger an additional attack that damages the player, with AttackInfo as follows:
Radius is the same as each respective type of explosion (i.e. radius 1 for Hyperbloom)
Burning
Probably the most complex reaction to date (way worse than EC or Freeze).... Introdues 2 new modifiers but no additional elements, which technically "breaks" the current implementation but thankfully I think should be ok implementing a hack solution. As long as Hoyoverse doesn't introduce any new reactions. See earlier note on Modifier refactor.
Reaction, Duration, and Durability
When
dendro
reacts withpyro
, you get two resulting modifiers (or "elements" in our hack solution):burning
andburning_fuel
.burning
always has 50 durability regardless of the reacted amount. It also does not have a set duration. Instead,burning
will last as long as both:burning
durability > 0, andburning_fuel
exists stillburning
has element of typepyro
and will react just like normalpyro
. However it cannot be topped up by additional pyro application (makes sense since it's a completely different modifier). Any additionalpyro
application will merely coexist.For our hack implementation, we'll just have to go with:
And then on tick we'll need to check for if
burning_fuel
is still present, and if not removeburning
burning_fuel
durability has a 0.8x multiplier on the reacted amount. So for example:dendro 20
, applied from adendro 25
attackpyro 25
dendro (burning_fuel) 16
The duration formula follows the standard
0.1 * d + 7
in seconds, or6 * d + 420
in frames.In addition, the decay rate is subject to a minimum threshold of at least 10 durability per second. Effectively, you have the following for decay rate:
Note here I'm treating
burning_fuel
as it's own element i.e.attributes.BurningFuel
when that's not actually the case here in game (see modifier discussion about).burning_fuel
refreshUnlike other element attachment, when additional Dendro is applied to existing
burning_fuel
, it does not overlap but instead refreshes. This means that the existingburning_fuel
durability/duration will be overwritten by the applying Dendro durability/duration. However, the existing decay rate is kept.For example:
dendro 40 (burning_fuel)
dendro 25
dendro 25 (burning_fuel)
So you can actually "shrink" the amount of
dendro (burning_fuel)
aura per say.Burning damage
While
burning
is active, every 0.25s it will trigger a spherical attack with radius 1, center on the target that is burning.AttackInfo is as follows:
TODO: it's possible that if burning ends early before the next tick happens then the next tick happens right away? not sure
POST STILL WIP
Beta Was this translation helpful? Give feedback.
All reactions