From 6c8d76b61e664712c874affd67f8481cad903532 Mon Sep 17 00:00:00 2001 From: kengzzzz Date: Fri, 29 Nov 2024 21:11:35 +0700 Subject: [PATCH] citlali from ange1o5 --- internal/characters/citlali/asc.go | 76 +++++++++ internal/characters/citlali/burst.go | 69 ++++++++ internal/characters/citlali/citlali.go | 59 +++++++ internal/characters/citlali/citlali_gen.go | 39 +++++ internal/characters/citlali/cons.go | 87 ++++++++++ .../characters/citlali/data_gen.textproto | 151 ++++++++++++++++++ internal/characters/citlali/shield.go | 29 ++++ internal/characters/citlali/skill.go | 107 +++++++++++++ pkg/core/attacks/icd_groups_gen.go | 5 + pkg/core/attacks/icd_tags_gen.go | 1 + pkg/core/keys/keys_char_gen.go | 5 + pkg/core/player/shield/shield.go | 1 + pkg/shortcut/characters.go | 1 + pkg/simulation/imports_char_gen.go | 1 + .../db/src/Data/char_data.generated.json | 17 ++ .../ui/src/Data/char_data.generated.json | 17 ++ 16 files changed, 665 insertions(+) create mode 100644 internal/characters/citlali/asc.go create mode 100644 internal/characters/citlali/burst.go create mode 100644 internal/characters/citlali/citlali.go create mode 100644 internal/characters/citlali/citlali_gen.go create mode 100644 internal/characters/citlali/cons.go create mode 100644 internal/characters/citlali/data_gen.textproto create mode 100644 internal/characters/citlali/shield.go create mode 100644 internal/characters/citlali/skill.go diff --git a/internal/characters/citlali/asc.go b/internal/characters/citlali/asc.go new file mode 100644 index 000000000..34b286e3e --- /dev/null +++ b/internal/characters/citlali/asc.go @@ -0,0 +1,76 @@ +package citlali + +import ( + "github.com/genshinsim/gcsim/pkg/core/attributes" + "github.com/genshinsim/gcsim/pkg/core/combat" + "github.com/genshinsim/gcsim/pkg/core/event" + "github.com/genshinsim/gcsim/pkg/enemy" + "github.com/genshinsim/gcsim/pkg/modifier" +) + +const ( + nightSoulGenerationIcd = "a1-ns-icd-key" +) + +func (c *char) a1() { + if c.Base.Ascension < 1 { + return + } + c.Core.Events.Subscribe(event.OnMelt, c.a1Hook, "citlali-a1-onmelt-res-shred") + c.Core.Events.Subscribe(event.OnFrozen, c.a1Hook, "citlali-a1-onfrozen-res-shred") +} +func (c *char) a1Hook(args ...interface{}) bool { + t, ok := args[0].(*enemy.Enemy) + if !ok { + return false + } + if !c.nightsoulState.HasBlessing() { + return false + } + if !c.StatusIsActive(nightSoulGenerationIcd) { + c.AddStatus(nightSoulGenerationIcd, 8*60, false) + c.nightsoulState.GeneratePoints(16) + c.ActivateItzpapa(c.itzpapaSrc) + if c.Base.Cons >= 1 { + c.numStellarBlades += 3 + } + } + amt := -0.2 + if c.Base.Cons >= 2 { + amt = -0.4 + } + t.AddResistMod(combat.ResistMod{ + Base: modifier.NewBaseWithHitlag("citlali-a1-hydro-res-shred", 12*60), + Ele: attributes.Hydro, + Value: amt, + }) + t.AddResistMod(combat.ResistMod{ + Base: modifier.NewBaseWithHitlag("citlali-a1-pyro-res-shred", 12*60), + Ele: attributes.Pyro, + Value: amt, + }) + return false +} +func (c *char) a4() { + if c.Base.Ascension < 4 { + return + } + c.Core.Events.Subscribe(event.OnNightsoulBurst, func(args ...interface{}) bool { + c.nightsoulState.GeneratePoints(4) + c.ActivateItzpapa(c.itzpapaSrc) + return false + }, "citlali-a4-ns-gain") +} +func (c *char) a4Dmg(abil string) float64 { + if c.Base.Ascension < 4 { + return 0 + } + em := c.NonExtraStat(attributes.EM) + if abil == iceStormAbil { + return 24 * em + } + if abil == frostFallAbil { + return 0.9 * em + } + return 0 +} diff --git a/internal/characters/citlali/burst.go b/internal/characters/citlali/burst.go new file mode 100644 index 000000000..2f7451843 --- /dev/null +++ b/internal/characters/citlali/burst.go @@ -0,0 +1,69 @@ +package citlali + +import ( + "github.com/genshinsim/gcsim/internal/frames" + "github.com/genshinsim/gcsim/pkg/core/action" + "github.com/genshinsim/gcsim/pkg/core/attacks" + "github.com/genshinsim/gcsim/pkg/core/attributes" + "github.com/genshinsim/gcsim/pkg/core/combat" +) + +const ( + iceStormHitmark = 118 + spiritVesselSkullHitmark = 223 + iceStormAbil = "Ice Storm DMG" +) + +var ( + burstFrames []int +) + +func init() { + burstFrames = frames.InitAbilSlice(133) // Q -> Swap +} +func (c *char) Burst(p map[string]int) (action.Info, error) { + aiIceStorm := combat.AttackInfo{ + ActorIndex: c.Index, + Abil: iceStormAbil, + AttackTag: attacks.AttackTagElementalBurst, + AdditionalTags: []attacks.AdditionalTag{attacks.AdditionalTagNightsoul}, + ICDTag: attacks.ICDTagNone, + ICDGroup: attacks.ICDGroupDefault, + StrikeType: attacks.StrikeTypeDefault, + Element: attributes.Cryo, + Durability: 50, + Mult: 9.677, + FlatDmg: c.a4Dmg(iceStormAbil), + } + aiSpiritVesselSkull := combat.AttackInfo{ + ActorIndex: c.Index, + Abil: "Spiritvessel Skull DMG", + AttackTag: attacks.AttackTagElementalBurst, + AdditionalTags: []attacks.AdditionalTag{attacks.AdditionalTagNightsoul}, + ICDTag: attacks.ICDTagElementalBurst, // TODO: check this + ICDGroup: attacks.ICDGroupDefault, + StrikeType: attacks.StrikeTypeDefault, + Element: attributes.Cryo, + Durability: 25, + Mult: 2.419, + } + c.ConsumeEnergy(5) + c.SetCD(action.ActionBurst, 15*60) + c.nightsoulState.GeneratePoints(24) + c.ActivateItzpapa(c.itzpapaSrc) + c.Core.QueueAttack(aiIceStorm, combat.NewCircleHitOnTarget(c.Core.Combat.PrimaryTarget(), nil, 6.5), iceStormHitmark, iceStormHitmark) + enemies := c.Core.Combat.EnemiesWithinArea(combat.NewCircleHitOnTarget(c.Core.Combat.Player(), nil, 7), nil) + c.QueueCharTask(func() { + c.nightsoulState.GeneratePoints(float64(3 * len(enemies))) + c.ActivateItzpapa(c.itzpapaSrc) + }, spiritVesselSkullHitmark) + for _, enemy := range enemies { + c.Core.QueueAttack(aiSpiritVesselSkull, combat.NewSingleTargetHit(enemy.Key()), spiritVesselSkullHitmark, spiritVesselSkullHitmark) + } + return action.Info{ + Frames: frames.NewAbilFunc(burstFrames), + AnimationLength: burstFrames[action.InvalidAction], + CanQueueAfter: burstFrames[action.ActionBurst], + State: action.BurstState, + }, nil +} diff --git a/internal/characters/citlali/citlali.go b/internal/characters/citlali/citlali.go new file mode 100644 index 000000000..b5c8f9657 --- /dev/null +++ b/internal/characters/citlali/citlali.go @@ -0,0 +1,59 @@ +package citlali + +// Citlali's Frostfall Storm applies once every 1.5s +// Initial E hit has no ICD. +// Initial burst has no ICD. +// Spiritvessel Skull ICD is default. +// C4 has no ICD. +// NA is default. +// CA has no ICD. +// 5 particles on initial E hit +import ( + tmpl "github.com/genshinsim/gcsim/internal/template/character" + "github.com/genshinsim/gcsim/internal/template/nightsoul" + "github.com/genshinsim/gcsim/pkg/core" + "github.com/genshinsim/gcsim/pkg/core/info" + "github.com/genshinsim/gcsim/pkg/core/keys" + "github.com/genshinsim/gcsim/pkg/core/player/character" +) + +func init() { + core.RegisterCharFunc(keys.Citlali, NewChar) +} + +type char struct { + *tmpl.Character + nightsoulState *nightsoul.State + itzpapaSrc int + skillShield *shd + numStellarBlades int +} + +func NewChar(s *core.Core, w *character.CharWrapper, _ info.CharacterProfile) error { + c := char{} + c.Character = tmpl.NewWithWrapper(s, w) + c.EnergyMax = 60 + c.NormalHitNum = 3 + c.SkillCon = 3 + c.BurstCon = 5 + c.HasArkhe = false + w.Character = &c + c.nightsoulState = nightsoul.New(s, w) + c.nightsoulState.MaxPoints = 80 // TODO: the REAL one + c.itzpapaSrc = -1 + return nil +} +func (c *char) Init() error { + c.a1() + c.a4() + c.c1() + return nil +} +func (c *char) Condition(fields []string) (any, error) { + switch fields[0] { + case "nightsoul": + return c.nightsoulState.Condition(fields) + default: + return c.Character.Condition(fields) + } +} diff --git a/internal/characters/citlali/citlali_gen.go b/internal/characters/citlali/citlali_gen.go new file mode 100644 index 000000000..bb8981590 --- /dev/null +++ b/internal/characters/citlali/citlali_gen.go @@ -0,0 +1,39 @@ +// Code generated by "pipeline"; DO NOT EDIT. +package citlali +import ( + _ "embed" + "fmt" + "slices" + "github.com/genshinsim/gcsim/pkg/core/action" + "github.com/genshinsim/gcsim/pkg/core/keys" + "github.com/genshinsim/gcsim/pkg/gcs/validation" + "github.com/genshinsim/gcsim/pkg/model" + "google.golang.org/protobuf/encoding/prototext" +) +//go:embed data_gen.textproto +var pbData []byte +var base *model.AvatarData +var paramKeysValidation = map[action.Action][]string{} +func init() { + base = &model.AvatarData{} + err := prototext.Unmarshal(pbData, base) + if err != nil { + panic(err) + } + validation.RegisterCharParamValidationFunc(keys.Citlali, ValidateParamKeys) +} +func ValidateParamKeys(a action.Action, keys []string) error { + valid, ok := paramKeysValidation[a] + if !ok { + return nil + } + for _, v := range keys { + if !slices.Contains(valid, v) { + return fmt.Errorf("key %v is invalid for action %v", v, a.String()) + } + } + return nil +} +func (x *char) Data() *model.AvatarData { + return base +} \ No newline at end of file diff --git a/internal/characters/citlali/cons.go b/internal/characters/citlali/cons.go new file mode 100644 index 000000000..1e3803e46 --- /dev/null +++ b/internal/characters/citlali/cons.go @@ -0,0 +1,87 @@ +package citlali + +import ( + "github.com/genshinsim/gcsim/pkg/core/attacks" + "github.com/genshinsim/gcsim/pkg/core/attributes" + "github.com/genshinsim/gcsim/pkg/core/combat" + "github.com/genshinsim/gcsim/pkg/core/event" + "github.com/genshinsim/gcsim/pkg/core/glog" + "github.com/genshinsim/gcsim/pkg/core/player/character" + "github.com/genshinsim/gcsim/pkg/modifier" +) + +const c4SkullIcd = "c4-skull-icd" + +// Additionally, when Citlali is using her leap, or is Aiming or using her +// Charged Attack in mid-air, her Phlogiston consumption is decreased by 45%. +// NOT IMPLEMENTED +func (c *char) c1() { + c.Core.Events.Subscribe(event.OnEnemyDamage, func(args ...interface{}) bool { + atk := args[1].(*combat.AttackEvent) + if c.Index == atk.Info.ActorIndex { + return false + } + if c.numStellarBlades > 0 { + em := c.NonExtraStat(attributes.EM) + amt := em * 2 + if c.Core.Flags.LogDebug { + c.Core.Log.NewEvent("Citlali C1 proc dmg add", glog.LogPreDamageMod, atk.Info.ActorIndex). + Write("before", atk.Info.FlatDmg). + Write("addition", amt). + Write("Stellar Blades left", c.numStellarBlades) + } + atk.Info.FlatDmg += amt + c.numStellarBlades-- + } + return false + }, "citlali-c1-on-dmg") +} + +// For now, assuming her shield won't be destroyed ahead of time +func (c *char) c2() { + if c.Base.Cons < 2 { + return + } + chars := c.Core.Player.Chars() + for _, char := range chars { + char.AddStatMod(character.StatMod{ + Base: modifier.NewBaseWithHitlag("citlali-c2-em", 20*60), + AffectedStat: attributes.EM, + Amount: func() ([]float64, bool) { + if c.Index == char.Index { + buffSelf := make([]float64, attributes.EndStatType) + buffSelf[attributes.EM] = 125 + return buffSelf, true + } + buffOther := make([]float64, attributes.EndStatType) + buffOther[attributes.EM] = 250 + return buffOther, true + }, + }) + } +} +func (c *char) c4Skull() { + if c.Base.Cons < 4 { + return + } + if c.StatusIsActive(c4SkullIcd) { + return + } + c.AddStatus(c4SkullIcd, 8*60, false) + c.nightsoulState.GeneratePoints(16) + aiSpiritVesselSkull := combat.AttackInfo{ + ActorIndex: c.Index, + Abil: "Spiritvessel Skull DMG (C4)", + AttackTag: attacks.AttackTagNone, + AdditionalTags: []attacks.AdditionalTag{attacks.AdditionalTagNightsoul}, + ICDTag: attacks.ICDTagElementalBurst, // TODO: check this + ICDGroup: attacks.ICDGroupDefault, + StrikeType: attacks.StrikeTypeDefault, + Element: attributes.Cryo, + Durability: 25, + FlatDmg: 12 * c.NonExtraStat(attributes.EM), + } + // TODO: the actual hitmark + c.Core.QueueAttack(aiSpiritVesselSkull, combat.NewSingleTargetHit(c.Core.Combat.PrimaryTarget().Key()), + spiritVesselSkullHitmark-iceStormHitmark, spiritVesselSkullHitmark-iceStormHitmark) +} diff --git a/internal/characters/citlali/data_gen.textproto b/internal/characters/citlali/data_gen.textproto new file mode 100644 index 000000000..3e710f84e --- /dev/null +++ b/internal/characters/citlali/data_gen.textproto @@ -0,0 +1,151 @@ +id: 10000107 +key: "citlali" +rarity: QUALITY_ORANGE +body: BODY_GIRL +region: ASSOC_TYPE_NATLAN +element: Ice +weapon_class: WEAPON_CATALYST +icon_name: "UI_AvatarIcon_Layla" +stats: { + base_hp: 906.0 + base_atk: 10.0 + base_def: 59.0 + hp_curve: GROW_CURVE_HP_S5 + atk_curve: GROW_CURVE_ATTACK_S5 + def_cruve: GROW_CURVE_HP_S5 + promo_data: { + max_level: 20 + add_props: { + prop_type: FIGHT_PROP_BASE_HP + } + add_props: { + prop_type: FIGHT_PROP_BASE_DEFENSE + } + add_props: { + prop_type: FIGHT_PROP_BASE_ATTACK + } + add_props: { + prop_type: FIGHT_PROP_ELEMENT_MASTERY + } + } + promo_data: { + max_level: 40 + add_props: { + prop_type: FIGHT_PROP_BASE_HP + value: 890.95044 + } + add_props: { + prop_type: FIGHT_PROP_BASE_DEFENSE + value: 53.865 + } + add_props: { + prop_type: FIGHT_PROP_BASE_ATTACK + value: 19.795113 + } + add_props: { + prop_type: FIGHT_PROP_ELEMENT_MASTERY + } + } + promo_data: { + max_level: 50 + add_props: { + prop_type: FIGHT_PROP_BASE_HP + value: 1523.9941 + } + add_props: { + prop_type: FIGHT_PROP_BASE_DEFENSE + value: 92.1375 + } + add_props: { + prop_type: FIGHT_PROP_BASE_ATTACK + value: 33.86006 + } + add_props: { + prop_type: FIGHT_PROP_ELEMENT_MASTERY + value: 28.8 + } + } + promo_data: { + max_level: 60 + add_props: { + prop_type: FIGHT_PROP_BASE_HP + value: 2368.0525 + } + add_props: { + prop_type: FIGHT_PROP_BASE_DEFENSE + value: 143.1675 + } + add_props: { + prop_type: FIGHT_PROP_BASE_ATTACK + value: 52.613323 + } + add_props: { + prop_type: FIGHT_PROP_ELEMENT_MASTERY + value: 57.6 + } + } + promo_data: { + max_level: 70 + add_props: { + prop_type: FIGHT_PROP_BASE_HP + value: 3001.0962 + } + add_props: { + prop_type: FIGHT_PROP_BASE_DEFENSE + value: 181.44 + } + add_props: { + prop_type: FIGHT_PROP_BASE_ATTACK + value: 66.67827 + } + add_props: { + prop_type: FIGHT_PROP_ELEMENT_MASTERY + value: 57.6 + } + } + promo_data: { + max_level: 80 + add_props: { + prop_type: FIGHT_PROP_BASE_HP + value: 3634.14 + } + add_props: { + prop_type: FIGHT_PROP_BASE_DEFENSE + value: 219.7125 + } + add_props: { + prop_type: FIGHT_PROP_BASE_ATTACK + value: 80.74322 + } + add_props: { + prop_type: FIGHT_PROP_ELEMENT_MASTERY + value: 86.4 + } + } + promo_data: { + max_level: 90 + add_props: { + prop_type: FIGHT_PROP_BASE_HP + value: 4267.1836 + } + add_props: { + prop_type: FIGHT_PROP_BASE_DEFENSE + value: 257.985 + } + add_props: { + prop_type: FIGHT_PROP_BASE_ATTACK + value: 94.80817 + } + add_props: { + prop_type: FIGHT_PROP_ELEMENT_MASTERY + value: 115.2 + } + } +} +skill_details: { + skill: 10402 + burst: 10403 + attack: 10401 + burst_energy_cost: 60 +} +name_text_hash_map: 2876340530 \ No newline at end of file diff --git a/internal/characters/citlali/shield.go b/internal/characters/citlali/shield.go new file mode 100644 index 000000000..dea146279 --- /dev/null +++ b/internal/characters/citlali/shield.go @@ -0,0 +1,29 @@ +package citlali + +import ( + "github.com/genshinsim/gcsim/pkg/core/attributes" + "github.com/genshinsim/gcsim/pkg/core/player/shield" +) + +// need to rewrite Expires +type shd struct { + *shield.Tmpl +} + +func (c *char) addShield() { + em := c.NonExtraStat(attributes.EM) + shieldHP := 10.368 * em + c.skillShield = &shd{ + Tmpl: &shield.Tmpl{ + ActorIndex: c.Index, + Target: -1, + Src: c.Core.F, + Name: "Citalali Skill Shield", + ShieldType: shield.CitlaliSkill, + HP: shieldHP, + Ele: attributes.Cryo, + Expires: c.Core.F + 20*60, + }, + } + c.Core.Player.Shields.Add(c.skillShield) +} diff --git a/internal/characters/citlali/skill.go b/internal/characters/citlali/skill.go new file mode 100644 index 000000000..2f79059e3 --- /dev/null +++ b/internal/characters/citlali/skill.go @@ -0,0 +1,107 @@ +package citlali + +import ( + "github.com/genshinsim/gcsim/internal/frames" + "github.com/genshinsim/gcsim/pkg/core/action" + "github.com/genshinsim/gcsim/pkg/core/attacks" + "github.com/genshinsim/gcsim/pkg/core/attributes" + "github.com/genshinsim/gcsim/pkg/core/combat" +) + +const ( + itzpapaInterval = 60 // looking at footage, seems like both attack and NS consumption intervals are the same + obsidianTzitzimitlHitmark = 23 + itzpapaKey = "itzpapa-key" + frostFallAbil = "Frostfall Storm DMG" +) + +var ( + skillFrames []int +) + +func init() { + skillFrames = frames.InitAbilSlice(49) // E -> Q +} +func (c *char) Skill(p map[string]int) (action.Info, error) { + ai := combat.AttackInfo{ + ActorIndex: c.Index, + Abil: "Obsidian Tzitzimitl DMG", + AttackTag: attacks.AttackTagElementalArt, + AdditionalTags: []attacks.AdditionalTag{attacks.AdditionalTagNightsoul}, + ICDTag: attacks.ICDTagNone, + ICDGroup: attacks.ICDGroupDefault, + StrikeType: attacks.StrikeTypeDefault, + Element: attributes.Cryo, + Durability: 25, + Mult: 1.313, + } + c.QueueCharTask(func() { + c.SetCD(action.ActionSkill, 16*60) + c.addShield() + }, 1) + c.Core.QueueAttack(ai, combat.NewCircleHitOnTarget(c.Core.Combat.PrimaryTarget(), nil, 6), obsidianTzitzimitlHitmark, obsidianTzitzimitlHitmark, c.particleCB) + if c.nightsoulState.HasBlessing() { + c.nightsoulState.GeneratePoints(24) + } else { + c.nightsoulState.EnterBlessing(24) + } + c.itzpapaSrc = c.Core.F + c.ActivateItzpapa(c.Core.F) + if c.Base.Cons >= 1 { + c.numStellarBlades = 10 + c.c2() + } + return action.Info{ + Frames: frames.NewAbilFunc(skillFrames), + AnimationLength: skillFrames[action.InvalidAction], + CanQueueAfter: skillFrames[action.ActionBurst], + State: action.SkillState, + }, nil +} +func (c *char) ActivateItzpapa(src int) { + // try to activate Itzpapa each time Citlali gains NS points to avoid event subscribtion + if c.nightsoulState.Points() >= 50 { + // if it's activation or REactivation + if !c.StatusIsActive(itzpapaKey) || src != c.itzpapaSrc { + // this status is active only when Itzpapa is in "attack mode" + c.AddStatus(itzpapaKey, -1, false) + c.QueueCharTask(c.ItzpapaHit(src), itzpapaInterval) + } + } +} +func (c *char) ItzpapaHit(src int) func() { + return func() { + if src != c.itzpapaSrc { + return + } + if !c.StatusIsActive(itzpapaKey) { + return + } + if c.nightsoulState.Points() == 0 { + c.nightsoulState.ExitBlessing() + c.DeleteStatus(itzpapaKey) + c.numStellarBlades = 0 // C1 + return + } + ai := combat.AttackInfo{ + ActorIndex: c.Index, + Abil: frostFallAbil, + AttackTag: attacks.AttackTagElementalArt, + AdditionalTags: []attacks.AdditionalTag{attacks.AdditionalTagNightsoul}, + ICDTag: attacks.ICDTagCitlaliItzpapa, + ICDGroup: attacks.ICDGroupCitlaliItzpapa, + StrikeType: attacks.StrikeTypeDefault, + Element: attributes.Cryo, + Durability: 25, + Mult: 0.306, + FlatDmg: c.a4Dmg(frostFallAbil), + } + c.nightsoulState.ConsumePoints(8) + c.Core.QueueAttack(ai, combat.NewCircleHitOnTarget(c.Core.Combat.PrimaryTarget(), nil, 6), 0, 0) + c.QueueCharTask(c.ItzpapaHit(src), itzpapaInterval) + c.c4Skull() + } +} +func (c *char) particleCB(a combat.AttackCB) { + c.Core.QueueParticle(c.Base.Key.String(), 5, attributes.Cryo, c.ParticleDelay) +} diff --git a/pkg/core/attacks/icd_groups_gen.go b/pkg/core/attacks/icd_groups_gen.go index 54f9d4e47..0962c200f 100644 --- a/pkg/core/attacks/icd_groups_gen.go +++ b/pkg/core/attacks/icd_groups_gen.go @@ -38,6 +38,7 @@ const ( ICDGroupYaoyaoRadishBurst ICDGroupYelanBreakthrough ICDGroupYelanBurst + ICDGroupCitlaliItzpapa ICDGroupLength ) @@ -181,4 +182,8 @@ func init() { ICDGroupResetTimer[ICDGroupYelanBurst] = 120 ICDGroupEleApplicationSequence[ICDGroupYelanBurst] = []float64{1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0} ICDGroupDamageSequence[ICDGroupYelanBurst] = []float64{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + + ICDGroupResetTimer[ICDGroupCitlaliItzpapa] = 120 + ICDGroupEleApplicationSequence[ICDGroupCitlaliItzpapa] = []float64{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + ICDGroupDamageSequence[ICDGroupCitlaliItzpapa] = []float64{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} } diff --git a/pkg/core/attacks/icd_tags_gen.go b/pkg/core/attacks/icd_tags_gen.go index 4219fbfb3..4d224c759 100644 --- a/pkg/core/attacks/icd_tags_gen.go +++ b/pkg/core/attacks/icd_tags_gen.go @@ -31,5 +31,6 @@ const ( ICDTagYanfeiFire ICDTagYelanBreakthrough ICDTagYelanBurst + ICDTagCitlaliItzpapa ICDTagLength ) diff --git a/pkg/core/keys/keys_char_gen.go b/pkg/core/keys/keys_char_gen.go index ac3ba3637..52ade9e70 100644 --- a/pkg/core/keys/keys_char_gen.go +++ b/pkg/core/keys/keys_char_gen.go @@ -23,6 +23,7 @@ const ( Chevreuse Chiori Chongyun + Citlali Clorinde Collei Cyno @@ -162,6 +163,10 @@ func init() { charPrettyName[Chongyun] = "Chongyun" CharKeyToEle[Chongyun] = attributes.Cryo + charNames[Citlali] = "citlali" + charPrettyName[Citlali] = "Citlali" + CharKeyToEle[Citlali] = attributes.Cryo + charNames[Clorinde] = "clorinde" charPrettyName[Clorinde] = "Clorinde" CharKeyToEle[Clorinde] = attributes.Electro diff --git a/pkg/core/player/shield/shield.go b/pkg/core/player/shield/shield.go index acb544a83..ad178ca72 100644 --- a/pkg/core/player/shield/shield.go +++ b/pkg/core/player/shield/shield.go @@ -27,6 +27,7 @@ const ( KiraraSkill TravelerHydroC4 SigewinneC2 + CitlaliSkill EndType ) diff --git a/pkg/shortcut/characters.go b/pkg/shortcut/characters.go index 67974d722..01323bbb4 100644 --- a/pkg/shortcut/characters.go +++ b/pkg/shortcut/characters.go @@ -174,4 +174,5 @@ var CharNameToKey = map[string]keys.Char{ "xilonen": keys.Xilonen, "xilo": keys.Xilonen, "sigewinne": keys.Sigewinne, + "citlali": keys.Citlali, } diff --git a/pkg/simulation/imports_char_gen.go b/pkg/simulation/imports_char_gen.go index 146d8db72..efc0055e2 100644 --- a/pkg/simulation/imports_char_gen.go +++ b/pkg/simulation/imports_char_gen.go @@ -18,6 +18,7 @@ import ( _ "github.com/genshinsim/gcsim/internal/characters/chevreuse" _ "github.com/genshinsim/gcsim/internal/characters/chiori" _ "github.com/genshinsim/gcsim/internal/characters/chongyun" + _ "github.com/genshinsim/gcsim/internal/characters/citlali" _ "github.com/genshinsim/gcsim/internal/characters/clorinde" _ "github.com/genshinsim/gcsim/internal/characters/collei" _ "github.com/genshinsim/gcsim/internal/characters/cyno" diff --git a/ui/packages/db/src/Data/char_data.generated.json b/ui/packages/db/src/Data/char_data.generated.json index 6c9127296..58786ff82 100644 --- a/ui/packages/db/src/Data/char_data.generated.json +++ b/ui/packages/db/src/Data/char_data.generated.json @@ -362,6 +362,23 @@ }, "name_text_hash_map ": "2876340530" }, + "citlali": { + "id": 10000107, + "key": "citlali", + "rarity": "QUALITY_ORANGE", + "body": "BODY_GIRL", + "region": "ASSOC_TYPE_NATLAN", + "element": "Ice", + "weapon_class": "WEAPON_CATALYST", + "icon_name": "UI_AvatarIcon_Layla", + "skill_details": { + "skill": 10402, + "burst": 10403, + "attack": 10401, + "burst_energy_cost": 60 + }, + "name_text_hash_map ": "2876340530" + }, "clorinde": { "id": 10000098, "key": "clorinde", diff --git a/ui/packages/ui/src/Data/char_data.generated.json b/ui/packages/ui/src/Data/char_data.generated.json index 6c9127296..58786ff82 100644 --- a/ui/packages/ui/src/Data/char_data.generated.json +++ b/ui/packages/ui/src/Data/char_data.generated.json @@ -362,6 +362,23 @@ }, "name_text_hash_map ": "2876340530" }, + "citlali": { + "id": 10000107, + "key": "citlali", + "rarity": "QUALITY_ORANGE", + "body": "BODY_GIRL", + "region": "ASSOC_TYPE_NATLAN", + "element": "Ice", + "weapon_class": "WEAPON_CATALYST", + "icon_name": "UI_AvatarIcon_Layla", + "skill_details": { + "skill": 10402, + "burst": 10403, + "attack": 10401, + "burst_energy_cost": 60 + }, + "name_text_hash_map ": "2876340530" + }, "clorinde": { "id": 10000098, "key": "clorinde",