Compare commits
3 Commits
c9a7e15f89
...
d6fb4b6caf
| Author | SHA1 | Date | |
|---|---|---|---|
| d6fb4b6caf | |||
| 5b5e008b5e | |||
| 079b996f5a |
1812
doc/2026-01-15-global.diff
Normal file
1812
doc/2026-01-15-global.diff
Normal file
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,7 @@ This file is my notes from exploring the database.
|
|||||||
- 47 is skill names, 48 is skill descriptions
|
- 47 is skill names, 48 is skill descriptions
|
||||||
- 75 is support card names incl. variant, 76 is support card variant, 77 is support card character
|
- 75 is support card names incl. variant, 76 is support card variant, 77 is support card character
|
||||||
- 147 is spark names, 172 is spark descriptions
|
- 147 is spark names, 172 is spark descriptions
|
||||||
- 33 is race names
|
- 33 is race names by race id, 28 is race names by race instance id, 31 is race courses
|
||||||
- 65 is player titles, 66 is title descriptions - ties with honor_data?
|
- 65 is player titles, 66 is title descriptions - ties with honor_data?
|
||||||
|
|
||||||
# succession factor (sparks)
|
# succession factor (sparks)
|
||||||
@@ -189,7 +189,8 @@ seems to be activate_lot = 1 means wit check, 0 means guaranteed
|
|||||||
|
|
||||||
- group 1, grade: g1 100, g2 200, g3 300, op 400, pre-op 700
|
- group 1, grade: g1 100, g2 200, g3 300, op 400, pre-op 700
|
||||||
- group 61 is ....?? don't match anything
|
- group 61 is ....?? don't match anything
|
||||||
- takarazuka kinen, kikuka sho, and tenno sho spring are defined twice???
|
- several races are defined twice for "weird" races that appear in certain careers (maruzensky's 5 opponent spring stakes, mcqueen/ryan/rice's kyoto takarazuka kinen, &c.); these **do not** count as the same race as the normal versions for shared saddle bonus
|
||||||
|
|
||||||
single_mode_wins_saddle defines titles (classic triple crown, tenno sweep, &c.) using win_saddle_type = 0
|
single_mode_wins_saddle defines titles (classic triple crown, tenno sweep, &c.) using win_saddle_type = 0
|
||||||
|
|
||||||
# trainee definitions
|
# trainee definitions
|
||||||
@@ -198,7 +199,7 @@ single_mode_wins_saddle defines titles (classic triple crown, tenno sweep, &c.)
|
|||||||
- card_rarity_data has per-star-level stats: initial numbers, stat caps (!!), aptitudes (!!)
|
- card_rarity_data has per-star-level stats: initial numbers, stat caps (!!), aptitudes (!!)
|
||||||
- card_talent_upgrade has costs to increase potential level, but it doesn't seem to have skill sets
|
- card_talent_upgrade has costs to increase potential level, but it doesn't seem to have skill sets
|
||||||
- card_talent_hint_upgrade has costs to raise hint levels, but it's actually universal, only six rows
|
- card_talent_hint_upgrade has costs to raise hint levels, but it's actually universal, only six rows
|
||||||
|
- single_mode_route_race is career goals (not only races)
|
||||||
|
|
||||||
# unrelated to everything
|
# unrelated to everything
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package horse
|
package global
|
||||||
|
|
||||||
// Automatically generated with horsegen; DO NOT EDIT
|
// Automatically generated with horsegen; DO NOT EDIT
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,22 @@
|
|||||||
package horse
|
package horse
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
type SkillID int32
|
type SkillID int32
|
||||||
|
|
||||||
|
type TenThousandths int32
|
||||||
|
|
||||||
|
func (x TenThousandths) String() string {
|
||||||
|
b := make([]byte, 0, 12)
|
||||||
|
b = strconv.AppendInt(b, int64(x/1e4), 10)
|
||||||
|
b = append(b, '.')
|
||||||
|
if x < 0 {
|
||||||
|
x = -x
|
||||||
|
}
|
||||||
|
b = strconv.AppendInt(b, int64(x%1e4), 10)
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
// Skill is the internal data about a skill.
|
// Skill is the internal data about a skill.
|
||||||
type Skill struct {
|
type Skill struct {
|
||||||
ID SkillID
|
ID SkillID
|
||||||
@@ -21,8 +36,8 @@ type Skill struct {
|
|||||||
type Activation struct {
|
type Activation struct {
|
||||||
Precondition string
|
Precondition string
|
||||||
Condition string
|
Condition string
|
||||||
Duration int // 1e4 scale
|
Duration TenThousandths
|
||||||
Cooldown int // 1e4 scale
|
Cooldown TenThousandths
|
||||||
Abilities []Ability
|
Abilities []Ability
|
||||||
}
|
}
|
||||||
|
|
||||||
36
go/skill_test.go
Normal file
36
go/skill_test.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package horse_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cmp"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
horse "git.sunturtle.xyz/zephyr/horse/go"
|
||||||
|
"git.sunturtle.xyz/zephyr/horse/go/global"
|
||||||
|
)
|
||||||
|
|
||||||
|
var SortedSkills = sync.OnceValue(func() []horse.Skill {
|
||||||
|
skills := make([]horse.Skill, 0, len(global.AllSkills))
|
||||||
|
for _, v := range global.AllSkills {
|
||||||
|
skills = append(skills, v)
|
||||||
|
}
|
||||||
|
slices.SortFunc(skills, func(a, b horse.Skill) int { return cmp.Compare(a.ID, b.ID) })
|
||||||
|
return skills
|
||||||
|
})
|
||||||
|
|
||||||
|
func TestSkillStrings(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
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 _, abil := range a.Abilities {
|
||||||
|
if n := abil.Type.String(); strings.HasPrefix(n, "AbilityType(") {
|
||||||
|
t.Errorf("%v %s: %s", s.ID, s.Name, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
module horse/character
|
module horse/global/character
|
||||||
|
|
||||||
// Automatically generated with the horsegen tool; DO NOT EDIT
|
// Automatically generated with horsegen; DO NOT EDIT
|
||||||
|
|
||||||
import std/core/vector
|
import std/core/vector
|
||||||
import std/core-extras
|
import std/core-extras
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
module horse/skill-group
|
module horse/global/skill-group
|
||||||
|
|
||||||
// Automatically generated with horsegen; DO NOT EDIT
|
// Automatically generated with horsegen; DO NOT EDIT
|
||||||
|
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
module horse/skill
|
module horse/global/skill
|
||||||
|
|
||||||
|
// Automatically generated with horsegen; DO NOT EDIT
|
||||||
|
|
||||||
import std/num/decimal
|
import std/num/decimal
|
||||||
pub import horse/skill-group
|
pub import horse/skill-group
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{{ define "go-character" -}}
|
{{ define "go-character" -}}
|
||||||
package horse
|
package {{ $.Region }}
|
||||||
|
|
||||||
// Automatically generated with horsegen; DO NOT EDIT
|
// Automatically generated with horsegen; DO NOT EDIT
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{{ define "koka-character" -}}
|
{{ define "koka-character" -}}
|
||||||
module horse/character
|
module horse/{{ $.Region }}/character
|
||||||
|
|
||||||
// Automatically generated with the horsegen tool; DO NOT EDIT
|
// Automatically generated with horsegen; DO NOT EDIT
|
||||||
|
|
||||||
import std/core/vector
|
import std/core/vector
|
||||||
import std/core-extras
|
import std/core-extras
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ func LoadTemplates() (*template.Template, error) {
|
|||||||
|
|
||||||
// ExecCharacter renders the Koka character module to kk and the Go character file to g.
|
// ExecCharacter renders the Koka character module to kk and the Go character file to g.
|
||||||
// If either is nil, it is skipped.
|
// If either is nil, it is skipped.
|
||||||
func ExecCharacter(t *template.Template, kk, g io.Writer, c []NamedID[Character], pairs, trios []AffinityRelation) error {
|
func ExecCharacter(t *template.Template, region string, kk, g io.Writer, c []NamedID[Character], pairs, trios []AffinityRelation) error {
|
||||||
if len(pairs) != len(c)*len(c) {
|
if len(pairs) != len(c)*len(c) {
|
||||||
return fmt.Errorf("there are %d pairs but there must be %d for %d characters", len(pairs), len(c)*len(c), len(c))
|
return fmt.Errorf("there are %d pairs but there must be %d for %d characters", len(pairs), len(c)*len(c), len(c))
|
||||||
}
|
}
|
||||||
@@ -53,6 +53,7 @@ func ExecCharacter(t *template.Template, kk, g io.Writer, c []NamedID[Character]
|
|||||||
}
|
}
|
||||||
|
|
||||||
data := struct {
|
data := struct {
|
||||||
|
Region string
|
||||||
Characters []NamedID[Character]
|
Characters []NamedID[Character]
|
||||||
Pairs []AffinityRelation
|
Pairs []AffinityRelation
|
||||||
Trios []AffinityRelation
|
Trios []AffinityRelation
|
||||||
@@ -60,7 +61,7 @@ func ExecCharacter(t *template.Template, kk, g io.Writer, c []NamedID[Character]
|
|||||||
TrioMaps map[int]map[int]map[int]int
|
TrioMaps map[int]map[int]map[int]int
|
||||||
Count int
|
Count int
|
||||||
MaxID int
|
MaxID int
|
||||||
}{c, pairs, trios, pm, tm, len(c), maxid}
|
}{region, c, pairs, trios, pm, tm, len(c), maxid}
|
||||||
var err error
|
var err error
|
||||||
if kk != nil {
|
if kk != nil {
|
||||||
err = errors.Join(t.ExecuteTemplate(kk, "koka-character", &data))
|
err = errors.Join(t.ExecuteTemplate(kk, "koka-character", &data))
|
||||||
@@ -71,7 +72,7 @@ func ExecCharacter(t *template.Template, kk, g io.Writer, c []NamedID[Character]
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExecSkill(t *template.Template, kk, g io.Writer, groups []NamedID[SkillGroup], skills []Skill) error {
|
func ExecSkill(t *template.Template, region string, kk, g io.Writer, groups []NamedID[SkillGroup], skills []Skill) error {
|
||||||
m := make(map[int][]Skill, len(groups))
|
m := make(map[int][]Skill, len(groups))
|
||||||
u := make(map[int]int, len(groups))
|
u := make(map[int]int, len(groups))
|
||||||
for _, t := range skills {
|
for _, t := range skills {
|
||||||
@@ -88,10 +89,11 @@ func ExecSkill(t *template.Template, kk, g io.Writer, groups []NamedID[SkillGrou
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
data := struct {
|
data := struct {
|
||||||
|
Region string
|
||||||
Groups []NamedID[SkillGroup]
|
Groups []NamedID[SkillGroup]
|
||||||
Skills []Skill
|
Skills []Skill
|
||||||
Related map[int][]Skill
|
Related map[int][]Skill
|
||||||
}{groups, skills, m}
|
}{region, groups, skills, m}
|
||||||
var err error
|
var err error
|
||||||
if kk != nil {
|
if kk != nil {
|
||||||
err = errors.Join(t.ExecuteTemplate(kk, "koka-skill", &data))
|
err = errors.Join(t.ExecuteTemplate(kk, "koka-skill", &data))
|
||||||
@@ -102,11 +104,12 @@ func ExecSkill(t *template.Template, kk, g io.Writer, groups []NamedID[SkillGrou
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExecSkillGroupKK(t *template.Template, w io.Writer, g []NamedID[SkillGroup], s []Skill) error {
|
func ExecSkillGroupKK(t *template.Template, region string, w io.Writer, g []NamedID[SkillGroup], s []Skill) error {
|
||||||
data := struct {
|
data := struct {
|
||||||
|
Region string
|
||||||
Groups []NamedID[SkillGroup]
|
Groups []NamedID[SkillGroup]
|
||||||
Skills []Skill
|
Skills []Skill
|
||||||
}{g, s}
|
}{region, g, s}
|
||||||
return t.ExecuteTemplate(w, "koka-skill-group", &data)
|
return t.ExecuteTemplate(w, "koka-skill-group", &data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,12 +15,13 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var (
|
var (
|
||||||
mdb string
|
mdb string
|
||||||
kkOut, goOut string
|
out string
|
||||||
|
region string
|
||||||
)
|
)
|
||||||
flag.StringVar(&mdb, "mdb", os.ExpandEnv(`$USERPROFILE\AppData\LocalLow\Cygames\Umamusume\master\master.mdb`), "`path` to Umamusume master.mdb")
|
flag.StringVar(&mdb, "mdb", os.ExpandEnv(`$USERPROFILE\AppData\LocalLow\Cygames\Umamusume\master\master.mdb`), "`path` to Umamusume master.mdb")
|
||||||
flag.StringVar(&kkOut, "kk", `.\horse`, "existing `dir`ectory for output Koka files")
|
flag.StringVar(&out, "o", `.`, "root `dir`ectory for output files")
|
||||||
flag.StringVar(&goOut, "go", `.`, "existing `dir`ectory for output Go files")
|
flag.StringVar(®ion, "region", "global", "region the database is for (global, jp)")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
pctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
|
pctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
|
||||||
@@ -85,35 +86,44 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := os.MkdirAll(filepath.Join(out, "horse", region), 0775); err != nil {
|
||||||
|
slog.Error("create koka output dir", slog.Any("err", err))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll(filepath.Join(out, "go", region), 0775); err != nil {
|
||||||
|
slog.Error("create go output dir", slog.Any("err", err))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
eg, ctx = errgroup.WithContext(pctx)
|
eg, ctx = errgroup.WithContext(pctx)
|
||||||
eg.Go(func() error {
|
eg.Go(func() error {
|
||||||
cf, err := os.Create(filepath.Join(kkOut, "character.kk"))
|
cf, err := os.Create(filepath.Join(out, "horse", region, "character.kk"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
gf, err := os.Create(filepath.Join(goOut, "character.go"))
|
gf, err := os.Create(filepath.Join(out, "go", region, "character.go"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
slog.Info("write characters")
|
slog.Info("write characters")
|
||||||
return ExecCharacter(t, cf, gf, charas, pairs, trios)
|
return ExecCharacter(t, region, cf, gf, charas, pairs, trios)
|
||||||
})
|
})
|
||||||
eg.Go(func() error {
|
eg.Go(func() error {
|
||||||
sf, err := os.Create(filepath.Join(kkOut, "skill.kk"))
|
sf, err := os.Create(filepath.Join(out, "horse", region, "skill.kk"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
gf, err := os.Create(filepath.Join(goOut, "skill_data.go"))
|
gf, err := os.Create(filepath.Join(out, "go", region, "skill.go"))
|
||||||
slog.Info("write skills")
|
slog.Info("write skills")
|
||||||
return ExecSkill(t, sf, gf, sg, skills)
|
return ExecSkill(t, region, sf, gf, sg, skills)
|
||||||
})
|
})
|
||||||
eg.Go(func() error {
|
eg.Go(func() error {
|
||||||
sf, err := os.Create(filepath.Join(kkOut, "skill-group.kk"))
|
sf, err := os.Create(filepath.Join(out, "horse", region, "skill-group.kk"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
slog.Info("write skill groups")
|
slog.Info("write skill groups")
|
||||||
return ExecSkillGroupKK(t, sf, sg, skills)
|
return ExecSkillGroupKK(t, region, sf, sg, skills)
|
||||||
})
|
})
|
||||||
if err := eg.Wait(); err != nil {
|
if err := eg.Wait(); err != nil {
|
||||||
slog.Error("generate", slog.Any("err", err))
|
slog.Error("generate", slog.Any("err", err))
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
{{- define "go-skill-data" -}}
|
{{- define "go-skill-data" -}}
|
||||||
package horse
|
package {{ $.Region }}
|
||||||
|
|
||||||
// Automatically generated with horsegen; DO NOT EDIT
|
// Automatically generated with horsegen; DO NOT EDIT
|
||||||
|
|
||||||
|
import . "git.sunturtle.xyz/zephyr/horse/go"
|
||||||
|
|
||||||
|
{{/*
|
||||||
//go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type SkillID -trimprefix Skill -linecomment
|
//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 }}
|
||||||
@@ -32,29 +36,7 @@ var AllSkills = map[SkillID]Skill{
|
|||||||
[]Ability{
|
[]Ability{
|
||||||
{{- range $abil := $a.Abilities }}
|
{{- range $abil := $a.Abilities }}
|
||||||
{{- if ne $abil.Type 0 }}
|
{{- if ne $abil.Type 0 }}
|
||||||
{
|
{ {{- $abil.Type }}, {{ $abil.ValueUsage }}, {{ $abil.Value }}, {{ $abil.Target }}, {{ $abil.TargetValue -}} },
|
||||||
{{ if eq $abil.Type 1 -}}AbilityPassiveSpeed,
|
|
||||||
{{ else if eq $abil.Type 2 -}}AbilityPassiveStamina,
|
|
||||||
{{ else if eq $abil.Type 3 -}}AbilityPassivePower,
|
|
||||||
{{ else if eq $abil.Type 4 -}}AbilityPassiveGuts,
|
|
||||||
{{ else if eq $abil.Type 5 -}}AbilityPassiveWit,
|
|
||||||
{{ else if eq $abil.Type 6 -}}AbilityGreatEscape,
|
|
||||||
{{ else if eq $abil.Type 8 -}}AbilityVision,
|
|
||||||
{{ else if eq $abil.Type 9 -}}AbilityHP,
|
|
||||||
{{ else if eq $abil.Type 10 -}}AbilityGateDelay,
|
|
||||||
{{ else if eq $abil.Type 13 -}}AbilityFrenzy,
|
|
||||||
{{ else if eq $abil.Type 21 -}}AbilityCurrentSpeed,
|
|
||||||
{{ else if eq $abil.Type 27 -}}AbilityTargetSpeed,
|
|
||||||
{{ else if eq $abil.Type 28 -}}AbilityLaneSpeed,
|
|
||||||
{{ else if eq $abil.Type 31 -}}AbilityAccel,
|
|
||||||
{{ else if eq $abil.Type 35 -}}AbilityLaneChange,
|
|
||||||
{{ else }}??? $abil.Type={{$abil.Type}}
|
|
||||||
{{ end -}}
|
|
||||||
{{ $abil.ValueUsage }},
|
|
||||||
{{ $abil.Value }},
|
|
||||||
{{ $abil.Target }},
|
|
||||||
{{ $abil.TargetValue }},
|
|
||||||
},
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
},
|
},
|
||||||
@@ -67,4 +49,10 @@ var AllSkills = map[SkillID]Skill{
|
|||||||
},
|
},
|
||||||
{{- end }}
|
{{- end }}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var SkillNameToID = map[string]SkillID{
|
||||||
|
{{- range $s := $.Skills }}
|
||||||
|
{{ printf "%q" $s.Name }}{{ if ne $s.InheritID 0 }} + " (Inherited)"{{ end }}: {{ $s.ID }},
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{{- define "koka-skill-group" -}}
|
{{- define "koka-skill-group" -}}
|
||||||
module horse/skill-group
|
module horse/{{ $.Region }}/skill-group
|
||||||
|
|
||||||
// Automatically generated with horsegen; DO NOT EDIT
|
// Automatically generated with horsegen; DO NOT EDIT
|
||||||
|
|
||||||
@@ -48,7 +48,9 @@ pub fun skill-group/(==)(a: skill-group, b: skill-group): bool
|
|||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
{{- define "koka-skill" -}}
|
{{- define "koka-skill" -}}
|
||||||
module horse/skill
|
module horse/{{ $.Region }}/skill
|
||||||
|
|
||||||
|
// Automatically generated with horsegen; DO NOT EDIT
|
||||||
|
|
||||||
import std/num/decimal
|
import std/num/decimal
|
||||||
pub import horse/skill-group
|
pub import horse/skill-group
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user