Skip to content

Commit

Permalink
chasca from wfpsim
Browse files Browse the repository at this point in the history
  • Loading branch information
kengzzzz committed Nov 30, 2024
1 parent 6ba7129 commit 188d3f2
Show file tree
Hide file tree
Showing 17 changed files with 1,345 additions and 0 deletions.
197 changes: 197 additions & 0 deletions internal/characters/chasca/aimed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
package chasca

import (
"fmt"

"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"
"github.com/genshinsim/gcsim/pkg/core/geometry"
)

var aimedFrames [][]int
var multitargetFrames [][]int
var c6MultitargetFrames [][]int
var c6FatalRoundsFrames [][]int
var aimedHitmarks = []int{15, 86}
var multitargetHitmarks = []int{3, 6, 9, 12, 15, 18}
var firstBulletLoadFrames = 33
var additionalBulletLoadFrames = 20
var c6firstBulletLoadFrames = 20
var c6AdditionalBulletLoadFrames = 14
var fatalBulletLoadFrames = 2

func init() {
aimedFrames = make([][]int, 2)
// Aimed Shot
aimedFrames[0] = frames.InitAbilSlice(26)
aimedFrames[0][action.ActionDash] = aimedHitmarks[0]
aimedFrames[0][action.ActionJump] = aimedHitmarks[0]
// Fully-Charged Aimed Shot
aimedFrames[1] = frames.InitAbilSlice(96)
aimedFrames[1][action.ActionDash] = aimedHitmarks[1]
aimedFrames[1][action.ActionJump] = aimedHitmarks[1]
multitargetFrames = make([][]int, 6)
multitargetFrames[0] = frames.InitAbilSlice(firstBulletLoadFrames)
multitargetFrames[0][action.ActionAim] = multitargetHitmarks[0]
multitargetFrames[1] = frames.InitAbilSlice(additionalBulletLoadFrames + firstBulletLoadFrames)
multitargetFrames[1][action.ActionAim] = multitargetHitmarks[1]
multitargetFrames[2] = frames.InitAbilSlice(additionalBulletLoadFrames*2 + firstBulletLoadFrames)
multitargetFrames[2][action.ActionAim] = multitargetHitmarks[2]
multitargetFrames[3] = frames.InitAbilSlice(additionalBulletLoadFrames*3 + firstBulletLoadFrames)
multitargetFrames[3][action.ActionAim] = multitargetHitmarks[3]
multitargetFrames[4] = frames.InitAbilSlice(additionalBulletLoadFrames*4 + firstBulletLoadFrames)
multitargetFrames[4][action.ActionAim] = multitargetHitmarks[4]
multitargetFrames[5] = frames.InitAbilSlice(additionalBulletLoadFrames*5 + firstBulletLoadFrames)
multitargetFrames[5][action.ActionAim] = multitargetHitmarks[5]
c6MultitargetFrames = make([][]int, 6)
c6MultitargetFrames[0] = frames.InitAbilSlice(c6firstBulletLoadFrames)
c6MultitargetFrames[0][action.ActionAim] = multitargetHitmarks[0]
c6MultitargetFrames[1] = frames.InitAbilSlice(c6AdditionalBulletLoadFrames + c6firstBulletLoadFrames)
c6MultitargetFrames[1][action.ActionAim] = multitargetHitmarks[1]
c6MultitargetFrames[2] = frames.InitAbilSlice(c6AdditionalBulletLoadFrames*2 + c6firstBulletLoadFrames)
c6MultitargetFrames[2][action.ActionAim] = multitargetHitmarks[2]
c6MultitargetFrames[3] = frames.InitAbilSlice(c6AdditionalBulletLoadFrames*3 + c6firstBulletLoadFrames)
c6MultitargetFrames[3][action.ActionAim] = multitargetHitmarks[3]
c6MultitargetFrames[4] = frames.InitAbilSlice(c6AdditionalBulletLoadFrames*4 + c6firstBulletLoadFrames)
c6MultitargetFrames[4][action.ActionAim] = multitargetHitmarks[4]
c6MultitargetFrames[5] = frames.InitAbilSlice(c6AdditionalBulletLoadFrames*5 + c6firstBulletLoadFrames)
c6MultitargetFrames[5][action.ActionAim] = multitargetHitmarks[5]
c6FatalRoundsFrames = make([][]int, 6)
c6FatalRoundsFrames[0] = frames.InitAbilSlice(fatalBulletLoadFrames * 1)
c6FatalRoundsFrames[0][action.ActionAim] = multitargetHitmarks[0]
c6FatalRoundsFrames[1] = frames.InitAbilSlice(fatalBulletLoadFrames * 2)
c6FatalRoundsFrames[1][action.ActionAim] = multitargetHitmarks[1]
c6FatalRoundsFrames[2] = frames.InitAbilSlice(fatalBulletLoadFrames * 3)
c6FatalRoundsFrames[2][action.ActionAim] = multitargetHitmarks[2]
c6FatalRoundsFrames[3] = frames.InitAbilSlice(fatalBulletLoadFrames * 4)
c6FatalRoundsFrames[3][action.ActionAim] = multitargetHitmarks[3]
c6FatalRoundsFrames[4] = frames.InitAbilSlice(fatalBulletLoadFrames * 5)
c6FatalRoundsFrames[4][action.ActionAim] = multitargetHitmarks[4]
c6FatalRoundsFrames[5] = frames.InitAbilSlice(fatalBulletLoadFrames * 6)
c6FatalRoundsFrames[5][action.ActionAim] = multitargetHitmarks[5]
}
func (c *char) Aimed(p map[string]int) (action.Info, error) {
if c.nightsoulState.HasBlessing() {
return c.MultitargetFireHold(p)
}
hold, ok := p["hold"]
if !ok {
hold = attacks.AimParamLv1
}
switch hold {
case attacks.AimParamPhys:
case attacks.AimParamLv1:
default:
return action.Info{}, fmt.Errorf("invalid hold param supplied, got %v", hold)
}
travel, ok := p["travel"]
if !ok {
travel = 10
}
weakspot := p["weakspot"]
ai := combat.AttackInfo{
ActorIndex: c.Index,
Abil: "Fully-Charged Aimed Shot",
AttackTag: attacks.AttackTagExtra,
ICDTag: attacks.ICDTagNone,
ICDGroup: attacks.ICDGroupDefault,
StrikeType: attacks.StrikeTypePierce,
Element: attributes.Anemo,
Durability: 25,
Mult: aim[c.TalentLvlAttack()],
HitWeakPoint: weakspot == 1,
HitlagHaltFrames: 0.12 * 60,
HitlagFactor: 0.01,
HitlagOnHeadshotOnly: true,
IsDeployable: true,
}
if hold < attacks.AimParamLv1 {
ai.Abil = "Aimed Shot"
ai.Element = attributes.Physical
ai.Mult = aim[c.TalentLvlAttack()]
}
c.Core.QueueAttack(
ai,
combat.NewBoxHit(
c.Core.Combat.Player(),
c.Core.Combat.PrimaryTarget(),
geometry.Point{Y: -0.5},
0.1,
1,
),
aimedHitmarks[hold],
aimedHitmarks[hold]+travel,
)
return action.Info{
Frames: frames.NewAbilFunc(aimedFrames[hold]),
AnimationLength: aimedFrames[hold][action.InvalidAction],
CanQueueAfter: aimedHitmarks[hold],
State: action.AimState,
}, nil
}
func (c *char) MultitargetFireHold(p map[string]int) (action.Info, error) {
hold, ok := p["hold"]
if !ok {
hold = 6 // Default 6 bullet
}
if hold < 1 || hold > 6 {
return action.Info{}, fmt.Errorf("invalid hold param supplied, got %v", hold)
}
c.loadShadowhuntShells(hold)
for i := len(c.shadowhuntShells) - 1; i >= 0; i-- {
element := c.shadowhuntShells[i]
ai := combat.AttackInfo{
ActorIndex: c.Index,
Abil: "Shining Shadowhunt Shell",
AttackTag: attacks.AttackTagExtra,
ICDTag: attacks.ICDTagChascaShot,
ICDGroup: attacks.ICDGroupChascaShot,
StrikeType: attacks.StrikeTypeDefault,
Element: element,
Durability: 25,
Mult: skillShiningShadowhunt[c.TalentLvlSkill()],
}
if element != attributes.Anemo && c.Base.Cons >= 2 && !c.StatusIsActive(c2icd) {
c2ai := combat.AttackInfo{
ActorIndex: c.Index,
Abil: "C2 Shining Shadowhunt Shell",
AttackTag: attacks.AttackTagExtra,
ICDTag: attacks.ICDTagChascaShot,
ICDGroup: attacks.ICDGroupChascaShot,
StrikeType: attacks.StrikeTypeDefault,
Element: element,
Durability: 25,
Mult: 400 / 100,
}
ap := combat.NewBoxHitOnTarget(c.Core.Combat.PrimaryTarget(), nil, 5, 5)
c.Core.QueueAttack(c2ai, ap, 0, 2)
c.AddStatus(c2icd, -1, false)
}
if element == attributes.Anemo {
ai.Abil = "Shadowhunt Shell"
ai.Element = attributes.Anemo
ai.Mult = skillShadowhunt[c.TalentLvlSkill()]
}
ap := combat.NewBoxHitOnTarget(c.Core.Combat.PrimaryTarget(), nil, 1, 1)
c.Core.QueueAttack(ai, ap, 0, firstBulletLoadFrames+additionalBulletLoadFrames*(hold-1)+(-i*4), c.particleCB) // -i since start from the end of the list
c.c6()
}
c.DeleteStatus(c2icd)
if c.Base.Cons < 6 {
return action.Info{
Frames: frames.NewAbilFunc(multitargetFrames[hold-1]),
AnimationLength: multitargetFrames[hold-1][action.InvalidAction],
CanQueueAfter: multitargetFrames[hold-1][action.ActionSkill],
State: action.ChargeAttackState,
}, nil
}
return action.Info{
Frames: frames.NewAbilFunc(c6MultitargetFrames[hold-1]),
AnimationLength: c6MultitargetFrames[hold-1][action.InvalidAction],
CanQueueAfter: c6MultitargetFrames[hold-1][action.ActionBurst],
State: action.ChargeAttackState,
}, nil
}
107 changes: 107 additions & 0 deletions internal/characters/chasca/asc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package chasca

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"
)

func (c *char) a1() {
if c.Base.Ascension < 1 {
return
}
chance := 0.0
if c.Base.Cons >= 1 {
chance = 0.333
}
if len(c.shadowhuntShells) >= 3 {
uniqueCount := len(c.uniqueConversionElements)
switch uniqueCount {
case 1:
chance += 0.333
case 2:
chance += 0.667
default:
chance += 1.0
}
}
if c.Core.Rand.Float64() < chance {
if len(c.conversionElements) > 0 {
randomIndex := c.Core.Rand.Intn(len(c.conversionElements))
c.shadowhuntShells[2] = c.conversionElements[randomIndex]
if c.Base.Cons >= 1 {
c1RandomIndex := c.Core.Rand.Intn(len(c.conversionElements))
c.shadowhuntShells[1] = c.conversionElements[c1RandomIndex]
}
} else {
c.Core.Log.NewEvent("chasca a1: conversionElements is empty", glog.LogWarnings, -1)
}
}
}
func (c *char) a1Amount() float64 {
a1Boost := 0.0
if c.Base.Ascension < 1 {
return a1Boost
}
uniqueCount := len(c.uniqueConversionElements) + c.c2stacks()
switch uniqueCount {
case 1:
a1Boost = 0.15
case 2:
a1Boost = 0.35
default:
a1Boost = 0.65
}
mDmg := make([]float64, attributes.EndStatType)
mDmg[attributes.DmgP] = a1Boost
c.AddAttackMod(character.AttackMod{
Base: modifier.NewBase("chasca-a1-dmg-bonus", -1),
Amount: func(atk *combat.AttackEvent, t combat.Target) ([]float64, bool) {
if atk.Info.Abil != "Shining Shadowhunt Shell" {
return nil, false
}
return mDmg, true
},
})
return a1Boost
}
func (c *char) a4() {
if c.Base.Ascension < 4 {
return
}
c.Core.Events.Subscribe(event.OnNightsoulBurst, func(args ...interface{}) bool {
element := attributes.Anemo
for _, char := range c.Core.Player.Chars() {
switch char.Base.Element {
case attributes.Pyro, attributes.Hydro, attributes.Cryo, attributes.Electro:
element = char.Base.Element
}
}
if element == attributes.Anemo {
c.a4Dmg = 1.5 * skillShadowhunt[c.TalentLvlSkill()]
} else {
c.a4Dmg = 1.5 * skillShiningShadowhunt[c.TalentLvlSkill()]
}
ai := combat.AttackInfo{
ActorIndex: c.Index,
Abil: "Burning Shadowhunt Shot",
AttackTag: attacks.AttackTagExtra,
ICDTag: attacks.ICDTagNone,
ICDGroup: attacks.ICDGroupDefault,
StrikeType: attacks.StrikeTypeDefault,
Element: element,
Durability: 25,
Mult: c.a4Dmg,
}
target := c.Core.Combat.ClosestEnemyWithinArea(combat.NewCircleHitOnTarget(c.Core.Combat.Player(), nil, 15), nil)
if target != nil {
ap := combat.NewCircleHitOnTarget(target, nil, 1)
c.Core.QueueAttack(ai, ap, 0, 1)
}
return false
}, "chasca-a4")
}
Loading

0 comments on commit 188d3f2

Please sign in to comment.