227 lines
8.9 KiB
Plaintext
227 lines
8.9 KiB
Plaintext
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"
|