horsegen: generate skills

This commit is contained in:
2026-01-10 02:30:38 -05:00
parent 5bcdd45b10
commit 05688a08e2
9 changed files with 3382 additions and 529 deletions

View File

@@ -1,7 +1,7 @@
{{ define "koka-skill" -}}
module horse/skill
{{- define "koka-skill-group" -}}
module horse/skill-group
// Automatically generated with the horsegen tool; DO NOT EDIT
// Automatically generated with horsegen; DO NOT EDIT
// Skill groups.
// A skill group may contain white, circle, double-circle, gold, and purple skills
@@ -27,7 +27,7 @@ pub fip(1) fun skill-group/from-id(^id: int): maybe<skill-group>
{{- end }}
_ -> Nothing
// Get names for skill groups.
// Get the name for a skill group.
// Skill group names are the name of the base skill in the group.
pub fun skill-group/show(sg: skill-group): string
match sg
@@ -45,4 +45,291 @@ pub fip fun skill-group/order2(a: skill-group, b: skill-group): order2<skill-gro
pub fun skill-group/(==)(a: skill-group, b: skill-group): bool
a.group-id == b.group-id
{{- end }}
{{- end -}}
{{- define "koka-skill" -}}
module horse/skill
import std/num/float64
pub import horse/skill-group
// Skills instances.
pub type skill
{{- range $s := $.Skills }}
{{ kkenum $s.Name }}
{{- end }}
// Map a skill to its ID.
pub fip fun skill/skill-id(^s: skill): int
match s
{{- range $s := $.Skills }}
{{ kkenum $s.Name }} -> {{ $s.ID }}
{{- end }}
// Get the skill for an ID.
pub fip(1) fun skill/from-id(^id: int): maybe<skill>
match id
{{- range $s := $.Skills }}
{{ $s.ID }} -> Just( {{- kkenum $s.Name -}} )
{{- end }}
_ -> Nothing
// Get the name of a skill.
pub fun skill/show(s: skill): string
match s
{{- range $s := $.Skills }}
{{ kkenum $s.Name }} -> {{ printf "%q" $s.Name }}
{{- end }}
// Compare two skills by ID order.
pub fip fun skill/order2(a: skill, b: skill): order2<skill>
match cmp(a.skill-id, b.skill-id)
Lt -> Lt2(a, b)
Eq -> Eq2(a)
Gt -> Gt2(a, b)
pub fun skill/(==)(a: skill, b: skill): bool
a.skill-id == b.skill-id
// Get complete skill info.
pub fun skill/detail(^s: skill): skill-detail
match s
{{- range $s := $.Skills }}
{{ kkenum $s.Name }} -> {{ template "kk-render-skill-detail" $s }}
{{- end }}
// Details about a skill.
pub struct skill-detail
skill-id: int
name: string
description: string
group: skill-group
rarity: rarity
group-rate: int
grade-value: int
wit-check: bool
activations: list<activation>
icon-id: int
// Automatically generated.
// Shows a string representation of the `skill-detail` type.
pub fun skill-detail/show(this : skill-detail) : e string
match this
Skill-detail(skill-id, name, description, group, rarity, group-rate, grade-value, wit-check, activations, icon-id) -> "Skill-detail(skill-id: " ++ skill-id.show ++ ", name: " ++ name.show ++ ", description: " ++ description.show ++ ", group: " ++ group.show ++ ", rarity: " ++ rarity.show ++ ", group-rate: " ++ group-rate.show ++ ", grade-value: " ++ grade-value.show ++ ", wit-check: " ++ wit-check.show ++ ", activations: " ++ activations.show ++ ", icon-id: " ++ icon-id.show ++ ")"
// Skill rarity.
pub type rarity
Common // white
Rare // gold
Unique-Low // 1*/2* unique
Unique-Upgraded // 3*+ unique on a trainee upgraded from 1*/2*
Unique // base 3* unique
pub fun rarity/show(r: rarity): string
match r
Common -> "Common"
Rare -> "Rare"
Unique-Low -> "Unique (1☆/2☆)"
Unique-Upgraded -> "Unique (3☆+ from 1☆/2☆ upgraded)"
Unique -> "Unique (3☆+)"
// Condition and precondition logic.
pub alias condition = string
// Activation conditions and effects.
// A skill has one or two activations.
pub struct activation
precondition: condition
condition: condition
duration: float64 // seconds
cooldown: float64 // seconds
abilities: list<ability> // one to three elements
pub fun activation/show(a: activation): string
match a
Activation("", condition, -1.0, _, abilities) -> condition ++ " -> " ++ abilities.show
Activation("", condition, duration, cooldown, abilities) | cooldown >= 500.0 -> condition ++ " -> " ++ abilities.show ++ " for " ++ duration.show ++ "s"
Activation("", condition, duration, cooldown, abilities) -> condition ++ " -> " ++ abilities.show ++ " for " ++ duration.show ++ "s on " ++ cooldown.show ++ "s cooldown"
Activation(precondition, condition, -1.0, _, abilities)-> precondition ++ " -> " ++ condition ++ " -> " ++ abilities.show
Activation(precondition, condition, duration, cooldown, abilities) | cooldown >= 500.0 -> precondition ++ " -> " ++ condition ++ " -> " ++ abilities.show ++ " for " ++ duration.show ++ "s"
Activation(precondition, condition, duration, cooldown, abilities) -> precondition ++ "-> " ++ condition ++ " -> " ++ abilities.show ++ " for " ++ duration.show ++ "s on " ++ cooldown.show ++ "s cooldown"
// Effects of activating a skill.
pub struct ability
ability-type: ability-type
value-usage: value-usage
target: target
pub fun ability/show(a: ability): string
match a
Ability(t, Direct, Self) -> t.show
Ability(t, Direct, target) -> t.show ++ " " ++ target.show
Ability(t, v, Self) -> t.show ++ " scaling by " ++ v.show
Ability(t, v, target) -> t.show ++ " " ++ target.show ++ " scaling by " ++ v.show
// Target of a skill activation effect.
pub type ability-type
Passive-Speed(bonus: float64)
Passive-Stamina(bonus: float64)
Passive-Power(bonus: float64)
Passive-Guts(bonus: float64)
Passive-Wit(bonus: float64)
Runaway
Vision(bonus: float64)
HP(rate: float64)
Gate-Delay(rate: float64)
Frenzy(add: float64)
Current-Speed(rate: float64)
Target-Speed(rate: float64)
Lane-Speed(rate: float64)
Accel(rate: float64)
Lane-Change(rate: float64)
pub fun ability-type/show(a: ability-type): string
match a
Passive-Speed(bonus) -> "passive " ++ bonus.show ++ " Speed"
Passive-Stamina(bonus) -> "passive " ++ bonus.show ++ " Stamina"
Passive-Power(bonus) -> "passive " ++ bonus.show ++ " Power"
Passive-Guts(bonus) -> "passive " ++ bonus.show ++ " Guts"
Passive-Wit(bonus) -> "passive " ++ bonus.show ++ " Wit"
Runaway -> "enable Great Escape style"
Vision(bonus) -> bonus.show ++ " vision"
HP(rate) | rate >= 0.0 -> show(rate * 100.0) ++ "% HP recovery"
HP(rate) -> show(rate * 100.0) ++ "% HP loss"
Gate-Delay(rate) -> rate.show ++ "× gate delay"
Frenzy(add) -> add.show ++ "s longer Rushed"
Current-Speed(rate) -> show(rate * 100.0) ++ "% current speed"
Target-Speed(rate) -> show(rate * 100.0) ++ "% target speed"
Lane-Speed(rate) -> show(rate * 100.0) ++ "% lane speed"
Accel(rate) -> show(rate * 100.0) ++ "% acceleration"
Lane-Change(rate) -> rate.show ++ " course width movement"
// Special scaling for skill activation effects.
pub type value-usage
Direct
Team-Speed
Team-Stamina
Team-Power
Team-Guts
Team-Wit
Multiply-Random
pub fun value-usage/show(v: value-usage): string
match v
Direct -> "no scaling"
Team-Speed -> "team's Speed"
Team-Stamina -> "team's Stamina"
Team-Power -> "team's Power"
Team-Guts -> "team's Guts"
Team-Wit -> "team's Wit"
Multiply-Random -> "random multiplier (0× to 0.04×)"
// Who a skill activation targets.
pub type target
Self
In-View
Ahead(limit: int)
Behind(limit: int)
Style(style: style)
Rushing-Ahead(limit: int)
Rushing-Behind(limit: int)
Rushing-Style(style: style)
pub fun target/show(t: target): string
match t
Self -> "self"
In-View -> "others in field of view"
Ahead(limit) | limit >= 18 -> "others ahead"
Ahead(limit) -> "next " ++ limit.show ++ " others ahead"
Behind(limit) | limit >= 18 -> "others behind"
Behind(limit) -> "next " ++ limit.show ++ " others behind"
Style(Front-Runner) -> "other Front Runners"
Style(Pace-Chaser) -> "other Pace Chasers"
Style(Late-Surger) -> "other Late Surgers"
Style(End-Closer) -> "other End Closers"
Rushing-Ahead(limit) | limit >= 18 -> "others rushing ahead"
Rushing-Ahead(limit) -> "next " ++ limit.show ++ " others rushing ahead"
Rushing-Behind(limit) | limit >= 18 -> "others rushing behind"
Rushing-Behind(limit) -> "next " ++ limit.show ++ " others rushing behind"
Rushing-Style(Front-Runner) -> "rushing Front Runners"
Rushing-Style(Pace-Chaser) -> "rushing Pace Chasers"
Rushing-Style(Late-Surger) -> "rushing Late Surgers"
Rushing-Style(End-Closer) -> "rushing End Closers"
// Running style for skill targets.
// TODO(zeph): there is definitely a better place for this to live
pub type style
Front-Runner
Pace-Chaser
Late-Surger
End-Closer
{{- end -}}
{{ define "kk-render-skill-detail" }}
{{- /* Call with Skill structure as argument. */ -}}
Skill-detail(skill-id = {{ $.ID -}}
, name = {{ printf "%q" $.Name -}}
, description = {{ printf "%q" $.Description -}}
, group = {{ kkenum $.GroupName -}}
, rarity = {{ if eq $.Rarity 1 }}Common{{ else if eq $.Rarity 2 }}Rare{{ else if eq $.Rarity 3 }}Unique-Low{{ else if eq $.Rarity 4 }}Unique-Upgraded{{ else if eq $.Rarity 5 }}Unique{{ else }}??? $.Rarity={{ $.Rarity }}{{ end -}}
, group-rate = {{ $.GroupRate -}}
, grade-value = {{ $.GradeValue -}}
, wit-check = {{ if $.WitCheck }}True{{ else }}False{{ end -}}
, activations = [
{{- range $a := $.Activations -}}
{{- if ne $a.Condition "" -}}
Activation(precondition = {{ printf "%q" $a.Precondition -}}
, condition = {{ printf "%q" $a.Condition -}}
, duration = {{ printf "%f" $a.Duration -}}
, cooldown = {{ printf "%f" $a.Cooldown -}}
, abilities = [
{{- range $abil := $a.Abilities -}}
{{- if ne $abil.Type 0 -}}
Ability(ability-type =
{{- if eq $abil.Type 1 -}}Passive-Speed({{ printf "%f" $abil.Value }})
{{- else if eq $abil.Type 2 -}}Passive-Stamina({{ printf "%f" $abil.Value }})
{{- else if eq $abil.Type 3 -}}Passive-Power({{ printf "%f" $abil.Value }})
{{- else if eq $abil.Type 4 -}}Passive-Guts({{ printf "%f" $abil.Value }})
{{- else if eq $abil.Type 5 -}}Passive-Wit({{ printf "%f" $abil.Value }})
{{- else if eq $abil.Type 6 -}}Runaway
{{- else if eq $abil.Type 8 -}}Vision({{ printf "%f" $abil.Value }})
{{- else if eq $abil.Type 9 -}}HP({{ printf "%f" $abil.Value }})
{{- else if eq $abil.Type 10 -}}Gate-Delay({{ printf "%f" $abil.Value }})
{{- else if eq $abil.Type 13 -}}Frenzy({{ printf "%f" $abil.Value }})
{{- else if eq $abil.Type 21 -}}Current-Speed({{ printf "%f" $abil.Value }})
{{- else if eq $abil.Type 27 -}}Target-Speed({{ printf "%f" $abil.Value }})
{{- else if eq $abil.Type 28 -}}Lane-Speed({{ printf "%f" $abil.Value }})
{{- else if eq $abil.Type 31 -}}Accel({{ printf "%f" $abil.Value }})
{{- else if eq $abil.Type 35 -}}Lane-Change({{ printf "%f" $abil.Value }})
{{- else -}}??? $abil.Type={{$abil.Type}}
{{- end -}}
, value-usage =
{{- if eq $abil.ValueUsage 1 -}}Direct
{{- else if eq $abil.ValueUsage 3 -}}Team-Speed
{{- else if eq $abil.ValueUsage 4 -}}Team-Stamina
{{- else if eq $abil.ValueUsage 5 -}}Team-Power
{{- else if eq $abil.ValueUsage 6 -}}Team-Guts
{{- else if eq $abil.ValueUsage 7 -}}Team-Wit
{{- else if eq $abil.ValueUsage 8 -}}Multiply-Random
{{- else -}}??? $abil.ValueUsage={{ $abil.ValueUsage }}
{{- end -}}
, target =
{{- if eq $abil.Target 1 -}}Self
{{- else if eq $abil.Target 4 -}}In-View
{{- else if eq $abil.Target 9 -}}Ahead({{ $abil.TargetValue }})
{{- else if eq $abil.Target 10 -}}Behind({{ $abil.TargetValue }})
{{- else if eq $abil.Target 18 -}}Style({{ if eq $abil.TargetValue 1 }}Front-Runner{{ else if eq $abil.TargetValue 2 }}Pace-Chaser{{ else if eq $abil.TargetValue 3 }}Late-Surger{{ else if eq $abil.TargetValue 4 }}End-Closer{{ else }}??? $abil.TargetValue={{ $abil.TargetValue }}{{ end }})
{{- else if eq $abil.Target 19 -}}Rushing-Ahead({{ $abil.TargetValue }})
{{- else if eq $abil.Target 20 -}}Rushing-Behind({{ $abil.TargetValue }})
{{- else if eq $abil.Target 21 -}}Rushing-Style({{ if eq $abil.TargetValue 1 }}Front-Runner{{ else if eq $abil.TargetValue 2 }}Pace-Chaser{{ else if eq $abil.TargetValue 3 }}Late-Surger{{ else if eq $abil.TargetValue 4 }}End-Closer{{ else }}??? $abil.TargetValue={{ $abil.TargetValue }}{{ end }})
{{- end -}}
),
{{- end -}}
{{- end -}}
]),
{{- end -}}
{{- end -}}
], icon-id = {{ $.IconID -}}
)
{{- end -}}