Compare commits

...

5 Commits

10 changed files with 318 additions and 322 deletions

6
horse/README.md Normal file
View File

@@ -0,0 +1,6 @@
# horse
This directory contains manually written code and types on which the generated code depends.
The generated code is in ./global; other regions will follow the same convention once they are supported.
It is always safe to delete the entire directories and regenerate them.

View File

@@ -0,0 +1,58 @@
// Code generated by "stringer -type AbilityTarget -trimprefix Target -linecomment"; DO NOT EDIT.
package horse
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[TargetSelf-1]
_ = x[TargetSympathizers-2]
_ = x[TargetInView-4]
_ = x[TargetFrontmost-7]
_ = x[TargetAhead-9]
_ = x[TargetBehind-10]
_ = x[TargetAllTeammates-11]
_ = x[TargetStyle-18]
_ = x[TargetRushingAhead-19]
_ = x[TargetRushingBehind-20]
_ = x[TargetRushingStyle-21]
_ = x[TargetCharacter-22]
_ = x[TargetTriggering-23]
}
const (
_AbilityTarget_name_0 = "selfothers with Sympathy"
_AbilityTarget_name_1 = "others in view"
_AbilityTarget_name_2 = "frontmost"
_AbilityTarget_name_3 = "others aheadothers behindall teammates"
_AbilityTarget_name_4 = "using stylerushing others aheadrushing others behindrushing using stylespecific characterwhosoever triggered this skill"
)
var (
_AbilityTarget_index_0 = [...]uint8{0, 4, 24}
_AbilityTarget_index_3 = [...]uint8{0, 12, 25, 38}
_AbilityTarget_index_4 = [...]uint8{0, 11, 31, 52, 71, 89, 119}
)
func (i AbilityTarget) String() string {
switch {
case 1 <= i && i <= 2:
i -= 1
return _AbilityTarget_name_0[_AbilityTarget_index_0[i]:_AbilityTarget_index_0[i+1]]
case i == 4:
return _AbilityTarget_name_1
case i == 7:
return _AbilityTarget_name_2
case 9 <= i && i <= 11:
i -= 9
return _AbilityTarget_name_3[_AbilityTarget_index_3[i]:_AbilityTarget_index_3[i+1]]
case 18 <= i && i <= 23:
i -= 18
return _AbilityTarget_name_4[_AbilityTarget_index_4[i]:_AbilityTarget_index_4[i+1]]
default:
return "AbilityTarget(" + strconv.FormatInt(int64(i), 10) + ")"
}
}

View File

@@ -1,4 +1,4 @@
// Code generated by "stringer -type AbilityType -trimprefix Ability"; DO NOT EDIT. // Code generated by "stringer -type AbilityType -trimprefix Ability -linecomment"; DO NOT EDIT.
package horse package horse
@@ -26,19 +26,19 @@ func _() {
} }
const ( const (
_AbilityType_name_0 = "PassiveSpeedPassiveStaminaPassivePowerPassiveGutsPassiveWitGreatEscape" _AbilityType_name_0 = "SpeedStaminaPowerGutsWitGreat Escape"
_AbilityType_name_1 = "VisionHPGateDelay" _AbilityType_name_1 = "VisionHPGate delay multiplier"
_AbilityType_name_2 = "Frenzy" _AbilityType_name_2 = "Frenzy"
_AbilityType_name_3 = "CurrentSpeed" _AbilityType_name_3 = "Current speed"
_AbilityType_name_4 = "TargetSpeedLaneSpeed" _AbilityType_name_4 = "Target speedLane change speed"
_AbilityType_name_5 = "Accel" _AbilityType_name_5 = "Acceleration"
_AbilityType_name_6 = "LaneChange" _AbilityType_name_6 = "Forced lane change"
) )
var ( var (
_AbilityType_index_0 = [...]uint8{0, 12, 26, 38, 49, 59, 70} _AbilityType_index_0 = [...]uint8{0, 5, 12, 17, 21, 24, 36}
_AbilityType_index_1 = [...]uint8{0, 6, 8, 17} _AbilityType_index_1 = [...]uint8{0, 6, 8, 29}
_AbilityType_index_4 = [...]uint8{0, 11, 20} _AbilityType_index_4 = [...]uint8{0, 12, 29}
) )
func (i AbilityType) String() string { func (i AbilityType) String() string {

View File

@@ -0,0 +1,29 @@
// Code generated by "stringer -type AbilityValueUsage -trimprefix ValueUsage -linecomment"; DO NOT EDIT.
package horse
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[ValueUsageDirect-1]
_ = x[ValueUsageTeamSpeed-2]
_ = x[ValueUsageTeamStamina-3]
_ = x[ValueUsageTeamPower-4]
_ = x[ValueUsageTeamGuts-5]
_ = x[ValueUsageTeamWit-6]
}
const _AbilityValueUsage_name = "directlyscaling with team Speedscaling with team Staminascaling with team Powerscaling with team Gutsscaling with team Wit"
var _AbilityValueUsage_index = [...]uint8{0, 8, 31, 56, 79, 101, 122}
func (i AbilityValueUsage) String() string {
idx := int(i) - 1
if i < 1 || idx >= len(_AbilityValueUsage_index)-1 {
return "AbilityValueUsage(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _AbilityValueUsage_name[_AbilityValueUsage_index[idx]:_AbilityValueUsage_index[idx+1]]
}

12
horse/character.go Normal file
View File

@@ -0,0 +1,12 @@
package horse
type CharacterID int16
type Character struct {
ID CharacterID
Name string
}
func (c Character) String() string {
return c.Name
}

File diff suppressed because one or more lines are too long

View File

@@ -44,29 +44,82 @@ type Activation struct {
// Ability is an individual effect applied by a skill. // Ability is an individual effect applied by a skill.
type Ability struct { type Ability struct {
Type AbilityType Type AbilityType
ValueUsage int8 ValueUsage AbilityValueUsage
Value int32 Value TenThousandths
Target int8 Target AbilityTarget
TargetValue int32 TargetValue int32
} }
func (a Ability) String() string {
r := make([]byte, 0, 64)
r = append(r, a.Type.String()...)
if a.Value != 0 {
r = append(r, ' ')
r = append(r, a.Value.String()...)
}
if a.Target != TargetSelf {
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 AbilityType int8 type AbilityType int8
//go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type AbilityType -trimprefix Ability //go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type AbilityType -trimprefix Ability -linecomment
const ( const (
AbilityPassiveSpeed AbilityType = 1 AbilityPassiveSpeed AbilityType = 1 // Speed
AbilityPassiveStamina AbilityType = 2 AbilityPassiveStamina AbilityType = 2 // Stamina
AbilityPassivePower AbilityType = 3 AbilityPassivePower AbilityType = 3 // Power
AbilityPassiveGuts AbilityType = 4 AbilityPassiveGuts AbilityType = 4 // Guts
AbilityPassiveWit AbilityType = 5 AbilityPassiveWit AbilityType = 5 // Wit
AbilityGreatEscape AbilityType = 6 AbilityGreatEscape AbilityType = 6 // Great Escape
AbilityVision AbilityType = 8 AbilityVision AbilityType = 8 // Vision
AbilityHP AbilityType = 9 AbilityHP AbilityType = 9 // HP
AbilityGateDelay AbilityType = 10 AbilityGateDelay AbilityType = 10 // Gate delay multiplier
AbilityFrenzy AbilityType = 13 AbilityFrenzy AbilityType = 13 // Frenzy
AbilityCurrentSpeed AbilityType = 21 AbilityCurrentSpeed AbilityType = 21 // Current speed
AbilityTargetSpeed AbilityType = 27 AbilityTargetSpeed AbilityType = 27 // Target speed
AbilityLaneSpeed AbilityType = 28 AbilityLaneSpeed AbilityType = 28 // Lane change speed
AbilityAccel AbilityType = 31 AbilityAccel AbilityType = 31 // Acceleration
AbilityLaneChange AbilityType = 35 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
ValueUsageTeamSpeed AbilityValueUsage = 2 // scaling with team Speed
ValueUsageTeamStamina AbilityValueUsage = 3 // scaling with team Stamina
ValueUsageTeamPower AbilityValueUsage = 4 // scaling with team Power
ValueUsageTeamGuts AbilityValueUsage = 5 // scaling with team Guts
ValueUsageTeamWit AbilityValueUsage = 6 // scaling with team Wit
)
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
) )

View File

@@ -23,8 +23,6 @@ var SortedSkills = sync.OnceValue(func() []horse.Skill {
func TestSkillStrings(t *testing.T) { func TestSkillStrings(t *testing.T) {
t.Parallel() t.Parallel()
for _, s := range SortedSkills() { for _, s := range SortedSkills() {
// We could check that s.ID.String() matches s.Name,
// but that may be awkward for inherited skills.
for _, a := range s.Activations { for _, a := range s.Activations {
for _, abil := range a.Abilities { for _, abil := range a.Abilities {
if n := abil.Type.String(); strings.HasPrefix(n, "AbilityType(") { if n := abil.Type.String(); strings.HasPrefix(n, "AbilityType(") {

View File

@@ -3,99 +3,26 @@ package {{ $.Region }}
// Automatically generated with horsegen; DO NOT EDIT // Automatically generated with horsegen; DO NOT EDIT
import ( import . "git.sunturtle.xyz/zephyr/horse/horse"
"fmt"
"slices" const (
"strconv" {{- range $c := $.Characters }}
Character{{ goenum $c.Name }} = {{ $c.ID }} // {{ $c.Name }}
{{- end }}
) )
type Character struct { var Characters = map[CharacterID]Character{
ID int16
Name string
}
var characterIDs = []int16{
{{- range $c := $.Characters }} {{- range $c := $.Characters }}
{{ $c.ID }}, // {{ $c.Name }} Character{{ goenum $c.Name }}: { {{- $c.ID }}, {{ printf "%q" $c.Name -}} },
{{- end }} {{- end }}
} }
var characterNames = []string{ var CharacterNameToID = map[string]CharacterID{
{{- range $c := $.Characters }}
{{ printf "%q" $c.Name }},
{{- end }}
}
var characterNameToID = map[string]int16{
{{- range $c := $.Characters }} {{- range $c := $.Characters }}
{{ printf "%q" $c.Name }}: {{ $c.ID }}, {{ printf "%q" $c.Name }}: {{ $c.ID }},
{{- end }} {{- end }}
} }
func characterIndex(id int16) (int, bool) {
return slices.BinarySearch(characterIDs, id)
}
func CharacterForID(id int16) Character {
i, ok := characterIndex(id)
if !ok {
return Character{}
}
return Character{
ID: id,
Name: characterNames[i],
}
}
func CharacterForName(name string) Character {
id, ok := characterNameToID[name]
if !ok {
return Character{}
}
return Character{
ID: id,
Name: name,
}
}
func (c *Character) MarshalJSON() ([]byte, error) {
// Only marshal legal or empty characters.
if c.ID == 0 {
return []byte{'0'}, nil
}
i, ok := characterIndex(c.ID)
if !ok {
return nil, fmt.Errorf("marshaling character %q with invalid ID %d", c.Name, c.ID)
}
if characterNames[i] != c.Name {
return nil, fmt.Errorf("marshaling character with ID %d: name is %q but should be %q", c.ID, c.Name, characterNames[i])
}
return strconv.AppendInt(nil, int64(c.ID), 10), nil
}
func (c *Character) UnmarshalJSON(b []byte) error {
if string(b) == "null" {
return nil
}
id, err := strconv.ParseInt(string(b), 10, 16)
if err != nil {
return fmt.Errorf("unmarshaling invalid character ID %q: %w", b, err)
}
if id == 0 {
*c = Character{}
return nil
}
i, ok := characterIndex(int16(id))
if !ok {
return fmt.Errorf("unmarshaling unrecognized character ID %d", id)
}
*c = Character{
ID: int16(id),
Name: characterNames[i],
}
return nil
}
var pairAffinity = []int8{ var pairAffinity = []int8{
{{- range $a := $.Characters -}} {{- range $a := $.Characters -}}
{{- range $b := $.Characters -}} {{- range $b := $.Characters -}}
@@ -114,32 +41,26 @@ var trioAffinity = []int8{
{{- end -}} {{- end -}}
} }
func PairAffinity(a, b Character) int { func PairAffinity(a, b CharacterID) int {
i, ok := characterIndex(a.ID) if _, ok := Characters[a]; !ok {
if !ok {
return 0 return 0
} }
j, ok := characterIndex(b.ID) if _, ok := Characters[b]; !ok {
if !ok {
return 0 return 0
} }
return int(pairAffinity[i*{{ $.Count }} + j]) return int(pairAffinity[a*{{ $.Count }} + b])
} }
func TrioAffinity(a, b, c Character) int { func TrioAffinity(a, b, c CharacterID) int {
i, ok := characterIndex(a.ID) if _, ok := Characters[a]; !ok {
if !ok {
return 0 return 0
} }
j, ok := characterIndex(b.ID) if _, ok := Characters[b]; !ok {
if !ok {
return 0 return 0
} }
k, ok := characterIndex(c.ID) if _, ok := Characters[c]; !ok {
if !ok {
return 0 return 0
} }
return int(trioAffinity[i*{{ $.Count }}*{{ $.Count }} + j*{{ $.Count }} + k]) return int(trioAffinity[a*{{ $.Count }}*{{ $.Count }} + b*{{ $.Count }} + c])
} }
{{ end }} {{ end }}

View File

@@ -5,9 +5,6 @@ package {{ $.Region }}
import . "git.sunturtle.xyz/zephyr/horse/horse" import . "git.sunturtle.xyz/zephyr/horse/horse"
{{/*
//go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type SkillID -trimprefix Skill -linecomment
*/ -}}
const ( const (
{{- range $s := $.Skills }} {{- range $s := $.Skills }}
Skill{{ goenum $s.Name }}{{ if ne $s.InheritID 0 }}Inherit{{ end }} SkillID = {{ $s.ID }} // {{ $s.Name }} Skill{{ goenum $s.Name }}{{ if ne $s.InheritID 0 }}Inherit{{ end }} SkillID = {{ $s.ID }} // {{ $s.Name }}