231 lines
8.6 KiB
Go
231 lines
8.6 KiB
Go
package horse
|
||
|
||
import (
|
||
"bytes"
|
||
"fmt"
|
||
"strconv"
|
||
)
|
||
|
||
type SkillID int32
|
||
|
||
type TenThousandths int32
|
||
|
||
func (x TenThousandths) String() string {
|
||
b := make([]byte, 0, 12)
|
||
if x < 0 {
|
||
x = -x
|
||
b = append(b, '-')
|
||
}
|
||
b = strconv.AppendInt(b, int64(x/1e4), 10)
|
||
if x%1e4 != 0 {
|
||
b = append(b, '.')
|
||
b = fmt.Appendf(b, "%04d", x%1e4)
|
||
b = bytes.TrimRight(b, "0")
|
||
}
|
||
return string(b)
|
||
}
|
||
|
||
// Skill is the internal data about a skill.
|
||
type Skill struct {
|
||
ID SkillID `json:"skill_id"`
|
||
Name string `json:"name"`
|
||
Description string `json:"description"`
|
||
Group SkillGroupID `json:"group"`
|
||
Rarity int8 `json:"rarity"`
|
||
GroupRate int8 `json:"group_rate"`
|
||
GradeValue int32 `json:"grade_value,omitzero"`
|
||
WitCheck bool `json:"wit_check"`
|
||
Activations []Activation `json:"activations"`
|
||
UniqueOwner string `json:"unique_owner,omitzero"`
|
||
SPCost int `json:"sp_cost,omitzero"`
|
||
IconID int `json:"icon_id"`
|
||
}
|
||
|
||
// Activation is the parameters controlling when a skill activates.
|
||
type Activation struct {
|
||
Precondition string `json:"precondition,omitzero"`
|
||
Condition string `json:"condition"`
|
||
Duration TenThousandths `json:"duration,omitzero"`
|
||
DurScale DurScale `json:"dur_scale"`
|
||
Cooldown TenThousandths `json:"cooldown,omitzero"`
|
||
Abilities []Ability `json:"abilities"`
|
||
}
|
||
|
||
// Ability is an individual effect applied by a skill.
|
||
type Ability struct {
|
||
Type AbilityType `json:"type"`
|
||
ValueUsage AbilityValueUsage `json:"value_usage"`
|
||
Value TenThousandths `json:"value"`
|
||
Target AbilityTarget `json:"target"`
|
||
TargetValue int32 `json:"target_value,omitzero"`
|
||
}
|
||
|
||
func (a Ability) String() string {
|
||
r := make([]byte, 0, 64)
|
||
r = append(r, a.Type.String()...)
|
||
if a.Value != 0 {
|
||
r = append(r, ' ')
|
||
if a.Value > 0 {
|
||
r = append(r, '+')
|
||
}
|
||
switch a.Type {
|
||
case AbilityPassiveSpeed, AbilityPassiveStamina, AbilityPassivePower, AbilityPassiveGuts, AbilityPassiveWit:
|
||
r = append(r, a.Value.String()...)
|
||
case AbilityVision:
|
||
r = append(r, a.Value.String()...)
|
||
r = append(r, 'm')
|
||
case AbilityHP:
|
||
r = append(r, (a.Value * 100).String()...)
|
||
r = append(r, '%')
|
||
case AbilityGateDelay:
|
||
r = append(r, a.Value.String()...)
|
||
r = append(r, "×"...)
|
||
case AbilityFrenzy:
|
||
r = append(r, a.Value.String()...)
|
||
r = append(r, 's')
|
||
case AbilityCurrentSpeed, AbilityTargetSpeed, AbilityLaneSpeed:
|
||
r = append(r, a.Value.String()...)
|
||
r = append(r, " m/s"...)
|
||
case AbilityAccel:
|
||
r = append(r, a.Value.String()...)
|
||
r = append(r, " m/s²"...)
|
||
case AbilityLaneChange:
|
||
r = append(r, a.Value.String()...)
|
||
r = append(r, " track widths"...)
|
||
}
|
||
}
|
||
switch a.Target {
|
||
case TargetSelf:
|
||
// do nothing
|
||
case TargetStyle, TargetRushingStyle:
|
||
// TargetValue is the style to target, not the number of targets.
|
||
r = append(r, " to "...)
|
||
r = append(r, a.Target.String()...)
|
||
switch a.TargetValue {
|
||
case 1:
|
||
r = append(r, " Front Runner"...)
|
||
case 2:
|
||
r = append(r, " Pace Chaser"...)
|
||
case 3:
|
||
r = append(r, " Late Surger"...)
|
||
case 4:
|
||
r = append(r, " End Closer"...)
|
||
}
|
||
default:
|
||
// For other targeting types, TargetValue is either irrelevant or limit.
|
||
r = append(r, " to "...)
|
||
if a.TargetValue > 1 && a.TargetValue < 18 {
|
||
r = strconv.AppendInt(r, int64(a.TargetValue), 10)
|
||
r = append(r, ' ')
|
||
}
|
||
r = append(r, a.Target.String()...)
|
||
}
|
||
if a.ValueUsage != ValueUsageDirect {
|
||
r = append(r, ' ')
|
||
r = append(r, a.ValueUsage.String()...)
|
||
}
|
||
return string(r)
|
||
}
|
||
|
||
type DurScale int8
|
||
|
||
//go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type DurScale -trimprefix Duration -linecomment
|
||
const (
|
||
DurationDirect DurScale = 1 // directly
|
||
DurationFrontDistance DurScale = 2 // scaling with distance from the front
|
||
DurationRemainingHP DurScale = 3 // scaling with remaining HP
|
||
DurationIncrementPass DurScale = 4 // increasing with each pass while active
|
||
DurationMidSideBlock DurScale = 5 // scaling with mid-race phase blocked side time
|
||
DurationRemainingHP2 DurScale = 7 // scaling with remaining HP
|
||
)
|
||
|
||
type AbilityType int8
|
||
|
||
//go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type AbilityType -trimprefix Ability -linecomment
|
||
const (
|
||
AbilityPassiveSpeed AbilityType = 1 // Speed
|
||
AbilityPassiveStamina AbilityType = 2 // Stamina
|
||
AbilityPassivePower AbilityType = 3 // Power
|
||
AbilityPassiveGuts AbilityType = 4 // Guts
|
||
AbilityPassiveWit AbilityType = 5 // Wit
|
||
AbilityGreatEscape AbilityType = 6 // Enable Great Escape
|
||
AbilityVision AbilityType = 8 // Vision
|
||
AbilityHP AbilityType = 9 // HP
|
||
AbilityGateDelay AbilityType = 10 // Gate delay multiplier
|
||
AbilityFrenzy AbilityType = 13 // Frenzy
|
||
AbilityCurrentSpeed AbilityType = 21 // Current speed
|
||
AbilityTargetSpeed AbilityType = 27 // Target speed
|
||
AbilityLaneSpeed AbilityType = 28 // Lane change speed
|
||
AbilityAccel AbilityType = 31 // Acceleration
|
||
AbilityLaneChange AbilityType = 35 // Forced lane change
|
||
)
|
||
|
||
type AbilityValueUsage int8
|
||
|
||
//go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type AbilityValueUsage -trimprefix ValueUsage -linecomment
|
||
const (
|
||
ValueUsageDirect AbilityValueUsage = 1 // directly
|
||
ValueUsageSkillCount AbilityValueUsage = 2 // scaling with the number of skills
|
||
ValueUsageTeamSpeed AbilityValueUsage = 3 // scaling with team Speed
|
||
ValueUsageTeamStamina AbilityValueUsage = 4 // scaling with team Stamina
|
||
ValueUsageTeamPower AbilityValueUsage = 5 // scaling with team Power
|
||
ValueUsageTeamGuts AbilityValueUsage = 6 // scaling with team Guts
|
||
ValueUsageTeamWit AbilityValueUsage = 7 // scaling with team Wit
|
||
ValueUsageRandom AbilityValueUsage = 8 // with a random 0× to 0.04× multiplier
|
||
ValueUsageRandom2 AbilityValueUsage = 9 // with a random 0× to 0.04× multiplier
|
||
ValueUsageClimax AbilityValueUsage = 10 // scaling with the number of races won in training
|
||
ValueUsageMaxStat AbilityValueUsage = 13 // scaling with the highest raw stat
|
||
ValueUsageGreenCount AbilityValueUsage = 14 // scaling with the number of Passive skills activated
|
||
ValueUsageDistAdd AbilityValueUsage = 19 // plus extra when far from the lead
|
||
ValueUsageMidSideBlock AbilityValueUsage = 20 // scaling with mid-race phase blocked side time
|
||
ValueUsageSpeed AbilityValueUsage = 22 // scaling with overall speed
|
||
ValueUsageSpeed2 AbilityValueUsage = 23 // scaling with overall speed
|
||
ValueUsageArcPotential AbilityValueUsage = 24 // scaling with L'Arc global potential
|
||
ValueUsageMaxLead AbilityValueUsage = 25 // scaling with the longest lead obtained in the first ⅔
|
||
)
|
||
|
||
type AbilityTarget int8
|
||
|
||
//go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type AbilityTarget -trimprefix Target -linecomment
|
||
const (
|
||
TargetSelf AbilityTarget = 1 // self
|
||
TargetSympathizers AbilityTarget = 2 // others with Sympathy
|
||
TargetInView AbilityTarget = 4 // others in view
|
||
TargetFrontmost AbilityTarget = 7 // frontmost
|
||
TargetAhead AbilityTarget = 9 // others ahead
|
||
TargetBehind AbilityTarget = 10 // others behind
|
||
TargetAllTeammates AbilityTarget = 11 // all teammates
|
||
TargetStyle AbilityTarget = 18 // using style
|
||
TargetRushingAhead AbilityTarget = 19 // rushing others ahead
|
||
TargetRushingBehind AbilityTarget = 20 // rushing others behind
|
||
TargetRushingStyle AbilityTarget = 21 // rushing using style
|
||
TargetCharacter AbilityTarget = 22 // specific character
|
||
TargetTriggering AbilityTarget = 23 // whosoever triggered this skill
|
||
)
|
||
|
||
type SkillGroupID int32
|
||
|
||
// SkillGroup is a group of skills which are alternate versions of each other.
|
||
//
|
||
// Any of the skill IDs in a group may be zero, indicating that there is no
|
||
// skill with the corresponding group rate.
|
||
// Some skill groups contain only Skill2 or SkillBad, while others may have all
|
||
// four skills.
|
||
//
|
||
// As a special case, horsegen lists both unique skills and their inherited
|
||
// versions in the skill groups for both.
|
||
type SkillGroup struct {
|
||
ID SkillGroupID `json:"skill_group"`
|
||
// Skill1 is the base version of the skill, either a common (white) skill
|
||
// or an Uma's own unique.
|
||
Skill1 SkillID `json:"skill1,omitzero"`
|
||
// Skill2 is the first upgraded version of the skill: a rare (gold)
|
||
// skill, a double circle skill, or an inherited unique skill.
|
||
Skill2 SkillID `json:"skill2,omitzero"`
|
||
// Skill3 is the highest upgraded version, a gold version of a skill with
|
||
// a double circle version.
|
||
Skill3 SkillID `json:"skill3,omitzero"`
|
||
// SkillBad is a negative (purple) skill.
|
||
SkillBad SkillID `json:"skill_bad,omitzero"`
|
||
}
|