|
| 1 | +package escoffier |
| 2 | + |
| 3 | +import ( |
| 4 | + "fmt" |
| 5 | + |
| 6 | + "github.com/genshinsim/gcsim/internal/frames" |
| 7 | + "github.com/genshinsim/gcsim/pkg/core/action" |
| 8 | + "github.com/genshinsim/gcsim/pkg/core/attacks" |
| 9 | + "github.com/genshinsim/gcsim/pkg/core/attributes" |
| 10 | + "github.com/genshinsim/gcsim/pkg/core/combat" |
| 11 | + "github.com/genshinsim/gcsim/pkg/core/geometry" |
| 12 | +) |
| 13 | + |
| 14 | +var ( |
| 15 | + attackFrames [][]int |
| 16 | + attackHitmarks = [][]int{{7}, {16}, {27, 40}} |
| 17 | + attackHitlagHaltFrame = [][]float64{{0.06}, {0.06}, {0.06, 0.06}} |
| 18 | + attackDefHalt = [][]bool{{true}, {true}, {true, true}} |
| 19 | + attackHitboxes = [][][]float64{{{1.6, 2}}, {{2}}, {{2.5}, {2.5}}} |
| 20 | + attackOffsets = [][]float64{{1}, {-0.2}, {-0.2, -0.2}} |
| 21 | +) |
| 22 | + |
| 23 | +const normalHitNum = 3 |
| 24 | + |
| 25 | +func init() { |
| 26 | + attackFrames = make([][]int, normalHitNum) |
| 27 | + |
| 28 | + attackFrames[0] = frames.InitNormalCancelSlice(attackHitmarks[0][0], 17) |
| 29 | + attackFrames[0][action.ActionCharge] = 20 |
| 30 | + attackFrames[0][action.ActionWalk] = 22 |
| 31 | + |
| 32 | + attackFrames[1] = frames.InitNormalCancelSlice(attackHitmarks[1][0], 21) |
| 33 | + attackFrames[1][action.ActionAttack] = 29 |
| 34 | + attackFrames[1][action.ActionWalk] = 30 |
| 35 | + |
| 36 | + attackFrames[2] = frames.InitNormalCancelSlice(attackHitmarks[2][1], 62) |
| 37 | + attackFrames[2][action.ActionWalk] = 61 |
| 38 | + attackFrames[2][action.ActionCharge] = 500 //TODO: this action is illegal; need better way to handle it |
| 39 | +} |
| 40 | + |
| 41 | +// Normal attack damage queue generator |
| 42 | +// relatively standard with no major differences versus other characters |
| 43 | +func (c *char) Attack(p map[string]int) (action.Info, error) { |
| 44 | + for i, mult := range attack[c.NormalCounter] { |
| 45 | + ai := combat.AttackInfo{ |
| 46 | + ActorIndex: c.Index, |
| 47 | + Abil: fmt.Sprintf("Normal %v", c.NormalCounter), |
| 48 | + AttackTag: attacks.AttackTagNormal, |
| 49 | + ICDTag: attacks.ICDTagNormalAttack, |
| 50 | + ICDGroup: attacks.ICDGroupDefault, |
| 51 | + StrikeType: attacks.StrikeTypeSlash, |
| 52 | + Element: attributes.Physical, |
| 53 | + Durability: 25, |
| 54 | + Mult: mult[c.TalentLvlAttack()], |
| 55 | + HitlagFactor: 0.01, |
| 56 | + HitlagHaltFrames: attackHitlagHaltFrame[c.NormalCounter][i] * 60, |
| 57 | + CanBeDefenseHalted: attackDefHalt[c.NormalCounter][i], |
| 58 | + } |
| 59 | + |
| 60 | + ap := combat.NewCircleHitOnTarget( |
| 61 | + c.Core.Combat.Player(), |
| 62 | + geometry.Point{Y: attackOffsets[c.NormalCounter][i]}, |
| 63 | + attackHitboxes[c.NormalCounter][i][0], |
| 64 | + ) |
| 65 | + if c.NormalCounter == 0 { |
| 66 | + ai.StrikeType = attacks.StrikeTypeSpear |
| 67 | + ap = combat.NewBoxHitOnTarget( |
| 68 | + c.Core.Combat.Player(), |
| 69 | + geometry.Point{Y: attackOffsets[c.NormalCounter][i]}, |
| 70 | + attackHitboxes[c.NormalCounter][i][0], |
| 71 | + attackHitboxes[c.NormalCounter][i][1], |
| 72 | + ) |
| 73 | + } |
| 74 | + c.QueueCharTask(func() { |
| 75 | + c.Core.QueueAttack(ai, ap, 0, 0) |
| 76 | + }, attackHitmarks[c.NormalCounter][i]) |
| 77 | + } |
| 78 | + |
| 79 | + defer c.AdvanceNormalIndex() |
| 80 | + |
| 81 | + return action.Info{ |
| 82 | + Frames: frames.NewAttackFunc(c.Character, attackFrames), |
| 83 | + AnimationLength: attackFrames[c.NormalCounter][action.InvalidAction], |
| 84 | + CanQueueAfter: attackHitmarks[c.NormalCounter][len(attackHitmarks[c.NormalCounter])-1], |
| 85 | + State: action.NormalAttackState, |
| 86 | + }, nil |
| 87 | +} |
0 commit comments