horse, horsegen: redesign approach for koka
This commit is contained in:
49
horse/game-id.kk
Normal file
49
horse/game-id.kk
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
module horse/game-id
|
||||||
|
|
||||||
|
// Game ID for characters, cards, skills, races, &c.
|
||||||
|
// Values for different categories may overlap.
|
||||||
|
alias game-id = int
|
||||||
|
|
||||||
|
// Specific game ID types.
|
||||||
|
// I've already made mistakes with ID categories and I haven't even committed this file yet.
|
||||||
|
|
||||||
|
// Game ID for characters.
|
||||||
|
// Generally numbers in the range 1000-9999.
|
||||||
|
pub struct character-id
|
||||||
|
game-id: game-id
|
||||||
|
|
||||||
|
// Game ID for trainees, i.e. costume instances of characters.
|
||||||
|
// Generally a character ID with two digits appended.
|
||||||
|
pub struct trainee-id
|
||||||
|
game-id: game-id
|
||||||
|
|
||||||
|
// Game ID for skills.
|
||||||
|
pub struct skill-id
|
||||||
|
game-id: game-id
|
||||||
|
|
||||||
|
// Game ID for skill groups.
|
||||||
|
pub struct skill-group-id
|
||||||
|
game-id: game-id
|
||||||
|
|
||||||
|
// Game ID for skill icons.
|
||||||
|
pub struct skill-icon-id
|
||||||
|
game-id: game-id
|
||||||
|
|
||||||
|
// order2 comparison between any game ID types.
|
||||||
|
pub inline fun order2(x: a, y: a, ?a/game-id: (a) -> game-id): order2<a>
|
||||||
|
match x.game-id.cmp(y.game-id)
|
||||||
|
Lt -> Lt2(x, y)
|
||||||
|
Eq -> Eq2(x)
|
||||||
|
Gt -> Gt2(x, y)
|
||||||
|
|
||||||
|
// Comparison between any game ID types.
|
||||||
|
pub inline fun cmp(x: a, y: a, ?a/game-id: (a) -> game-id): order
|
||||||
|
x.game-id.cmp(y.game-id)
|
||||||
|
|
||||||
|
// Equality between any game ID types.
|
||||||
|
pub inline fun (==)(x: a, y: a, ?a/game-id: (a) -> game-id): bool
|
||||||
|
x.game-id == y.game-id
|
||||||
|
|
||||||
|
// Check whether a game ID is valid, i.e. nonzero.
|
||||||
|
pub inline fun is-valid(x: a, ?a/game-id: (a) -> game-id): bool
|
||||||
|
x.game-id != 0
|
||||||
File diff suppressed because it is too large
Load Diff
16660
horse/global/skill.kk
16660
horse/global/skill.kk
File diff suppressed because it is too large
Load Diff
104
horse/movement.kk
Normal file
104
horse/movement.kk
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
module horse/movement
|
||||||
|
|
||||||
|
// Running styles.
|
||||||
|
pub type style
|
||||||
|
Front-Runner
|
||||||
|
Pace-Chaser
|
||||||
|
Late-Surger
|
||||||
|
End-Closer
|
||||||
|
|
||||||
|
// Automatically generated.
|
||||||
|
// Equality comparison of the `style` type.
|
||||||
|
pub fun style/(==)(this : style, other : style) : e bool
|
||||||
|
match (this, other)
|
||||||
|
(Front-Runner, Front-Runner) -> True
|
||||||
|
(Pace-Chaser, Pace-Chaser) -> True
|
||||||
|
(Late-Surger, Late-Surger) -> True
|
||||||
|
(End-Closer, End-Closer) -> True
|
||||||
|
(_, _) -> False
|
||||||
|
|
||||||
|
// Shows a string representation of the `style` type.
|
||||||
|
pub fun style/show(this : style) : e string
|
||||||
|
match this
|
||||||
|
Front-Runner -> "Front Runner"
|
||||||
|
Pace-Chaser -> "Pace Chaser"
|
||||||
|
Late-Surger -> "Late Surger"
|
||||||
|
End-Closer -> "End Closer"
|
||||||
|
|
||||||
|
// Starting aptitude levels.
|
||||||
|
pub type level
|
||||||
|
G
|
||||||
|
F
|
||||||
|
E
|
||||||
|
D
|
||||||
|
C
|
||||||
|
B
|
||||||
|
A
|
||||||
|
S
|
||||||
|
|
||||||
|
// Automatically generated.
|
||||||
|
// Comparison of the `level` type.
|
||||||
|
pub fun level/cmp(this : level, other : level) : e order
|
||||||
|
match (this, other)
|
||||||
|
(G, G) -> Eq
|
||||||
|
(G, _) -> Lt
|
||||||
|
(_, G) -> Gt
|
||||||
|
(F, F) -> Eq
|
||||||
|
(F, _) -> Lt
|
||||||
|
(_, F) -> Gt
|
||||||
|
(E, E) -> Eq
|
||||||
|
(E, _) -> Lt
|
||||||
|
(_, E) -> Gt
|
||||||
|
(D, D) -> Eq
|
||||||
|
(D, _) -> Lt
|
||||||
|
(_, D) -> Gt
|
||||||
|
(C, C) -> Eq
|
||||||
|
(C, _) -> Lt
|
||||||
|
(_, C) -> Gt
|
||||||
|
(B, B) -> Eq
|
||||||
|
(B, _) -> Lt
|
||||||
|
(_, B) -> Gt
|
||||||
|
(A, A) -> Eq
|
||||||
|
(A, _) -> Lt
|
||||||
|
(_, A) -> Gt
|
||||||
|
(S, S) -> Eq
|
||||||
|
|
||||||
|
// Automatically generated.
|
||||||
|
// Fip comparison of the `level` type.
|
||||||
|
pub fun level/order2(this : level, other : level) : order2<level>
|
||||||
|
match (this, other)
|
||||||
|
(G, G) -> Eq2(G)
|
||||||
|
(G, other') -> Lt2(G, other')
|
||||||
|
(this', G) -> Gt2(G, this')
|
||||||
|
(F, F) -> Eq2(F)
|
||||||
|
(F, other') -> Lt2(F, other')
|
||||||
|
(this', F) -> Gt2(F, this')
|
||||||
|
(E, E) -> Eq2(E)
|
||||||
|
(E, other') -> Lt2(E, other')
|
||||||
|
(this', E) -> Gt2(E, this')
|
||||||
|
(D, D) -> Eq2(D)
|
||||||
|
(D, other') -> Lt2(D, other')
|
||||||
|
(this', D) -> Gt2(D, this')
|
||||||
|
(C, C) -> Eq2(C)
|
||||||
|
(C, other') -> Lt2(C, other')
|
||||||
|
(this', C) -> Gt2(C, this')
|
||||||
|
(B, B) -> Eq2(B)
|
||||||
|
(B, other') -> Lt2(B, other')
|
||||||
|
(this', B) -> Gt2(B, this')
|
||||||
|
(A, A) -> Eq2(A)
|
||||||
|
(A, other') -> Lt2(A, other')
|
||||||
|
(this', A) -> Gt2(A, this')
|
||||||
|
(S, S) -> Eq2(S)
|
||||||
|
|
||||||
|
// Automatically generated.
|
||||||
|
// Shows a string representation of the `level` type.
|
||||||
|
pub fun level/show(this : level) : string
|
||||||
|
match this
|
||||||
|
G -> "G"
|
||||||
|
F -> "F"
|
||||||
|
E -> "E"
|
||||||
|
D -> "D"
|
||||||
|
C -> "C"
|
||||||
|
B -> "B"
|
||||||
|
A -> "A"
|
||||||
|
S -> "S"
|
||||||
226
horse/skill.kk
Normal file
226
horse/skill.kk
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
module horse/skill
|
||||||
|
|
||||||
|
// This module contains skill-related definitions
|
||||||
|
// common to all versions of the game.
|
||||||
|
|
||||||
|
import std/num/decimal
|
||||||
|
import horse/game-id
|
||||||
|
import horse/movement
|
||||||
|
|
||||||
|
// Full details about a skill.
|
||||||
|
pub struct skill-detail
|
||||||
|
skill-id: skill-id
|
||||||
|
name: string
|
||||||
|
description: string
|
||||||
|
group-id: skill-group-id
|
||||||
|
rarity: rarity
|
||||||
|
group-rate: int
|
||||||
|
grade-value: int
|
||||||
|
wit-check: bool
|
||||||
|
activations: list<activation>
|
||||||
|
owner: maybe<trainee-id>
|
||||||
|
sp-cost: int
|
||||||
|
icon-id: skill-icon-id
|
||||||
|
|
||||||
|
pub fun detail(
|
||||||
|
s: skill-id,
|
||||||
|
?skill/show: (skill-id) -> string,
|
||||||
|
?skill/description: (skill-id) -> string,
|
||||||
|
?skill/group: (skill-id) -> skill-group-id,
|
||||||
|
?skill/rarity: (skill-id) -> rarity,
|
||||||
|
?skill/group-rate: (skill-id) -> int,
|
||||||
|
?skill/grade-value: (skill-id) -> int,
|
||||||
|
?skill/wit-check: (skill-id) -> bool,
|
||||||
|
?skill/activations: (skill-id) -> list<activation>,
|
||||||
|
?skill/unique-owner: (skill-id) -> maybe<trainee-id>,
|
||||||
|
?skill/sp-cost: (skill-id) -> int,
|
||||||
|
?skill/icon-id: (skill-id) -> skill-icon-id
|
||||||
|
): skill-detail
|
||||||
|
Skill-detail(
|
||||||
|
s,
|
||||||
|
s.show,
|
||||||
|
s.description,
|
||||||
|
s.group,
|
||||||
|
s.rarity,
|
||||||
|
s.group-rate,
|
||||||
|
s.grade-value,
|
||||||
|
s.wit-check,
|
||||||
|
s.activations,
|
||||||
|
s.unique-owner,
|
||||||
|
s.sp-cost,
|
||||||
|
s.icon-id
|
||||||
|
)
|
||||||
|
|
||||||
|
pub fun skill-detail/show(d: skill-detail, ?character/show: (character-id) -> string, ?trainee/show: (trainee-id) -> string): string
|
||||||
|
val Skill-detail(Skill-id(id), name, desc, _, rarity, _, grade-value, wit-check, activations, owner, sp-cost, _) = d
|
||||||
|
val r = name ++ " (ID " ++ id.show ++ "): " ++ desc ++ " " ++ activations.map(activation/show).join(". ") ++ (if wit-check then ". Wit check. " else ". No wit check. ") ++ rarity.show ++ " costing " ++ sp-cost.show ++ " SP, worth " ++ grade-value.show ++ " grade value."
|
||||||
|
match owner
|
||||||
|
Nothing -> r
|
||||||
|
Just(owner-id) -> match owner-id.show
|
||||||
|
"" -> r ++ " Unique skill of trainee with ID " ++ owner-id.show ++ "."
|
||||||
|
owner-name -> r ++ " Unique skill of " ++ owner-name ++ "."
|
||||||
|
|
||||||
|
// Skill rarity levels.
|
||||||
|
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\u2606/2\u2606)"
|
||||||
|
Unique-Upgraded -> "Unique (3\u2606+ from 1\u2606/2\u2606 upgraded)"
|
||||||
|
Unique -> "Unique (3\u2606+)"
|
||||||
|
|
||||||
|
// 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: decimal // seconds
|
||||||
|
cooldown: decimal // seconds
|
||||||
|
abilities: list<ability> // one to three elements
|
||||||
|
|
||||||
|
pub fun activation/show(a: activation, ?character/show: (character-id) -> string): string
|
||||||
|
match a
|
||||||
|
Activation("", condition, duration, _, abilities) | !duration.is-pos -> condition ++ " -> " ++ abilities.show
|
||||||
|
Activation("", condition, duration, cooldown, abilities) | cooldown >= 500.decimal -> condition ++ " -> for " ++ duration.show ++ "s, " ++ abilities.show
|
||||||
|
Activation("", condition, duration, cooldown, abilities) -> condition ++ " -> for " ++ duration.show ++ "s on " ++ cooldown.show ++ "s cooldown, " ++ abilities.show
|
||||||
|
Activation(precondition, condition, duration, _, abilities) | !duration.is-pos -> precondition ++ " -> " ++ condition ++ " -> " ++ abilities.show
|
||||||
|
Activation(precondition, condition, duration, cooldown, abilities) | cooldown >= 500.decimal -> precondition ++ " -> " ++ condition ++ " -> for " ++ duration.show ++ "s, " ++ abilities.show
|
||||||
|
Activation(precondition, condition, duration, cooldown, abilities) -> precondition ++ " -> " ++ condition ++ " -> for " ++ duration.show ++ "s on " ++ cooldown.show ++ "s cooldown, " ++ abilities.show
|
||||||
|
|
||||||
|
// Effects of activating a skill.
|
||||||
|
pub struct ability
|
||||||
|
ability-type: ability-type
|
||||||
|
value-usage: value-usage
|
||||||
|
target: target
|
||||||
|
|
||||||
|
pub fun ability/show(a: ability, ?character/show: (character-id) -> string): string
|
||||||
|
match a
|
||||||
|
Ability(t, Direct, Self) -> t.show
|
||||||
|
Ability(t, Direct, target) -> t.show ++ " " ++ target.show
|
||||||
|
Ability(t, v, Self) -> t.show ++ " " ++ v.show
|
||||||
|
Ability(t, v, target) -> t.show ++ " " ++ target.show ++ " " ++ v.show
|
||||||
|
|
||||||
|
// Skill ability effects.
|
||||||
|
pub type ability-type
|
||||||
|
Passive-Speed(bonus: decimal)
|
||||||
|
Passive-Stamina(bonus: decimal)
|
||||||
|
Passive-Power(bonus: decimal)
|
||||||
|
Passive-Guts(bonus: decimal)
|
||||||
|
Passive-Wit(bonus: decimal)
|
||||||
|
Great-Escape
|
||||||
|
Vision(bonus: decimal)
|
||||||
|
HP(rate: decimal)
|
||||||
|
Gate-Delay(rate: decimal)
|
||||||
|
Frenzy(add: decimal)
|
||||||
|
Current-Speed(add: decimal)
|
||||||
|
Target-Speed(add: decimal)
|
||||||
|
Lane-Speed(add: decimal)
|
||||||
|
Accel(add: decimal)
|
||||||
|
Lane-Change(add: decimal)
|
||||||
|
|
||||||
|
pub fun ability-type/show(a: ability-type): string
|
||||||
|
match a
|
||||||
|
Passive-Speed(bonus) -> bonus.show ++ " Speed"
|
||||||
|
Passive-Stamina(bonus) -> bonus.show ++ " Stamina"
|
||||||
|
Passive-Power(bonus) -> bonus.show ++ " Power"
|
||||||
|
Passive-Guts(bonus) -> bonus.show ++ " Guts"
|
||||||
|
Passive-Wit(bonus) -> bonus.show ++ " Wit"
|
||||||
|
Great-Escape -> "enable Great Escape style"
|
||||||
|
Vision(bonus) -> bonus.show ++ " vision"
|
||||||
|
HP(rate) | rate.is-pos -> show(rate * 100.decimal) ++ "% HP recovery"
|
||||||
|
HP(rate) -> show(rate * 100.decimal) ++ "% HP loss"
|
||||||
|
Gate-Delay(rate) -> rate.show ++ "× gate delay"
|
||||||
|
Frenzy(add) -> add.show ++ "s longer Rushed"
|
||||||
|
Current-Speed(rate) -> rate.show ++ "m/s current speed"
|
||||||
|
Target-Speed(rate) -> rate.show ++ "m/s target speed"
|
||||||
|
Lane-Speed(rate) -> rate.show ++ "m/s lane change speed"
|
||||||
|
Accel(rate) -> rate.show ++ "m/s² acceleration"
|
||||||
|
Lane-Change(rate) -> rate.show ++ " course width movement"
|
||||||
|
|
||||||
|
// Special scaling types for skill abilities.
|
||||||
|
pub type value-usage
|
||||||
|
Direct
|
||||||
|
Team-Speed
|
||||||
|
Team-Stamina
|
||||||
|
Team-Power
|
||||||
|
Team-Guts
|
||||||
|
Team-Wit
|
||||||
|
Multiply-Random
|
||||||
|
Multiply-Random2
|
||||||
|
Climax
|
||||||
|
Max-Stat
|
||||||
|
Passive-Count
|
||||||
|
Front-Distance-Add
|
||||||
|
Midrace-Side-Block-Time
|
||||||
|
Speed-Scaling
|
||||||
|
Speed-Scaling2
|
||||||
|
Arc-Global-Potential
|
||||||
|
Max-Lead-Distance
|
||||||
|
|
||||||
|
pub fun value-usage/show(v: value-usage): string
|
||||||
|
match v
|
||||||
|
Direct -> "with no scaling"
|
||||||
|
Team-Speed -> "scaling with team Speed"
|
||||||
|
Team-Stamina -> "scaling with team Stamina"
|
||||||
|
Team-Power -> "scaling with team Power"
|
||||||
|
Team-Guts -> "scaling with team Guts"
|
||||||
|
Team-Wit -> "scaling with team Wit"
|
||||||
|
Multiply-Random -> "scaling with a random multiplier (0×, 0.02×, or 0.04×)"
|
||||||
|
Multiply-Random2 -> "scaling with a random multiplier (0×, 0.02×, or 0.04×)"
|
||||||
|
Climax -> "scaling with the number of races won during training"
|
||||||
|
Max-Stat -> "scaling with the value of the user's highest stat"
|
||||||
|
Passive-Count -> "scaling with the number of Passive skills activated"
|
||||||
|
Front-Distance-Add -> "scaling with distance from the leader"
|
||||||
|
Midrace-Side-Block-Time -> "scaling with mid-race phase blocked side time"
|
||||||
|
Speed-Scaling -> "scaling with overall speed"
|
||||||
|
Speed-Scaling2 -> "scaling with overall speed"
|
||||||
|
Arc-Global-Potential -> "scaling with L'Arc global potential"
|
||||||
|
Max-Lead-Distance -> "scaling with the distance of the longest lead obtained in the first two thirds of the race"
|
||||||
|
|
||||||
|
// Who a skill ability targets.
|
||||||
|
pub type target
|
||||||
|
Self
|
||||||
|
Sympathizers
|
||||||
|
In-View
|
||||||
|
Frontmost(limit: int)
|
||||||
|
Ahead(limit: int)
|
||||||
|
Behind(limit: int)
|
||||||
|
All-Teammates
|
||||||
|
Style(style: style)
|
||||||
|
Rushing-Ahead(limit: int)
|
||||||
|
Rushing-Behind(limit: int)
|
||||||
|
Rushing-Style(style: style)
|
||||||
|
Specific-Character(who: character-id)
|
||||||
|
Triggering
|
||||||
|
|
||||||
|
pub fun target/show(t: target, ?character/show: (character-id) -> string): string
|
||||||
|
match t
|
||||||
|
Self -> "self"
|
||||||
|
Sympathizers -> "others with Sympathy"
|
||||||
|
In-View -> "others in field of view"
|
||||||
|
Frontmost(limit) -> "frontmost " ++ limit.show
|
||||||
|
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"
|
||||||
|
All-Teammates -> "all teammates"
|
||||||
|
Style(s) -> "other " ++ s.show ++ "s"
|
||||||
|
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(s) -> "rushing " ++ s.show ++ "s"
|
||||||
|
Specific-Character(who) -> match who.show
|
||||||
|
"" -> "character with ID " ++ who.show
|
||||||
|
name -> name
|
||||||
|
Triggering -> "whosoever triggered this skill"
|
||||||
@@ -1,70 +1,16 @@
|
|||||||
module horse/trainee
|
module horse/trainee
|
||||||
|
|
||||||
import std/data/rb-map
|
import horse/movement
|
||||||
|
|
||||||
// Aptitudes of an umamusume being trained.
|
// Details of a trainee.
|
||||||
pub struct uma
|
pub struct trainee-detail
|
||||||
turf: aptitudes
|
turf: level
|
||||||
dirt: aptitudes
|
dirt: level
|
||||||
sprint: aptitudes
|
sprint: level
|
||||||
mile: aptitudes
|
mile: level
|
||||||
medium: aptitudes
|
medium: level
|
||||||
long: aptitudes
|
long: level
|
||||||
front-runner: aptitudes
|
front-runner: level
|
||||||
pace-chaser: aptitudes
|
pace-chaser: level
|
||||||
late-surger: aptitudes
|
late-surger: level
|
||||||
end-closer: aptitudes
|
end-closer: level
|
||||||
|
|
||||||
// Aptitude level distribution.
|
|
||||||
pub alias aptitudes = rbmap<level, float64>
|
|
||||||
|
|
||||||
// Starting aptitude levels.
|
|
||||||
pub type level
|
|
||||||
G
|
|
||||||
F
|
|
||||||
E
|
|
||||||
D
|
|
||||||
C
|
|
||||||
B
|
|
||||||
A
|
|
||||||
S
|
|
||||||
|
|
||||||
// Automatically generated.
|
|
||||||
// Fip comparison of the `level` type.
|
|
||||||
pub fun level/order2(this : level, other : level) : order2<level>
|
|
||||||
match (this, other)
|
|
||||||
(G, G) -> Eq2(G)
|
|
||||||
(G, other') -> Lt2(G, other')
|
|
||||||
(this', G) -> Gt2(G, this')
|
|
||||||
(F, F) -> Eq2(F)
|
|
||||||
(F, other') -> Lt2(F, other')
|
|
||||||
(this', F) -> Gt2(F, this')
|
|
||||||
(E, E) -> Eq2(E)
|
|
||||||
(E, other') -> Lt2(E, other')
|
|
||||||
(this', E) -> Gt2(E, this')
|
|
||||||
(D, D) -> Eq2(D)
|
|
||||||
(D, other') -> Lt2(D, other')
|
|
||||||
(this', D) -> Gt2(D, this')
|
|
||||||
(C, C) -> Eq2(C)
|
|
||||||
(C, other') -> Lt2(C, other')
|
|
||||||
(this', C) -> Gt2(C, this')
|
|
||||||
(B, B) -> Eq2(B)
|
|
||||||
(B, other') -> Lt2(B, other')
|
|
||||||
(this', B) -> Gt2(B, this')
|
|
||||||
(A, A) -> Eq2(A)
|
|
||||||
(A, other') -> Lt2(A, other')
|
|
||||||
(this', A) -> Gt2(A, this')
|
|
||||||
(S, S) -> Eq2(S)
|
|
||||||
|
|
||||||
// Automatically generated.
|
|
||||||
// Shows a string representation of the `level` type.
|
|
||||||
pub fun level/show(this : level) : string
|
|
||||||
match this
|
|
||||||
G -> "G"
|
|
||||||
F -> "F"
|
|
||||||
E -> "E"
|
|
||||||
D -> "D"
|
|
||||||
C -> "C"
|
|
||||||
B -> "B"
|
|
||||||
A -> "A"
|
|
||||||
S -> "S"
|
|
||||||
|
|||||||
@@ -93,15 +93,6 @@ func ExecSkill(t *template.Template, region string, kk, g io.Writer, groups []Na
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExecSkillGroupKK(t *template.Template, region string, w io.Writer, g []NamedID[SkillGroup], s []Skill) error {
|
|
||||||
data := struct {
|
|
||||||
Region string
|
|
||||||
Groups []NamedID[SkillGroup]
|
|
||||||
Skills []Skill
|
|
||||||
}{region, g, s}
|
|
||||||
return t.ExecuteTemplate(w, "koka-skill-group", &data)
|
|
||||||
}
|
|
||||||
|
|
||||||
const wordSeps = " ,!?/-+();#○☆♡'=♪∀゚∴"
|
const wordSeps = " ,!?/-+();#○☆♡'=♪∀゚∴"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -179,21 +179,22 @@ func SkillGroups(ctx context.Context, db *sqlitex.Pool) ([]NamedID[SkillGroup],
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Skill struct {
|
type Skill struct {
|
||||||
ID int
|
ID int
|
||||||
Name string
|
Name string
|
||||||
Description string
|
Description string
|
||||||
GroupID int
|
GroupID int
|
||||||
GroupName string
|
GroupName string
|
||||||
Rarity int
|
Rarity int
|
||||||
GroupRate int
|
GroupRate int
|
||||||
GradeValue int
|
GradeValue int
|
||||||
WitCheck bool
|
WitCheck bool
|
||||||
Activations [2]SkillActivation
|
Activations [2]SkillActivation
|
||||||
SPCost int
|
SPCost int
|
||||||
InheritID int
|
InheritID int
|
||||||
UniqueOwner string
|
UniqueOwnerID int
|
||||||
IconID int
|
UniqueOwner string
|
||||||
Index int
|
IconID int
|
||||||
|
Index int
|
||||||
}
|
}
|
||||||
|
|
||||||
type SkillActivation struct {
|
type SkillActivation struct {
|
||||||
@@ -303,11 +304,12 @@ func Skills(ctx context.Context, db *sqlitex.Pool) ([]Skill, error) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
SPCost: stmt.ColumnInt(47),
|
SPCost: stmt.ColumnInt(47),
|
||||||
InheritID: stmt.ColumnInt(48),
|
InheritID: stmt.ColumnInt(48),
|
||||||
UniqueOwner: stmt.ColumnText(49),
|
UniqueOwnerID: stmt.ColumnInt(49),
|
||||||
IconID: stmt.ColumnInt(50),
|
UniqueOwner: stmt.ColumnText(50),
|
||||||
Index: stmt.ColumnInt(51),
|
IconID: stmt.ColumnInt(51),
|
||||||
|
Index: stmt.ColumnInt(52),
|
||||||
}
|
}
|
||||||
r = append(r, s)
|
r = append(r, s)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,14 +116,6 @@ func main() {
|
|||||||
slog.Info("write skills")
|
slog.Info("write skills")
|
||||||
return ExecSkill(t, region, sf, gf, sg, skills)
|
return ExecSkill(t, region, sf, gf, sg, skills)
|
||||||
})
|
})
|
||||||
eg.Go(func() error {
|
|
||||||
sf, err := os.Create(filepath.Join(out, region, "skill-group.kk"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
slog.Info("write skill groups")
|
|
||||||
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))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,347 +1,213 @@
|
|||||||
{{- define "koka-skill-group" -}}
|
|
||||||
module horse/{{ $.Region }}/skill-group
|
|
||||||
|
|
||||||
// Automatically generated with horsegen; DO NOT EDIT
|
|
||||||
|
|
||||||
// Skill groups.
|
|
||||||
// A skill group may contain white, circle, double-circle, gold, and purple skills
|
|
||||||
// for the same effect.
|
|
||||||
// Sparks that grant skills refer to a skill group.
|
|
||||||
pub type skill-group
|
|
||||||
{{- range $g := $.Groups }}
|
|
||||||
{{ kkenum $g.Name }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
// Map a skill group to its ID.
|
|
||||||
pub fip fun skill-group/group-id(^sg: skill-group): int
|
|
||||||
match sg
|
|
||||||
{{- range $g := $.Groups }}
|
|
||||||
{{ kkenum $g.Name }} -> {{ $g.ID }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
// Get the skill group for an ID.
|
|
||||||
pub fip(1) fun skill-group/from-id(^id: int): maybe<skill-group>
|
|
||||||
match id
|
|
||||||
{{- range $g := $.Groups }}
|
|
||||||
{{ $g.ID }} -> Just( {{- kkenum $g.Name -}} )
|
|
||||||
{{- end }}
|
|
||||||
_ -> Nothing
|
|
||||||
|
|
||||||
// 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
|
|
||||||
{{- range $g := $.Groups }}
|
|
||||||
{{ kkenum $g.Name }} -> {{ printf "%q" $g.Name }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
// Compare two skill groups by ID order.
|
|
||||||
pub fip fun skill-group/order2(a: skill-group, b: skill-group): order2<skill-group>
|
|
||||||
match cmp(a.group-id, b.group-id)
|
|
||||||
Lt -> Lt2(a, b)
|
|
||||||
Eq -> Eq2(a)
|
|
||||||
Gt -> Gt2(a, b)
|
|
||||||
|
|
||||||
pub fun skill-group/(==)(a: skill-group, b: skill-group): bool
|
|
||||||
a.group-id == b.group-id
|
|
||||||
|
|
||||||
{{- end -}}
|
|
||||||
|
|
||||||
{{- define "koka-skill" -}}
|
{{- define "koka-skill" -}}
|
||||||
module horse/{{ $.Region }}/skill
|
module horse/{{ $.Region }}/skill
|
||||||
|
|
||||||
// Automatically generated with horsegen; DO NOT EDIT
|
// Automatically generated with horsegen; DO NOT EDIT
|
||||||
|
|
||||||
|
import std/data/rb-map
|
||||||
import std/num/decimal
|
import std/num/decimal
|
||||||
pub import horse/{{ $.Region }}/skill-group
|
import horse/game-id
|
||||||
|
import horse/movement
|
||||||
|
pub import horse/skill
|
||||||
|
|
||||||
// Skill instances.
|
val name2id: rbmap<string, skill-id> = rb-map/empty()
|
||||||
pub type skill
|
|
||||||
{{- range $s := $.Skills }}
|
{{- range $s := $.Skills }}
|
||||||
{{ kkenum $s.Name }}{{ if ne $s.InheritID 0 }}-Inherit{{ end -}}
|
.set({{ printf "%q" $s.Name }}{{ if $s.InheritID }} ++ " (Inherited)"{{ end }}, Skill-id({{ $s.ID }}))
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
// Map a skill to its ID.
|
// Get the skill ID that has the given exact name.
|
||||||
pub fip fun skill/skill-id(^s: skill): int
|
// Inherited skills have `" (Inherited)"` appended to their names.
|
||||||
match s
|
// If no skill matches the ID, the result is an invalid ID.
|
||||||
{{- range $s := $.Skills }}
|
pub fun from-name(name: string): skill-id
|
||||||
{{ kkenum $s.Name }}{{ if ne $s.InheritID 0 }}-Inherit{{ end }} -> {{ $s.ID }}
|
name2id.lookup(name).default(Skill-id(0))
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
// Get the skill for an ID.
|
// Get the name for a skill.
|
||||||
pub fip(1) fun skill/from-id(^id: int): maybe<skill>
|
// Inherited skills have `" (Inherited)"` appended to their names.
|
||||||
match id
|
// If no skill matches the ID, the result is the numeric ID.
|
||||||
|
pub fun show(s: skill-id): string
|
||||||
|
match s.game-id
|
||||||
{{- range $s := $.Skills }}
|
{{- range $s := $.Skills }}
|
||||||
{{ $s.ID }} -> Just( {{- kkenum $s.Name -}}{{ if ne $s.InheritID 0 }}-Inherit{{ end -}} )
|
{{ $s.ID }} -> {{ printf "%q" $s.Name }}{{ if $s.InheritID }} ++ " (Inherited)"{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
x -> "skill " ++ x.show
|
||||||
|
|
||||||
|
// Get the description for a skill.
|
||||||
|
// If no skill matches the ID, the result is the empty string.
|
||||||
|
pub fun description(s: skill-id): string
|
||||||
|
match s.game-id
|
||||||
|
{{- range $s := $.Skills }}
|
||||||
|
{{ $s.ID }} -> {{ printf "%q" $s.Description }}
|
||||||
|
{{- end }}
|
||||||
|
_ -> ""
|
||||||
|
|
||||||
|
// Get the skill group ID for a skill.
|
||||||
|
// If no skill matches the ID, the result is an invalid ID.
|
||||||
|
pub fun group(s: skill-id): skill-group-id
|
||||||
|
match s.game-id
|
||||||
|
{{- range $s := $.Skills }}
|
||||||
|
{{ $s.ID }} -> Skill-group-id( {{- $s.GroupID -}} )
|
||||||
|
{{- end }}
|
||||||
|
_ -> Skill-group-id(0)
|
||||||
|
|
||||||
|
// Get the rarity of a skill.
|
||||||
|
// If no skill matches the ID, the result is Common.
|
||||||
|
pub fun rarity(s: skill-id): rarity
|
||||||
|
match s.game-id
|
||||||
|
{{- range $s := $.Skills }}
|
||||||
|
{{ $s.ID }} -> {{ if eq $s.Rarity 1 }}Common{{ else if eq $s.Rarity 2 }}Rare{{ else if eq $s.Rarity 3 }}Unique-Low{{ else if eq $s.Rarity 4 }}Unique-Upgraded{{ else if eq $s.Rarity 5 }}Unique{{ else }}??? $s.Rarity={{ $s.Rarity }}{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
_ -> Common
|
||||||
|
|
||||||
|
// Get the group rate of a skill.
|
||||||
|
// If no skill matches the ID, the result is 0.
|
||||||
|
pub fun group-rate(s: skill-id): int
|
||||||
|
match s.game-id
|
||||||
|
{{- range $s := $.Skills }}
|
||||||
|
{{ $s.ID }} -> {{ $s.GroupRate }}
|
||||||
|
{{- end }}
|
||||||
|
_ -> 0
|
||||||
|
|
||||||
|
// Get the grade value of a skill.
|
||||||
|
// If no skill matches the ID, the result is 0.
|
||||||
|
pub fun grade-value(s: skill-id): int
|
||||||
|
match s.game-id
|
||||||
|
{{- range $s := $.Skills }}
|
||||||
|
{{ $s.ID }} -> {{ $s.GradeValue }}
|
||||||
|
{{- end }}
|
||||||
|
_ -> 0
|
||||||
|
|
||||||
|
// Get whether a skill is a wit check.
|
||||||
|
// If no skill matches the ID, the result is False.
|
||||||
|
pub fun wit-check(s: skill-id): bool
|
||||||
|
match s.game-id
|
||||||
|
{{- range $s := $.Skills }}
|
||||||
|
{{ $s.ID }} -> {{ if $s.WitCheck }}True{{ else }}False{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
_ -> False
|
||||||
|
|
||||||
|
// Get the activations of a skill.
|
||||||
|
// If no skill matches the ID, the result is an empty list.
|
||||||
|
pub fun activations(s: skill-id): list<activation>
|
||||||
|
match s.game-id
|
||||||
|
{{- range $s := $.Skills }}
|
||||||
|
{{ $s.ID }} -> [
|
||||||
|
{{- range $a := $s.Activations }}
|
||||||
|
{{- if $a.Condition }}
|
||||||
|
Activation(
|
||||||
|
precondition = {{ printf "%q" $a.Precondition }},
|
||||||
|
condition = {{ printf "%q" $a.Condition }},
|
||||||
|
duration = {{ $a.Duration }}.decimal{{ if gt $a.Duration 0 }}(-4){{ end }},
|
||||||
|
cooldown = {{ $a.Cooldown }}.decimal{{ if gt $a.Cooldown 0 }}(-4){{ end }},
|
||||||
|
abilities = [
|
||||||
|
{{- range $abil := $a.Abilities }}
|
||||||
|
{{- if $abil.Type }}
|
||||||
|
Ability(
|
||||||
|
ability-type = {{ if eq $abil.Type 1 }}Passive-Speed({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 2 }}Passive-Stamina({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 3 }}Passive-Power({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 4 }}Passive-Guts({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 5 }}Passive-Wit({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 6 }}Great-Escape
|
||||||
|
{{- else if eq $abil.Type 8 }}Vision({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 9 }}HP({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 10 }}Gate-Delay({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 13 }}Frenzy({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 21 }}Current-Speed({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 27 }}Target-Speed({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 28 }}Lane-Speed({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 31 }}Accel({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 35 }}Lane-Change({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- 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 if eq $abil.ValueUsage 9 }}Multiply-Random2
|
||||||
|
{{- else if eq $abil.ValueUsage 10 }}Climax
|
||||||
|
{{- else if eq $abil.ValueUsage 13 }}Max-Stat
|
||||||
|
{{- else if eq $abil.ValueUsage 14 }}Passive-Count
|
||||||
|
{{- else if eq $abil.ValueUsage 19 }}Front-Distance-Add
|
||||||
|
{{- else if eq $abil.ValueUsage 20 }}Midrace-Side-Block-Time
|
||||||
|
{{- else if eq $abil.ValueUsage 22 }}Speed-Scaling
|
||||||
|
{{- else if eq $abil.ValueUsage 23 }}Speed-Scaling2
|
||||||
|
{{- else if eq $abil.ValueUsage 24 }}Arc-Global-Potential
|
||||||
|
{{- else if eq $abil.ValueUsage 25 }}Max-Lead-Distance
|
||||||
|
{{- else }}??? $abil.ValueUsage={{ $abil.ValueUsage }}
|
||||||
|
{{- end }},
|
||||||
|
target = {{ if eq $abil.Target 1}}Self
|
||||||
|
{{- else if eq $abil.Target 4 }}Sympathizers
|
||||||
|
{{- else if eq $abil.Target 4 }}In-View
|
||||||
|
{{- else if eq $abil.Target 4 }}Frontmost
|
||||||
|
{{- else if eq $abil.Target 9 }}Ahead({{ $abil.TargetValue }})
|
||||||
|
{{- else if eq $abil.Target 10 }}Behind({{ $abil.TargetValue }})
|
||||||
|
{{- else if eq $abil.Target 4 }}All-Teammates
|
||||||
|
{{- 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 }})
|
||||||
|
{{- else if eq $abil.Target 22 }}Specific-Character(Character-id({{ $abil.TargetValue }}))
|
||||||
|
{{- else if eq $abil.Target 23 }}Triggering
|
||||||
|
{{- end }}
|
||||||
|
),
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
]
|
||||||
|
),
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
]
|
||||||
|
{{- end }}
|
||||||
|
_ -> Nil
|
||||||
|
|
||||||
|
// Get the owner of a unique skill.
|
||||||
|
// If the skill is not unique, or if there is no skill with the given ID,
|
||||||
|
// the result is Nothing.
|
||||||
|
pub fun unique-owner(s: skill-id): maybe<trainee-id>
|
||||||
|
match s.game-id
|
||||||
|
{{- range $s := $.Skills }}
|
||||||
|
{{- if $s.UniqueOwnerID }}
|
||||||
|
{{ $s.ID }} -> Just(Trainee-id({{ $s.UniqueOwnerID }}))
|
||||||
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
|
|
||||||
// Get the name of a skill.
|
// Get the SP cost of a skill.
|
||||||
// Inherited skills have the same names as their original counterparts.
|
// If there is no skill with the given ID, the result is 0.
|
||||||
pub fun skill/show(s: skill): string
|
pub fun sp-cost(s: skill-id): int
|
||||||
match s
|
match s.game-id
|
||||||
{{- range $s := $.Skills }}
|
{{- range $s := $.Skills }}
|
||||||
{{ kkenum $s.Name }}{{ if ne $s.InheritID 0 }}-Inherit{{ end }} -> {{ printf "%q" $s.Name }}
|
{{ $s.ID }} -> {{ $s.SPCost }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
_ -> 0
|
||||||
|
|
||||||
// Compare two skills by ID order.
|
// Get the icon ID of a skill.
|
||||||
pub fip fun skill/order2(a: skill, b: skill): order2<skill>
|
// If there is no skill with the given ID, the result is an invalid ID.
|
||||||
match cmp(a.skill-id, b.skill-id)
|
pub fun icon-id(s: skill-id): skill-icon-id
|
||||||
Lt -> Lt2(a, b)
|
match s.game-id
|
||||||
Eq -> Eq2(a)
|
{{- range $s := $.Skills }}
|
||||||
Gt -> Gt2(a, b)
|
{{ $s.ID }} -> Skill-icon-id({{ $s.IconID }})
|
||||||
|
{{- end }}
|
||||||
|
_ -> Skill-icon-id(0)
|
||||||
|
|
||||||
pub fun skill/(==)(a: skill, b: skill): bool
|
// Get the name for a skill group.
|
||||||
a.skill-id == b.skill-id
|
// Skill group names are the name of the base skill in the group.
|
||||||
|
// If there is no skill group with the given ID, the result is the numeric ID.
|
||||||
// Get the skills in a skill group.
|
pub fun skill-group/show(sg: skill-group-id): string
|
||||||
pub fun skill-group/skills(g: skill-group): list<skill>
|
match sg.game-id
|
||||||
match g
|
|
||||||
{{- range $g := $.Groups }}
|
{{- range $g := $.Groups }}
|
||||||
{{ kkenum $g.Name }} -> [ {{- range $s := index $.Related $g.ID }}{{ kkenum $s.Name }}{{ if ne $s.InheritID 0 }}-Inherit{{ end }}, {{ end }}]
|
{{ $g.ID }} -> {{- printf "%q" $g.Name -}}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
x -> "skill group " ++ x.show
|
||||||
|
|
||||||
// Get complete skill info.
|
// Get the list of skills in a skill group.
|
||||||
pub fun skill/detail(^s: skill): skill-detail
|
pub fun skill-group/skills(sg: skill-group-id): list<skill-id>
|
||||||
match s
|
match sg.game-id
|
||||||
{{- range $s := $.Skills }}
|
{{- range $g := $.Groups }}
|
||||||
{{ kkenum $s.Name }}{{ if ne $s.InheritID 0 }}-Inherit{{ end }} -> {{ template "kk-render-skill-detail" $s }}
|
{{ $g.ID }} -> [ {{- range $s := index $.Related $g.ID }}Skill-id({{ $s.ID }}), {{ end -}} ]
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
_ -> Nil
|
||||||
|
|
||||||
// Details about a skill.
|
{{- end }}
|
||||||
pub struct skill-detail
|
|
||||||
skill-id: int
|
|
||||||
name: string
|
|
||||||
description: string
|
|
||||||
group: maybe<skill-group>
|
|
||||||
rarity: rarity
|
|
||||||
group-rate: int
|
|
||||||
grade-value: int
|
|
||||||
wit-check: bool
|
|
||||||
activations: list<activation>
|
|
||||||
sp-cost: int
|
|
||||||
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, sp-cost, 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 ++ ", sp-cost: " ++ sp-cost.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\u2606/2\u2606)"
|
|
||||||
Unique-Upgraded -> "Unique (3\u2606+ from 1\u2606/2\u2606 upgraded)"
|
|
||||||
Unique -> "Unique (3\u2606+)"
|
|
||||||
|
|
||||||
// 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: decimal // seconds
|
|
||||||
cooldown: decimal // seconds
|
|
||||||
abilities: list<ability> // one to three elements
|
|
||||||
|
|
||||||
pub fun activation/show(a: activation): string
|
|
||||||
match a
|
|
||||||
Activation("", condition, duration, _, abilities) | duration <= 0.decimal -> condition ++ " -> " ++ abilities.show
|
|
||||||
Activation("", condition, duration, cooldown, abilities) | cooldown >= 500.decimal -> 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, duration, _, abilities) | duration <= 0.decimal -> precondition ++ " -> " ++ condition ++ " -> " ++ abilities.show
|
|
||||||
Activation(precondition, condition, duration, cooldown, abilities) | cooldown >= 500.decimal -> 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: decimal)
|
|
||||||
Passive-Stamina(bonus: decimal)
|
|
||||||
Passive-Power(bonus: decimal)
|
|
||||||
Passive-Guts(bonus: decimal)
|
|
||||||
Passive-Wit(bonus: decimal)
|
|
||||||
Great-Escape
|
|
||||||
Vision(bonus: decimal)
|
|
||||||
HP(rate: decimal)
|
|
||||||
Gate-Delay(rate: decimal)
|
|
||||||
Frenzy(add: decimal)
|
|
||||||
Current-Speed(rate: decimal)
|
|
||||||
Target-Speed(rate: decimal)
|
|
||||||
Lane-Speed(rate: decimal)
|
|
||||||
Accel(rate: decimal)
|
|
||||||
Lane-Change(rate: decimal)
|
|
||||||
|
|
||||||
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"
|
|
||||||
Great-Escape -> "enable Great Escape style"
|
|
||||||
Vision(bonus) -> bonus.show ++ " vision"
|
|
||||||
HP(rate) | rate >= 0.decimal -> show(rate * 100.decimal) ++ "% HP recovery"
|
|
||||||
HP(rate) -> show(rate * 100.decimal) ++ "% HP loss"
|
|
||||||
Gate-Delay(rate) -> rate.show ++ "× gate delay"
|
|
||||||
Frenzy(add) -> add.show ++ "s longer Rushed"
|
|
||||||
Current-Speed(rate) -> show(rate * 100.decimal) ++ "% current speed"
|
|
||||||
Target-Speed(rate) -> show(rate * 100.decimal) ++ "% target speed"
|
|
||||||
Lane-Speed(rate) -> show(rate * 100.decimal) ++ "% lane speed"
|
|
||||||
Accel(rate) -> show(rate * 100.decimal) ++ "% 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×, 0.02×, or 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 = {{ if ne $.GroupName "" }}Just({{ kkenum $.GroupName }}){{ else }}Nothing{{ end -}}
|
|
||||||
, 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 = {{ $a.Duration -}}{{ if gt $a.Duration 0 }}.decimal(-4){{ else }}.decimal{{ end -}}
|
|
||||||
, cooldown = {{ $a.Cooldown -}}{{ if gt $a.Cooldown 0 }}.decimal(-4){{ else }}.decimal{{ end -}}
|
|
||||||
, abilities = [
|
|
||||||
{{- range $abil := $a.Abilities -}}
|
|
||||||
{{- if ne $abil.Type 0 -}}
|
|
||||||
Ability(ability-type =
|
|
||||||
{{- if eq $abil.Type 1 -}}Passive-Speed({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 2 -}}Passive-Stamina({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 3 -}}Passive-Power({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 4 -}}Passive-Guts({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 5 -}}Passive-Wit({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 6 -}}Great-Escape
|
|
||||||
{{- else if eq $abil.Type 8 -}}Vision({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 9 -}}HP({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 10 -}}Gate-Delay({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 13 -}}Frenzy({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 21 -}}Current-Speed({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 27 -}}Target-Speed({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 28 -}}Lane-Speed({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 31 -}}Accel({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 35 -}}Lane-Change({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- 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 -}}
|
|
||||||
], sp-cost = {{ $.SPCost -}}
|
|
||||||
, icon-id = {{ $.IconID -}}
|
|
||||||
)
|
|
||||||
{{- end -}}
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ WITH skill_names AS (
|
|||||||
), card_unique AS (
|
), card_unique AS (
|
||||||
SELECT DISTINCT
|
SELECT DISTINCT
|
||||||
ss.skill_id1 AS unique_id,
|
ss.skill_id1 AS unique_id,
|
||||||
|
card_name.id AS owner_id,
|
||||||
card_name.name
|
card_name.name
|
||||||
FROM card_data card
|
FROM card_data card
|
||||||
JOIN card_name ON card.id = card_name.id
|
JOIN card_name ON card.id = card_name.id
|
||||||
@@ -81,6 +82,7 @@ SELECT
|
|||||||
d.target_value_2_3,
|
d.target_value_2_3,
|
||||||
IFNULL(p.need_skill_point, 0) AS sp_cost,
|
IFNULL(p.need_skill_point, 0) AS sp_cost,
|
||||||
d.unique_skill_id_1,
|
d.unique_skill_id_1,
|
||||||
|
COALESCE(u.owner_id, iu.owner_id, 0) AS unique_owner_id,
|
||||||
COALESCE(u.name, iu.name, '') AS unique_owner,
|
COALESCE(u.name, iu.name, '') AS unique_owner,
|
||||||
d.icon_id,
|
d.icon_id,
|
||||||
ROW_NUMBER() OVER (ORDER BY d.id) - 1 AS "index"
|
ROW_NUMBER() OVER (ORDER BY d.id) - 1 AS "index"
|
||||||
|
|||||||
Reference in New Issue
Block a user