Skip to content

Commit

Permalink
Change base stats to use stat array (#2280)
Browse files Browse the repository at this point in the history
* Refactored char.Base.Atk to use char.Stats(attributes.BaseAtk)

* Changed char.Base.Def to appropriate attributes.BaseDef

* Fixed baseHP using baseAtk instead

* fixup! traveler

* Clean up snapshot struct

* Simplify MaxHP/TotalAtk/TotalDef funcs

* Use NonExtraDefense for noelle/itto/peakpatrolsong

---------

Co-authored-by: Shizuka <shizuka.alpha@gmail.com>
  • Loading branch information
Charlie-Zheng and shizukayuki authored Nov 27, 2024
1 parent e864c9c commit 1930932
Show file tree
Hide file tree
Showing 55 changed files with 133 additions and 175 deletions.
4 changes: 2 additions & 2 deletions internal/characters/albedo/burst.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion internal/characters/bennett/burst.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion internal/characters/charlotte/burst.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()]

Expand Down
2 changes: 1 addition & 1 deletion internal/characters/chiori/asc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion internal/characters/chiori/burst.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion internal/characters/chiori/cons.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
2 changes: 1 addition & 1 deletion internal/characters/chiori/kinu.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions internal/characters/chiori/skill.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion internal/characters/clorinde/asc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
2 changes: 1 addition & 1 deletion internal/characters/faruzan/asc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
4 changes: 2 additions & 2 deletions internal/characters/gorou/asc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
}
3 changes: 1 addition & 2 deletions internal/characters/gorou/burst.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
})

Expand Down
2 changes: 1 addition & 1 deletion internal/characters/gorou/gorou.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion internal/characters/hutao/skill.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion internal/characters/itto/asc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
2 changes: 1 addition & 1 deletion internal/characters/itto/burst.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions internal/characters/jean/asc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
})
}
Expand Down
2 changes: 1 addition & 1 deletion internal/characters/jean/burst.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()]

Expand Down
3 changes: 1 addition & 2 deletions internal/characters/kaeya/skill.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
})
}
Expand Down
2 changes: 1 addition & 1 deletion internal/characters/kokomi/skill.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions internal/characters/noelle/asc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
})
Expand Down
2 changes: 1 addition & 1 deletion internal/characters/noelle/burst.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions internal/characters/noelle/skill.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand Down Expand Up @@ -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,
Expand Down
3 changes: 1 addition & 2 deletions internal/characters/qiqi/qiqi.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion internal/characters/sara/skill.go
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
4 changes: 2 additions & 2 deletions internal/characters/sayu/burst.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion internal/characters/traveler/common/anemo/traveleranemo.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
23 changes: 18 additions & 5 deletions internal/characters/traveler/common/baseatk.go
Original file line number Diff line number Diff line change
@@ -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
},
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
Loading

0 comments on commit 1930932

Please sign in to comment.