diff --git a/internal/characters/albedo/burst.go b/internal/characters/albedo/burst.go index c281070297..43fb84f85c 100644 --- a/internal/characters/albedo/burst.go +++ b/internal/characters/albedo/burst.go @@ -41,7 +41,7 @@ func (c *char) Burst(p map[string]int) (action.Info, error) { if hasC2 { c2Count = c.c2stacks c.c2stacks = 0 - ai.FlatDmg = c.TotalDef() * float64(c2Count) * 0.3 + ai.FlatDmg = c.TotalDef(false) * float64(c2Count) * 0.3 } // initial damage @@ -69,7 +69,7 @@ func (c *char) Burst(p map[string]int) (action.Info, error) { // C2 damage is recalculated once on burstHitmark if hasC2 { - ai.FlatDmg = c.TotalDef() * float64(c2Count) * 0.3 + ai.FlatDmg = c.TotalDef(false) * float64(c2Count) * 0.3 } // generate 7 blossoms diff --git a/internal/characters/bennett/burst.go b/internal/characters/bennett/burst.go index 76de5a34b0..88f1aeb529 100644 --- a/internal/characters/bennett/burst.go +++ b/internal/characters/bennett/burst.go @@ -91,7 +91,7 @@ func (c *char) applyBennettField(stats [attributes.EndStatType]float64, firstTic } m := make([]float64, attributes.EndStatType) - m[attributes.ATK] = pc * c.Base.Atk + m[attributes.ATK] = pc * c.Stat(attributes.BaseATK) if c.Base.Cons >= 6 { m[attributes.PyroP] = 0.15 } diff --git a/internal/characters/charlotte/burst.go b/internal/characters/charlotte/burst.go index 4163f4fb8f..3061d2edcf 100644 --- a/internal/characters/charlotte/burst.go +++ b/internal/characters/charlotte/burst.go @@ -58,7 +58,7 @@ func (c *char) Burst(p map[string]int) (action.Info, error) { snap := c.Snapshot(&ai) healp := snap.Stats[attributes.Heal] - atk := snap.BaseAtk*(1+snap.Stats[attributes.ATKP]) + snap.Stats[attributes.ATK] + atk := snap.Stats.TotalATK() heal := burstInitialHealFlat[c.TalentLvlBurst()] + atk*burstInitialHealPer[c.TalentLvlBurst()] healDot := burstDotHealFlat[c.TalentLvlBurst()] + atk*burstDotHealPer[c.TalentLvlBurst()] diff --git a/internal/characters/chiori/asc.go b/internal/characters/chiori/asc.go index 0f7f895497..a468bea99d 100644 --- a/internal/characters/chiori/asc.go +++ b/internal/characters/chiori/asc.go @@ -102,7 +102,7 @@ func (c *char) a1TapestrySetup() { Mult: thrustAtkScaling[c.TalentLvlSkill()], } snap := c.Snapshot(&ai) - ai.FlatDmg = snap.BaseDef*(1+snap.Stats[attributes.DEFP]) + snap.Stats[attributes.DEF] + ai.FlatDmg = snap.Stats.TotalDEF() ai.FlatDmg *= thrustDefScaling[c.TalentLvlSkill()] c.Core.QueueAttackWithSnap(ai, snap, combat.NewCircleHitOnTarget(t, nil, 2.5), 1) diff --git a/internal/characters/chiori/burst.go b/internal/characters/chiori/burst.go index 0f9acebf4b..c4d465fa36 100644 --- a/internal/characters/chiori/burst.go +++ b/internal/characters/chiori/burst.go @@ -43,7 +43,7 @@ func (c *char) Burst(p map[string]int) (action.Info, error) { snap := c.Snapshot(&ai) // flat dmg for def scaling portion - ai.FlatDmg = snap.BaseDef*(1+snap.Stats[attributes.DEFP]) + snap.Stats[attributes.DEF] + ai.FlatDmg = snap.Stats.TotalDEF() ai.FlatDmg *= burstDefScaling[c.TalentLvlBurst()] // c2 should be called slightly before the actual dmg happens diff --git a/internal/characters/chiori/cons.go b/internal/characters/chiori/cons.go index e47d5a481a..f58f734875 100644 --- a/internal/characters/chiori/cons.go +++ b/internal/characters/chiori/cons.go @@ -180,6 +180,6 @@ func (c *char) c6NAIncrease(ai *combat.AttackInfo, snap *combat.Snapshot) { if c.Base.Cons < 6 { return } - ai.FlatDmg = snap.BaseDef*(1+snap.Stats[attributes.DEFP]) + snap.Stats[attributes.DEF] + ai.FlatDmg = snap.Stats.TotalDEF() ai.FlatDmg *= 2.35 } diff --git a/internal/characters/chiori/kinu.go b/internal/characters/chiori/kinu.go index 31ab1d67a4..6fd7edad94 100644 --- a/internal/characters/chiori/kinu.go +++ b/internal/characters/chiori/kinu.go @@ -59,7 +59,7 @@ func (c *char) kinuAttack(src int, kinu *ticker, pos geometry.Point) func() { } snap := c.Snapshot(&ai) - ai.FlatDmg = snap.BaseDef*(1+snap.Stats[attributes.DEFP]) + snap.Stats[attributes.DEF] + ai.FlatDmg = snap.Stats.TotalDEF() ai.FlatDmg *= turretDefScaling[c.TalentLvlSkill()] * kinuDmgRatio // if the player has an attack target it will always choose this enemy diff --git a/internal/characters/chiori/skill.go b/internal/characters/chiori/skill.go index 6b44e199f7..3ee372c4a1 100644 --- a/internal/characters/chiori/skill.go +++ b/internal/characters/chiori/skill.go @@ -133,7 +133,7 @@ func (c *char) handleSkill(hold int) { } snap := c.Snapshot(&ai) - ai.FlatDmg = snap.BaseDef*(1+snap.Stats[attributes.DEFP]) + snap.Stats[attributes.DEF] + ai.FlatDmg = snap.Stats.TotalDEF() ai.FlatDmg *= thrustDefScaling[c.TalentLvlSkill()] c.Core.QueueAttackWithSnap(ai, snap, combat.NewBoxHitOnTarget(c.Core.Combat.Player(), nil, 5.5, 3.5), 0) @@ -212,7 +212,7 @@ func (c *char) skillDollAttack(src int, abil string, pos geometry.Point) func() } snap := c.Snapshot(&ai) - ai.FlatDmg = snap.BaseDef*(1+snap.Stats[attributes.DEFP]) + snap.Stats[attributes.DEF] + ai.FlatDmg = snap.Stats.TotalDEF() ai.FlatDmg *= turretDefScaling[c.TalentLvlSkill()] // if the player has an attack target it will always choose this enemy diff --git a/internal/characters/clorinde/asc.go b/internal/characters/clorinde/asc.go index 8616c92fd0..7630ae3180 100644 --- a/internal/characters/clorinde/asc.go +++ b/internal/characters/clorinde/asc.go @@ -73,7 +73,7 @@ func (c *char) a1Amount(atk *combat.AttackEvent, t combat.Target) ([]float64, bo default: return nil, false } - totalAtk := atk.Snapshot.BaseAtk*(1+atk.Snapshot.Stats[attributes.ATKP]) + atk.Snapshot.Stats[attributes.ATK] + totalAtk := atk.Snapshot.Stats.TotalATK() amt = min(totalAtk*c.a1BuffPercent*float64(c.a1stacks.Count()), c.a1Cap) atk.Info.FlatDmg += amt c.Core.Log.NewEvent("a1 adding flat dmg", glog.LogCharacterEvent, c.Index). diff --git a/internal/characters/faruzan/asc.go b/internal/characters/faruzan/asc.go index 2b70019622..bb29e351aa 100644 --- a/internal/characters/faruzan/asc.go +++ b/internal/characters/faruzan/asc.go @@ -49,7 +49,7 @@ func (c *char) a4() { active := c.Core.Player.ByIndex(atk.Info.ActorIndex) if active.StatusIsActive(burstBuffKey) && !c.StatusIsActive(a4ICDKey) { - amt := 0.32 * c.Base.Atk + amt := 0.32 * c.Stat(attributes.BaseATK) if c.Core.Flags.LogDebug { c.Core.Log.NewEvent("faruzan a4 proc dmg add", glog.LogPreDamageMod, atk.Info.ActorIndex). Write("before", atk.Info.FlatDmg). diff --git a/internal/characters/gorou/asc.go b/internal/characters/gorou/asc.go index 0c9099ad4b..26309e52c0 100644 --- a/internal/characters/gorou/asc.go +++ b/internal/characters/gorou/asc.go @@ -29,7 +29,7 @@ func (c *char) a4Skill() float64 { if c.Base.Ascension < 4 { return 0 } - return c.TotalDef() * 1.56 + return c.TotalDef(false) * 1.56 } // Gorou receives the following DMG Bonuses to his attacks based on his DEF: @@ -39,5 +39,5 @@ func (c *char) a4Burst() float64 { if c.Base.Ascension < 4 { return 0 } - return c.TotalDef() * 0.156 + return c.TotalDef(false) * 0.156 } diff --git a/internal/characters/gorou/burst.go b/internal/characters/gorou/burst.go index fc4d390ae0..378dc0746f 100644 --- a/internal/characters/gorou/burst.go +++ b/internal/characters/gorou/burst.go @@ -170,12 +170,11 @@ func (c *char) gorouBurstHealField(src int) func() { } // When General's Glory is in the "Impregnable" or "Crunch" states, it will also heal active characters // within its AoE by 50% of Gorou's own DEF every 1.5s. - amt := c.Base.Def*(1+c.healFieldStats[attributes.DEFP]) + c.healFieldStats[attributes.DEF] c.Core.Player.Heal(info.HealInfo{ Caller: c.Index, Target: c.Core.Player.Active(), Message: "Lapping Hound: Warm as Water", - Src: 0.5 * amt, + Src: c.healFieldStats.TotalDEF() * 0.5, Bonus: c.Stat(attributes.Heal), }) diff --git a/internal/characters/gorou/gorou.go b/internal/characters/gorou/gorou.go index d530bb37fe..ea9b6039ef 100644 --- a/internal/characters/gorou/gorou.go +++ b/internal/characters/gorou/gorou.go @@ -35,7 +35,7 @@ type char struct { c2Extension int c6Buff []float64 a1Buff []float64 - healFieldStats [attributes.EndStatType]float64 + healFieldStats attributes.Stats } func NewChar(s *core.Core, w *character.CharWrapper, _ info.CharacterProfile) error { diff --git a/internal/characters/hutao/skill.go b/internal/characters/hutao/skill.go index e0c0fb1260..024d44e01b 100644 --- a/internal/characters/hutao/skill.go +++ b/internal/characters/hutao/skill.go @@ -33,7 +33,7 @@ func init() { func (c *char) Skill(p map[string]int) (action.Info, error) { bonus := ppatk[c.TalentLvlSkill()] * c.MaxHP() - maxBonus := c.Base.Atk * 4 + maxBonus := c.Stat(attributes.BaseATK) * 4 if bonus > maxBonus { bonus = maxBonus } diff --git a/internal/characters/itto/asc.go b/internal/characters/itto/asc.go index 480d579b23..6729adade8 100644 --- a/internal/characters/itto/asc.go +++ b/internal/characters/itto/asc.go @@ -64,6 +64,6 @@ func (c *char) a4(ai *combat.AttackInfo) { if c.Base.Ascension < 4 { return } - ai.FlatDmg = c.TotalDef() * 0.35 + ai.FlatDmg = c.TotalDef(false) * 0.35 c.Core.Log.NewEvent("itto-a4 applied", glog.LogCharacterEvent, c.Index) } diff --git a/internal/characters/itto/burst.go b/internal/characters/itto/burst.go index eae2ecaa35..328d5751fe 100644 --- a/internal/characters/itto/burst.go +++ b/internal/characters/itto/burst.go @@ -48,7 +48,7 @@ func (c *char) Burst(p map[string]int) (action.Info, error) { Abil: "Royal Descent: Behold, Itto the Evil! (Stat Snapshot)", } c.Snapshot(&aiSnapshot) - burstDefSnapshot := c.Base.Def*(1+c.NonExtraStat(attributes.DEFP)) + c.NonExtraStat(attributes.DEF) + burstDefSnapshot := c.TotalDef(true) mult := defconv[c.TalentLvlBurst()] // TODO: Confirm exact timing of buff diff --git a/internal/characters/jean/asc.go b/internal/characters/jean/asc.go index f3886025d9..f66b8beefd 100644 --- a/internal/characters/jean/asc.go +++ b/internal/characters/jean/asc.go @@ -24,12 +24,11 @@ func (c *char) makeA1CB() combat.AttackCBFunc { snap := a.AttackEvent.Snapshot if c.Core.Rand.Float64() < 0.5 { - heal := 0.15 * (snap.BaseAtk*(1+snap.Stats[attributes.ATKP]) + snap.Stats[attributes.ATK]) c.Core.Player.Heal(info.HealInfo{ Caller: c.Index, Target: -1, Message: "Wind Companion", - Src: heal, + Src: snap.Stats.TotalATK() * .15, Bonus: c.Stat(attributes.Heal), }) } diff --git a/internal/characters/jean/burst.go b/internal/characters/jean/burst.go index 009127b231..e2604d9b24 100644 --- a/internal/characters/jean/burst.go +++ b/internal/characters/jean/burst.go @@ -66,7 +66,7 @@ func (c *char) Burst(p map[string]int) (action.Info, error) { // heal on burst start hpplus := snap.Stats[attributes.Heal] - atk := snap.BaseAtk*(1+snap.Stats[attributes.ATKP]) + snap.Stats[attributes.ATK] + atk := snap.Stats.TotalATK() heal := burstInitialHealFlat[c.TalentLvlBurst()] + atk*burstInitialHealPer[c.TalentLvlBurst()] healDot := burstDotHealFlat[c.TalentLvlBurst()] + atk*burstDotHealPer[c.TalentLvlBurst()] diff --git a/internal/characters/kaeya/skill.go b/internal/characters/kaeya/skill.go index ed63ab8dc5..3b705bd6b3 100644 --- a/internal/characters/kaeya/skill.go +++ b/internal/characters/kaeya/skill.go @@ -48,12 +48,11 @@ func (c *char) Skill(p map[string]int) (action.Info, error) { // A1: // Every hit with Frostgnaw regenerates HP for Kaeya equal to 15% of his ATK. if c.Base.Ascension >= 1 { - heal := .15 * (a.AttackEvent.Snapshot.BaseAtk*(1+a.AttackEvent.Snapshot.Stats[attributes.ATKP]) + a.AttackEvent.Snapshot.Stats[attributes.ATK]) c.Core.Player.Heal(info.HealInfo{ Caller: c.Index, Target: c.Core.Player.Active(), Message: "Cold-Blooded Strike", - Src: heal, + Src: a.AttackEvent.Snapshot.Stats.TotalATK() * .15, Bonus: c.Stat(attributes.Heal), }) } diff --git a/internal/characters/kokomi/skill.go b/internal/characters/kokomi/skill.go index 64e45b5234..bb3025048f 100644 --- a/internal/characters/kokomi/skill.go +++ b/internal/characters/kokomi/skill.go @@ -104,7 +104,7 @@ func (c *char) skillTick(d *combat.AttackEvent) { // handle healing if c.Core.Combat.Player().IsWithinArea(d.Pattern) { - maxhp := d.Snapshot.BaseHP*(1+d.Snapshot.Stats[attributes.HPP]) + d.Snapshot.Stats[attributes.HP] + maxhp := d.Snapshot.Stats.MaxHP() src := skillHealPct[c.TalentLvlSkill()]*maxhp + skillHealFlat[c.TalentLvlSkill()] // C2 handling diff --git a/internal/characters/noelle/asc.go b/internal/characters/noelle/asc.go index cf798f20c5..3bf4de235e 100644 --- a/internal/characters/noelle/asc.go +++ b/internal/characters/noelle/asc.go @@ -43,14 +43,13 @@ func (c *char) a1() { snap := c.Snapshot(&ai) // add shield - x := snap.BaseDef*(1+snap.Stats[attributes.DEFP]) + snap.Stats[attributes.DEF] c.Core.Player.Shields.Add(&shield.Tmpl{ ActorIndex: c.Index, Target: active.Index, Src: c.Core.F, ShieldType: shield.NoelleA1, Name: "Noelle A1", - HP: 4 * x, + HP: snap.Stats.TotalDEF() * 4, Ele: attributes.Cryo, Expires: c.Core.F + 1200, // 20 sec }) diff --git a/internal/characters/noelle/burst.go b/internal/characters/noelle/burst.go index e6ae49f4f2..02ee9601d2 100644 --- a/internal/characters/noelle/burst.go +++ b/internal/characters/noelle/burst.go @@ -36,7 +36,7 @@ func (c *char) Burst(p map[string]int) (action.Info, error) { Abil: "Sweeping Time (Stat Snapshot)", } c.Snapshot(&aiSnapshot) - burstDefSnapshot := c.Base.Def*(1+c.NonExtraStat(attributes.DEFP)) + c.NonExtraStat(attributes.DEF) + burstDefSnapshot := c.TotalDef(true) mult := defconv[c.TalentLvlBurst()] if c.Base.Cons >= 6 { mult += 0.5 diff --git a/internal/characters/noelle/skill.go b/internal/characters/noelle/skill.go index b5a5d0c5d3..195e8ce670 100644 --- a/internal/characters/noelle/skill.go +++ b/internal/characters/noelle/skill.go @@ -43,7 +43,7 @@ func (c *char) Skill(p map[string]int) (action.Info, error) { snap := c.Snapshot(&ai) // add shield first - defFactor := snap.BaseDef*(1+snap.Stats[attributes.DEFP]) + snap.Stats[attributes.DEF] + defFactor := snap.Stats.TotalDEF() shieldhp := shieldFlat[c.TalentLvlSkill()] + shieldDef[c.TalentLvlSkill()]*defFactor c.Core.Player.Shields.Add(c.newShield(shieldhp, shield.NoelleSkill, 720)) @@ -106,8 +106,8 @@ func (c *char) skillHealCB() combat.AttackCBFunc { } if c.Core.Rand.Float64() < prob { // heal target - x := atk.AttackEvent.Snapshot.BaseDef*(1+atk.AttackEvent.Snapshot.Stats[attributes.DEFP]) + atk.AttackEvent.Snapshot.Stats[attributes.DEF] - heal := shieldHeal[c.TalentLvlSkill()]*x + shieldHealFlat[c.TalentLvlSkill()] + def := atk.AttackEvent.Snapshot.Stats.TotalDEF() + heal := shieldHeal[c.TalentLvlSkill()]*def + shieldHealFlat[c.TalentLvlSkill()] c.Core.Player.Heal(info.HealInfo{ Caller: c.Index, Target: -1, diff --git a/internal/characters/qiqi/qiqi.go b/internal/characters/qiqi/qiqi.go index d65cf2e84d..79108805d4 100644 --- a/internal/characters/qiqi/qiqi.go +++ b/internal/characters/qiqi/qiqi.go @@ -3,7 +3,6 @@ package qiqi import ( tmpl "github.com/genshinsim/gcsim/internal/template/character" "github.com/genshinsim/gcsim/pkg/core" - "github.com/genshinsim/gcsim/pkg/core/attributes" "github.com/genshinsim/gcsim/pkg/core/combat" "github.com/genshinsim/gcsim/pkg/core/info" "github.com/genshinsim/gcsim/pkg/core/keys" @@ -64,7 +63,7 @@ func (c *char) healDynamic(healScalePer, healScaleFlat []float64, talentLevel in // Helper function to calculate healing amount from a snapshot instance func (c *char) healSnapshot(d *combat.Snapshot, healScalePer, healScaleFlat []float64, talentLevel int) float64 { - atk := d.BaseAtk*(1+d.Stats[attributes.ATKP]) + d.Stats[attributes.ATK] + atk := d.Stats.TotalATK() heal := healScaleFlat[talentLevel] + atk*healScalePer[talentLevel] return heal } diff --git a/internal/characters/sara/skill.go b/internal/characters/sara/skill.go index ea4b7a3f1f..81ead3ba41 100644 --- a/internal/characters/sara/skill.go +++ b/internal/characters/sara/skill.go @@ -88,7 +88,7 @@ func (c *char) attackBuff(a combat.AttackPattern, delay int) { } active := c.Core.Player.ActiveChar() - buff := atkBuff[c.TalentLvlSkill()] * c.Base.Atk + buff := atkBuff[c.TalentLvlSkill()] * c.Stat(attributes.BaseATK) c.Core.Log.NewEvent("sara attack buff applied", glog.LogCharacterEvent, c.Index). Write("char", active.Index). diff --git a/internal/characters/sayu/burst.go b/internal/characters/sayu/burst.go index 7746670464..743655716a 100644 --- a/internal/characters/sayu/burst.go +++ b/internal/characters/sayu/burst.go @@ -46,7 +46,7 @@ func (c *char) Burst(p map[string]int) (action.Info, error) { ) // heal - atk := snap.BaseAtk*(1+snap.Stats[attributes.ATKP]) + snap.Stats[attributes.ATK] + atk := snap.Stats.TotalATK() heal := initHealFlat[c.TalentLvlBurst()] + atk*initHealPP[c.TalentLvlBurst()] c.Core.Player.Heal(info.HealInfo{ Caller: c.Index, @@ -58,7 +58,7 @@ func (c *char) Burst(p map[string]int) (action.Info, error) { // ticks d := c.createBurstSnapshot() - atk = d.Snapshot.BaseAtk*(1+d.Snapshot.Stats[attributes.ATKP]) + d.Snapshot.Stats[attributes.ATK] + atk = d.Snapshot.Stats.TotalATK() heal = burstHealFlat[c.TalentLvlBurst()] + atk*burstHealPP[c.TalentLvlBurst()] if c.Base.Cons >= 6 { diff --git a/internal/characters/traveler/common/anemo/traveleranemo.go b/internal/characters/traveler/common/anemo/traveleranemo.go index 6fd85a0b0d..8a4ce58389 100644 --- a/internal/characters/traveler/common/anemo/traveleranemo.go +++ b/internal/characters/traveler/common/anemo/traveleranemo.go @@ -29,13 +29,13 @@ func NewTraveler(s *core.Core, w *character.CharWrapper, p info.CharacterProfile } c.Character = tmpl.NewWithWrapper(s, w) - c.Base.Atk += common.TravelerBaseAtkIncrease(p) c.Base.Element = attributes.Anemo c.EnergyMax = 60 c.BurstCon = 3 c.SkillCon = 5 c.NormalHitNum = normalHitNum + common.TravelerBaseAtkIncrease(w, p) return &c, nil } diff --git a/internal/characters/traveler/common/baseatk.go b/internal/characters/traveler/common/baseatk.go index a33b5ade26..7b796d6ec3 100644 --- a/internal/characters/traveler/common/baseatk.go +++ b/internal/characters/traveler/common/baseatk.go @@ -1,15 +1,28 @@ package common -import "github.com/genshinsim/gcsim/pkg/core/info" +import ( + "github.com/genshinsim/gcsim/pkg/core/attributes" + "github.com/genshinsim/gcsim/pkg/core/info" + "github.com/genshinsim/gcsim/pkg/core/player/character" + "github.com/genshinsim/gcsim/pkg/modifier" +) // doing Chapter III: Act I of sumeru archon quest buffs base atk by 3 -func TravelerBaseAtkIncrease(p info.CharacterProfile) float64 { +func TravelerBaseAtkIncrease(c *character.CharWrapper, p info.CharacterProfile) { baseAtkBuff, ok := p.Params["base_atk_buff"] if !ok { baseAtkBuff = 1 } - if baseAtkBuff == 1 { - return 3 + if baseAtkBuff != 1 { + return } - return 0 + + m := make([]float64, attributes.EndStatType) + m[attributes.BaseATK] = 3 + c.AddStatMod(character.StatMod{ + Base: modifier.NewBase("traveler-base-atk-buff", -1), + Amount: func() ([]float64, bool) { + return m, true + }, + }) } diff --git a/internal/characters/traveler/common/dendro/travelerdendro.go b/internal/characters/traveler/common/dendro/travelerdendro.go index 7a42959b27..1ddc9425df 100644 --- a/internal/characters/traveler/common/dendro/travelerdendro.go +++ b/internal/characters/traveler/common/dendro/travelerdendro.go @@ -27,13 +27,13 @@ func NewTraveler(s *core.Core, w *character.CharWrapper, p info.CharacterProfile } c.Character = tmpl.NewWithWrapper(s, w) - c.Base.Atk += common.TravelerBaseAtkIncrease(p) c.Base.Element = attributes.Dendro c.EnergyMax = 80 c.BurstCon = 5 c.SkillCon = 3 c.NormalHitNum = normalHitNum + common.TravelerBaseAtkIncrease(w, p) return &c, nil } diff --git a/internal/characters/traveler/common/electro/travelerelectro.go b/internal/characters/traveler/common/electro/travelerelectro.go index 173a6ea0d1..a6d702b1ac 100644 --- a/internal/characters/traveler/common/electro/travelerelectro.go +++ b/internal/characters/traveler/common/electro/travelerelectro.go @@ -28,13 +28,13 @@ func NewTraveler(s *core.Core, w *character.CharWrapper, p info.CharacterProfile } c.Character = tmpl.NewWithWrapper(s, w) - c.Base.Atk += common.TravelerBaseAtkIncrease(p) c.Base.Element = attributes.Electro c.EnergyMax = 80 c.BurstCon = 3 c.SkillCon = 5 c.NormalHitNum = normalHitNum + common.TravelerBaseAtkIncrease(w, p) return &c, nil } diff --git a/internal/characters/traveler/common/geo/travelergeo.go b/internal/characters/traveler/common/geo/travelergeo.go index 5ad139e5d8..004e4c7f14 100644 --- a/internal/characters/traveler/common/geo/travelergeo.go +++ b/internal/characters/traveler/common/geo/travelergeo.go @@ -25,15 +25,14 @@ func NewTraveler(s *core.Core, w *character.CharWrapper, p info.CharacterProfile } c.Character = tmpl.NewWithWrapper(s, w) - c.Base.Atk += common.TravelerBaseAtkIncrease(p) c.Base.Element = attributes.Geo c.EnergyMax = 60 c.BurstCon = 3 c.SkillCon = 5 c.NormalHitNum = normalHitNum - c.skillCD = 6 * 60 + common.TravelerBaseAtkIncrease(w, p) return &c, nil } diff --git a/internal/characters/traveler/common/hydro/travelerhydro.go b/internal/characters/traveler/common/hydro/travelerhydro.go index 0e08f0e711..8060ce03c3 100644 --- a/internal/characters/traveler/common/hydro/travelerhydro.go +++ b/internal/characters/traveler/common/hydro/travelerhydro.go @@ -22,15 +22,14 @@ func NewTraveler(s *core.Core, w *character.CharWrapper, p info.CharacterProfile } c.Character = tmpl.NewWithWrapper(s, w) - c.Base.Atk += common.TravelerBaseAtkIncrease(p) c.Base.Element = attributes.Hydro c.EnergyMax = 80 c.BurstCon = 5 c.SkillCon = 3 c.HasArkhe = true - c.NormalHitNum = normalHitNum + common.TravelerBaseAtkIncrease(w, p) return &c, nil } diff --git a/internal/characters/xilonen/burst.go b/internal/characters/xilonen/burst.go index 3948560284..5bfada2342 100644 --- a/internal/characters/xilonen/burst.go +++ b/internal/characters/xilonen/burst.go @@ -80,7 +80,7 @@ func (c *char) burstHeal(ai combat.AttackInfo) { for _, hitmark := range burstHealHitmarks { c.Core.Tasks.Add(func() { hi.Target = c.Core.Player.Active() - hi.Src = burstHealBase[c.TalentLvlBurst()] + c.TotalDef()*burstHealPer[c.TalentLvlBurst()] + hi.Src = burstHealBase[c.TalentLvlBurst()] + c.TotalDef(false)*burstHealPer[c.TalentLvlBurst()] hi.Bonus = c.Stat(attributes.Heal) c.Core.Player.Heal(hi) }, hitmark) diff --git a/internal/characters/xilonen/cons.go b/internal/characters/xilonen/cons.go index 80632c7749..24b52c9dc8 100644 --- a/internal/characters/xilonen/cons.go +++ b/internal/characters/xilonen/cons.go @@ -141,7 +141,7 @@ func (c *char) c4Init() { return false } - amt := 0.65 * c.TotalDef() + amt := 0.65 * c.TotalDef(false) char.SetTag(c4key, char.Tag(c4key)-1) c.Core.Log.NewEvent("xilonen c4 proc dmg add", glog.LogPreDamageMod, atk.Info.ActorIndex). @@ -189,7 +189,7 @@ func (c *char) applyC6() { return } hpplus := c.Stat(attributes.Heal) - heal := c.TotalDef() * 1.2 + heal := c.TotalDef(false) * 1.2 c.Core.Player.Heal(info.HealInfo{ Caller: c.Index, Target: -1, @@ -214,7 +214,7 @@ func (c *char) c6FlatDmg() { return nil, false } - amt := c.TotalDef() * 3.0 + amt := c.TotalDef(false) * 3.0 c.Core.Log.NewEvent("c6 proc dmg add", glog.LogPreDamageMod, c.Index). Write("amt", amt) diff --git a/internal/characters/xinyan/burst.go b/internal/characters/xinyan/burst.go index bb0ac8b555..a93e0b890c 100644 --- a/internal/characters/xinyan/burst.go +++ b/internal/characters/xinyan/burst.go @@ -82,7 +82,7 @@ func (c *char) Burst(p map[string]int) (action.Info, error) { if c.Base.Cons >= 2 { // TODO: snapshot timing? - defFactor := c.TotalDef() + defFactor := c.TotalDef(false) c.QueueCharTask(func() { c.updateShield(3, defFactor) }, burstShieldStart) diff --git a/internal/characters/xinyan/skill.go b/internal/characters/xinyan/skill.go index 916b1a3baf..86e7648e4c 100644 --- a/internal/characters/xinyan/skill.go +++ b/internal/characters/xinyan/skill.go @@ -46,7 +46,7 @@ func (c *char) Skill(p map[string]int) (action.Info, error) { } snap := c.Snapshot(&ai) - defFactor := snap.BaseDef*(1+snap.Stats[attributes.DEFP]) + snap.Stats[attributes.DEF] + defFactor := snap.Stats.TotalDEF() hitOpponents := 0 cb := func(_ combat.AttackCB) { diff --git a/internal/characters/yaoyao/burst.go b/internal/characters/yaoyao/burst.go index 7707652def..9306011aa3 100644 --- a/internal/characters/yaoyao/burst.go +++ b/internal/characters/yaoyao/burst.go @@ -70,7 +70,7 @@ func (c *char) Burst(p map[string]int) (action.Info, error) { } func (c *char) getBurstHealInfo(snap *combat.Snapshot) info.HealInfo { - maxhp := snap.BaseHP*(1+snap.Stats[attributes.HPP]) + snap.Stats[attributes.HP] + maxhp := snap.Stats.MaxHP() heal := burstRadishHealing[0][c.TalentLvlBurst()]*maxhp + burstRadishHealing[1][c.TalentLvlBurst()] return info.HealInfo{ Caller: c.Index, diff --git a/internal/characters/yaoyao/skill.go b/internal/characters/yaoyao/skill.go index 19d82948be..68c1f552ca 100644 --- a/internal/characters/yaoyao/skill.go +++ b/internal/characters/yaoyao/skill.go @@ -46,7 +46,7 @@ func (c *char) Skill(p map[string]int) (action.Info, error) { } func (c *char) getSkillHealInfo(snap *combat.Snapshot) info.HealInfo { - maxhp := snap.BaseHP*(1+snap.Stats[attributes.HPP]) + snap.Stats[attributes.HP] + maxhp := snap.Stats.MaxHP() heal := skillRadishHealing[0][c.TalentLvlSkill()]*maxhp + skillRadishHealing[1][c.TalentLvlSkill()] return info.HealInfo{ Caller: c.Index, diff --git a/internal/characters/yunjin/burst.go b/internal/characters/yunjin/burst.go index 80629a597b..78c9f26157 100644 --- a/internal/characters/yunjin/burst.go +++ b/internal/characters/yunjin/burst.go @@ -86,7 +86,7 @@ func (c *char) burstProc() { } finalBurstBuff := burstBuff[c.TalentLvlBurst()] + c.a4() - dmgAdded := c.TotalDef() * finalBurstBuff + dmgAdded := c.TotalDef(false) * finalBurstBuff ae.Info.FlatDmg += dmgAdded char.Tags[burstBuffKey] -= 1 diff --git a/internal/template/character/character.go b/internal/template/character/character.go index 5f9c0831db..e02a02a19c 100644 --- a/internal/template/character/character.go +++ b/internal/template/character/character.go @@ -57,10 +57,6 @@ func New(c *core.Core) *Character { func (c *Character) Snapshot(a *combat.AttackInfo) combat.Snapshot { s := combat.Snapshot{ CharLvl: c.Base.Level, - ActorEle: c.Base.Element, - BaseAtk: c.Base.Atk, - BaseDef: c.Base.Def, - BaseHP: c.Base.HP, SourceFrame: c.Core.F, } diff --git a/internal/weapons/claymore/redhorn/redhorn.go b/internal/weapons/claymore/redhorn/redhorn.go index 065961cd23..59cf73cf59 100644 --- a/internal/weapons/claymore/redhorn/redhorn.go +++ b/internal/weapons/claymore/redhorn/redhorn.go @@ -51,7 +51,7 @@ func NewWeapon(c *core.Core, char *character.CharWrapper, p info.WeaponProfile) if !(atk.Info.AttackTag == attacks.AttackTagNormal || atk.Info.AttackTag == attacks.AttackTagExtra) { return false } - baseDmgAdd := char.TotalDef() * nacaBoost + baseDmgAdd := char.TotalDef(false) * nacaBoost atk.Info.FlatDmg += baseDmgAdd c.Log.NewEvent("Redhorn proc dmg add", glog.LogPreDamageMod, char.Index). Write("base_added_dmg", baseDmgAdd) diff --git a/internal/weapons/sword/aquila/aquila.go b/internal/weapons/sword/aquila/aquila.go index 4c16470a26..4955bd7c88 100644 --- a/internal/weapons/sword/aquila/aquila.go +++ b/internal/weapons/sword/aquila/aquila.go @@ -77,13 +77,11 @@ func NewWeapon(c *core.Core, char *character.CharWrapper, p info.WeaponProfile) snap := char.Snapshot(&ai) c.QueueAttackWithSnap(ai, snap, combat.NewCircleHitOnTarget(c.Combat.Player(), nil, 6), 1) - atk := snap.BaseAtk*(1+snap.Stats[attributes.ATKP]) + snap.Stats[attributes.ATK] - c.Player.Heal(info.HealInfo{ Caller: char.Index, Target: c.Player.Active(), Message: "Aquila Favonia", - Src: atk * heal, + Src: snap.Stats.TotalATK() * heal, Bonus: char.Stat(attributes.Heal), }) return false diff --git a/internal/weapons/sword/blacksword/blacksword.go b/internal/weapons/sword/blacksword/blacksword.go index f5c6811c6f..094443ec34 100644 --- a/internal/weapons/sword/blacksword/blacksword.go +++ b/internal/weapons/sword/blacksword/blacksword.go @@ -65,7 +65,7 @@ func NewWeapon(c *core.Core, char *character.CharWrapper, p info.WeaponProfile) Caller: char.Index, Target: c.Player.Active(), Message: "The Black Sword", - Src: heal * (atk.Snapshot.BaseAtk*(1+atk.Snapshot.Stats[attributes.ATKP]) + atk.Snapshot.Stats[attributes.ATK]), + Src: heal * atk.Snapshot.Stats.TotalATK(), Bonus: char.Stat(attributes.Heal), }) // trigger cd diff --git a/internal/weapons/sword/cinnabar/cinnnabar.go b/internal/weapons/sword/cinnabar/cinnnabar.go index 8bad9fd7e9..e7780f7c3d 100644 --- a/internal/weapons/sword/cinnabar/cinnnabar.go +++ b/internal/weapons/sword/cinnabar/cinnnabar.go @@ -58,7 +58,7 @@ func NewWeapon(c *core.Core, char *character.CharWrapper, p info.WeaponProfile) }, 6) // icd starts 6 frames after char.AddStatus(durationKey, 6, false) } - damageAdd := char.TotalDef() * defPer + damageAdd := char.TotalDef(false) * defPer atk.Info.FlatDmg += damageAdd c.Log.NewEvent("Cinnabar Spindle proc dmg add", glog.LogPreDamageMod, char.Index). diff --git a/internal/weapons/sword/peakpatrolsong/peakpatrolsong.go b/internal/weapons/sword/peakpatrolsong/peakpatrolsong.go index 91188813f3..f4669c81c6 100644 --- a/internal/weapons/sword/peakpatrolsong/peakpatrolsong.go +++ b/internal/weapons/sword/peakpatrolsong/peakpatrolsong.go @@ -80,7 +80,7 @@ func NewWeapon(c *core.Core, char *character.CharWrapper, p info.WeaponProfile) }) if w.stacks == 2 { - bonus := teamBonus * char.TotalDef() / 1000.0 + bonus := teamBonus * char.TotalDef(true) / 1000.0 bonus = min(bonus, maxTeamBonus) for i := attributes.PyroP; i <= attributes.DendroP; i++ { t[i] = bonus diff --git a/pkg/avatar/avatar.go b/pkg/avatar/avatar.go index 49631a314e..c25e4cce2a 100644 --- a/pkg/avatar/avatar.go +++ b/pkg/avatar/avatar.go @@ -105,11 +105,13 @@ func (p *Player) calc(atk *combat.AttackEvent) (float64, bool) { // calculate using attack or def var a float64 - totalhp := atk.Snapshot.BaseHP*(1+atk.Snapshot.Stats[attributes.HPP]) + atk.Snapshot.Stats[attributes.HP] - if atk.Info.UseDef { - a = atk.Snapshot.BaseDef*(1+atk.Snapshot.Stats[attributes.DEFP]) + atk.Snapshot.Stats[attributes.DEF] - } else { - a = atk.Snapshot.BaseAtk*(1+atk.Snapshot.Stats[attributes.ATKP]) + atk.Snapshot.Stats[attributes.ATK] + switch { + case atk.Info.UseHP: + a = atk.Snapshot.Stats.MaxHP() + case atk.Info.UseDef: + a = atk.Snapshot.Stats.TotalDEF() + default: + a = atk.Snapshot.Stats.TotalATK() } base := atk.Info.Mult*a + atk.Info.FlatDmg @@ -127,8 +129,7 @@ func (p *Player) calc(atk *combat.AttackEvent) (float64, bool) { // TODO: Players don't have resistances right now res := 0.0 - def := char.Base.Def*(1+char.Stat(attributes.DEFP)) + char.Stat(attributes.DEF) - + def := char.TotalDef(false) def *= (1 - atk.Info.IgnoreDefPercent) defmod := 1 - def/(def+float64(5*atk.Snapshot.CharLvl)+500) @@ -183,17 +184,16 @@ func (p *Player) calc(atk *combat.AttackEvent) (float64, bool) { Write("damage", damage). Write("abil", atk.Info.Abil). Write("talent", atk.Info.Mult). - Write("base_atk", atk.Snapshot.BaseAtk). + Write("base_atk", atk.Snapshot.Stats[attributes.BaseATK]). Write("flat_atk", atk.Snapshot.Stats[attributes.ATK]). Write("atk_per", atk.Snapshot.Stats[attributes.ATKP]). Write("use_def", atk.Info.UseDef). - Write("base_def", atk.Snapshot.BaseDef). + Write("base_def", atk.Snapshot.Stats[attributes.BaseDEF]). Write("flat_def", atk.Snapshot.Stats[attributes.DEF]). Write("def_per", atk.Snapshot.Stats[attributes.DEFP]). - Write("base_hp", atk.Snapshot.BaseHP). + Write("base_hp", atk.Snapshot.Stats[attributes.BaseHP]). Write("flat_hp", atk.Snapshot.Stats[attributes.HP]). Write("hp_per", atk.Snapshot.Stats[attributes.HPP]). - Write("total_hp", totalhp). Write("catalyzed", atk.Info.Catalyzed). Write("flat_dmg", atk.Info.FlatDmg). Write("total_atk_def", a). diff --git a/pkg/core/attributes/stats.go b/pkg/core/attributes/stats.go index a0982a4f91..5ce8b4247e 100644 --- a/pkg/core/attributes/stats.go +++ b/pkg/core/attributes/stats.go @@ -5,7 +5,10 @@ import ( "strings" ) -type Stat int +type ( + Stat int + Stats [EndStatType]float64 +) // stat types const ( @@ -43,6 +46,10 @@ func (s Stat) String() string { return StatTypeString[s] } +func (s Stats) MaxHP() float64 { return s[BaseHP]*(1+s[HPP]) + s[HP] } +func (s Stats) TotalATK() float64 { return s[BaseATK]*(1+s[ATKP]) + s[ATK] } +func (s Stats) TotalDEF() float64 { return s[BaseDEF]*(1+s[DEFP]) + s[DEF] } + func PrettyPrintStats(stats []float64) string { var sb strings.Builder for i, v := range stats { diff --git a/pkg/core/combat/attackevent.go b/pkg/core/combat/attackevent.go index b787c6891a..baeff8942b 100644 --- a/pkg/core/combat/attackevent.go +++ b/pkg/core/combat/attackevent.go @@ -42,6 +42,7 @@ type AttackInfo struct { Mult float64 // ability multiplier. could set to 0 from initial Mona dmg StrikeType attacks.StrikeType UseDef bool // we use this instead of flatdmg to make sure stat snapshotting works properly + UseHP bool // we use this instead of flatdmg to make sure stat snapshotting works properly FlatDmg float64 // flat dmg; IgnoreDefPercent float64 // by default this value is 0; if = 1 then the attack will ignore defense; raiden c2 should be set to 0.6 (i.e. ignore 60%) IgnoreInfusion bool @@ -64,14 +65,8 @@ type AttackInfo struct { } type Snapshot struct { - CharLvl int - ActorEle attributes.Element - ExtraIndex int // this is currently purely for Kaeya icicle ICD - Cancelled bool // set to true if this snap should be ignored - Stats [attributes.EndStatType]float64 // total character stats including from artifact, bonuses, etc... - BaseAtk float64 // base attack used in calc - BaseDef float64 - BaseHP float64 + Stats attributes.Stats // total character stats including from artifact, bonuses, etc... + CharLvl int SourceFrame int // frame snapshot was generated at Logs []interface{} // logs for the snapshot diff --git a/pkg/core/info/character.go b/pkg/core/info/character.go index d3ab321b5d..6250d87185 100644 --- a/pkg/core/info/character.go +++ b/pkg/core/info/character.go @@ -107,9 +107,6 @@ type CharacterBase struct { Level int `json:"level"` MaxLevel int `json:"max_level"` Ascension int `json:"ascension"` - HP float64 `json:"hp"` - Atk float64 `json:"atk"` - Def float64 `json:"def"` Cons int `json:"cons"` } diff --git a/pkg/core/player/character/basestat.go b/pkg/core/player/character/basestat.go index 9f3b85bddd..e090be04bb 100644 --- a/pkg/core/player/character/basestat.go +++ b/pkg/core/player/character/basestat.go @@ -18,13 +18,10 @@ func (c *CharWrapper) UpdateBaseStats() error { if err != nil { return err } - asc := AvatarAsc(c.Base.MaxLevel, data) for i, v := range base { - if i >= int(attributes.DelimBaseStat) { - break - } c.BaseStats[i] += v } + asc := AvatarAsc(c.Base.MaxLevel, data) c.Base.Ascension = asc wdata := c.Equip.Weapon.Data() @@ -36,17 +33,9 @@ func (c *CharWrapper) UpdateBaseStats() error { return err } for i, v := range basew { - if i >= int(attributes.DelimBaseStat) { - break - } c.BaseStats[i] += v } - // set base - c.Base.HP += base[attributes.BaseHP] + basew[attributes.BaseHP] - c.Base.Atk += base[attributes.BaseATK] + basew[attributes.BaseATK] - c.Base.Def += base[attributes.BaseDEF] + basew[attributes.BaseDEF] - // misc data c.Base.Rarity = info.ConvertRarity(data.Rarity) c.Weapon.Class = info.ConvertWeaponClass(data.WeaponClass) diff --git a/pkg/core/player/character/stats.go b/pkg/core/player/character/stats.go index 3b75264553..0f315e2617 100644 --- a/pkg/core/player/character/stats.go +++ b/pkg/core/player/character/stats.go @@ -1,6 +1,7 @@ package character import ( + "slices" "strconv" "strings" @@ -123,9 +124,11 @@ func (c *CharWrapper) NonExtraStat(s attributes.Stat) float64 { return val } -func (c *CharWrapper) MaxHP() float64 { - hpp := c.BaseStats[attributes.HPP] - hp := c.BaseStats[attributes.HP] +func (c *CharWrapper) SelectStat(nonExtra bool, stat ...attributes.Stat) attributes.Stats { + var stats attributes.Stats + for _, k := range stat { + stats[k] += c.BaseStats[k] + } for _, v := range c.mods { m, ok := v.(*StatMod) @@ -133,70 +136,37 @@ func (c *CharWrapper) MaxHP() float64 { continue } // ignore this mod if stat type doesnt match - switch m.AffectedStat { - case attributes.NoStat, attributes.HP, attributes.HPP: - default: + if m.AffectedStat != attributes.NoStat && !slices.Contains(stat, m.AffectedStat) { continue } - // check expiry - if m.Expiry() > *c.f || m.Expiry() == -1 { - if amt, ok := m.Amount(); ok { - hpp += amt[attributes.HPP] - hp += amt[attributes.HP] - } - } - } - return (c.Base.HP*(1+hpp) + hp) -} - -func (c *CharWrapper) TotalAtk() float64 { - atkp := c.BaseStats[attributes.ATKP] - atk := c.BaseStats[attributes.ATK] - - for _, v := range c.mods { - m, ok := v.(*StatMod) - if !ok { - continue - } - // ignore this mod if stat type doesnt match - switch m.AffectedStat { - case attributes.NoStat, attributes.ATK, attributes.ATKP: - default: + // skip if extra stat + if nonExtra && m.Extra { continue } // check expiry if m.Expiry() > *c.f || m.Expiry() == -1 { if amt, ok := m.Amount(); ok { - atkp += amt[attributes.ATKP] - atk += amt[attributes.ATK] + for _, k := range stat { + stats[k] += amt[k] + } } } } - return (c.Base.Atk*(1+atkp) + atk) + + return stats } -func (c *CharWrapper) TotalDef() float64 { - defp := c.BaseStats[attributes.DEFP] - def := c.BaseStats[attributes.DEF] +func (c *CharWrapper) MaxHP() float64 { + stats := c.SelectStat(false, attributes.BaseHP, attributes.HPP, attributes.HP) + return stats.MaxHP() +} - for _, v := range c.mods { - m, ok := v.(*StatMod) - if !ok { - continue - } - // ignore this mod if stat type doesnt match - switch m.AffectedStat { - case attributes.NoStat, attributes.DEF, attributes.DEFP: - default: - continue - } - // check expiry - if m.Expiry() > *c.f || m.Expiry() == -1 { - if amt, ok := m.Amount(); ok { - defp += amt[attributes.DEFP] - def += amt[attributes.DEF] - } - } - } - return (c.Base.Def*(1+defp) + def) +func (c *CharWrapper) TotalAtk() float64 { + stats := c.SelectStat(false, attributes.BaseATK, attributes.ATKP, attributes.ATK) + return stats.TotalATK() +} + +func (c *CharWrapper) TotalDef(nonExtra bool) float64 { + stats := c.SelectStat(nonExtra, attributes.BaseDEF, attributes.DEFP, attributes.DEF) + return stats.TotalDEF() } diff --git a/pkg/enemy/damage.go b/pkg/enemy/damage.go index ce6f807411..41bfa3fed7 100644 --- a/pkg/enemy/damage.go +++ b/pkg/enemy/damage.go @@ -32,11 +32,13 @@ func (e *Enemy) calc(atk *combat.AttackEvent, evt glog.Event) (float64, bool) { // calculate using attack or def var a float64 - totalhp := atk.Snapshot.BaseHP*(1+atk.Snapshot.Stats[attributes.HPP]) + atk.Snapshot.Stats[attributes.HP] - if atk.Info.UseDef { - a = atk.Snapshot.BaseDef*(1+atk.Snapshot.Stats[attributes.DEFP]) + atk.Snapshot.Stats[attributes.DEF] - } else { - a = atk.Snapshot.BaseAtk*(1+atk.Snapshot.Stats[attributes.ATKP]) + atk.Snapshot.Stats[attributes.ATK] + switch { + case atk.Info.UseHP: + a = atk.Snapshot.Stats.MaxHP() + case atk.Info.UseDef: + a = atk.Snapshot.Stats.TotalDEF() + default: + a = atk.Snapshot.Stats.TotalATK() } base := atk.Info.Mult*a + atk.Info.FlatDmg @@ -111,17 +113,16 @@ func (e *Enemy) calc(atk *combat.AttackEvent, evt glog.Event) (float64, bool) { Write("damage", damage). Write("abil", atk.Info.Abil). Write("talent", atk.Info.Mult). - Write("base_atk", atk.Snapshot.BaseAtk). + Write("base_atk", atk.Snapshot.Stats[attributes.BaseATK]). Write("flat_atk", atk.Snapshot.Stats[attributes.ATK]). Write("atk_per", atk.Snapshot.Stats[attributes.ATKP]). Write("use_def", atk.Info.UseDef). - Write("base_def", atk.Snapshot.BaseDef). + Write("base_def", atk.Snapshot.Stats[attributes.BaseDEF]). Write("flat_def", atk.Snapshot.Stats[attributes.DEF]). Write("def_per", atk.Snapshot.Stats[attributes.DEFP]). - Write("base_hp", atk.Snapshot.BaseHP). + Write("base_hp", atk.Snapshot.Stats[attributes.BaseHP]). Write("flat_hp", atk.Snapshot.Stats[attributes.HP]). Write("hp_per", atk.Snapshot.Stats[attributes.HPP]). - Write("total_hp", totalhp). Write("catalyzed", atk.Info.Catalyzed). Write("flat_dmg", atk.Info.FlatDmg). Write("total_atk_def", a). diff --git a/pkg/reactable/reactable.go b/pkg/reactable/reactable.go index 5811471e05..1874ba7f45 100644 --- a/pkg/reactable/reactable.go +++ b/pkg/reactable/reactable.go @@ -432,8 +432,7 @@ func calcReactionDmg(char *character.CharWrapper, atk combat.AttackInfo, em floa lvl = 0 } snap := combat.Snapshot{ - CharLvl: char.Base.Level, - ActorEle: char.Base.Element, + CharLvl: char.Base.Level, } snap.Stats[attributes.EM] = em return (1 + ((16 * em) / (2000 + em)) + char.ReactBonus(atk)) * reactionLvlBase[lvl], snap diff --git a/pkg/simulation/details.go b/pkg/simulation/details.go index 1aae650cbf..0b500060ca 100644 --- a/pkg/simulation/details.go +++ b/pkg/simulation/details.go @@ -50,9 +50,9 @@ func (s *Simulation) CharacterDetails() []*model.Character { AttackTag: attacks.AttackTagNone, }) // convert all atk%, def% and hp% into flat amounts by tacking on base - snap.Stats[attributes.HP] += c.Base.HP * (1 + snap.Stats[attributes.HPP]) - snap.Stats[attributes.DEF] += c.Base.Def * (1 + snap.Stats[attributes.DEFP]) - snap.Stats[attributes.ATK] += c.Base.Atk * (1 + snap.Stats[attributes.ATKP]) + snap.Stats[attributes.HP] = snap.Stats.MaxHP() + snap.Stats[attributes.DEF] = snap.Stats.TotalDEF() + snap.Stats[attributes.ATK] = snap.Stats.TotalATK() snap.Stats[attributes.HPP] = 0 snap.Stats[attributes.DEFP] = 0 snap.Stats[attributes.ATKP] = 0 diff --git a/pkg/stats/status/status.go b/pkg/stats/status/status.go index 8e07b50a4f..6a9d571f89 100644 --- a/pkg/stats/status/status.go +++ b/pkg/stats/status/status.go @@ -61,7 +61,7 @@ func avgUpdate(arr []float64, index int, value float64) []float64 { } func damageMod(c *character.CharWrapper, elvl int) float64 { - def := c.TotalDef() + def := c.TotalDef(false) defmod := 1 - (def / (def + 5*float64(elvl) + 500)) // TODO: implement resmod resmod := 1.0