Compare commits

..
3 Commits
Author SHA1 Message Date
zephyr eaee64dca4 cmd/horsebot: download support card icons
ci/woodpecker/push/zenno Pipeline failed
ci/woodpecker/push/horsebot Pipeline was successful
2026-08-02 23:36:32 -04:00
zephyr a232f78ac7 zenno: support card type definitions 2026-08-02 23:27:43 -04:00
zephyr 061fe89b7f remove vestiges of an ancient past 2026-08-02 22:48:02 -04:00
3 changed files with 223 additions and 424 deletions
+11
View File
@@ -33,6 +33,10 @@ func saveImgs(ctx context.Context, db *sqlitex.Pool, out string) {
if err != nil {
slog.Error("ranks", slog.Any("err", err))
}
supps, err := suppIDs(ctx, db)
if err != nil {
slog.Error("supports", slog.Any("err", err))
}
g, ctx := errgroup.WithContext(ctx)
tick := time.NewTicker(250 * time.Millisecond)
@@ -40,6 +44,7 @@ func saveImgs(ctx context.Context, db *sqlitex.Pool, out string) {
idouts(ctx, g, tick, chara, filepath.Join(out, "chara"), "https://gametora.com/images/umamusume/characters/icons/chr_icon_%d.png", image.Pt(256, 256), image.Pt(64, 64), image.Pt(32, 32), image.Pt(16, 16))
idouts(ctx, g, tick, rank, filepath.Join(out, "rank"), "https://media.gametora.com/umamusume/ui/rank/%02d.png", image.Pt(128, 128), image.Pt(64, 64), image.Pt(32, 32), image.Pt(16, 16))
idouts(ctx, g, tick, rank, filepath.Join(out, "rank", "simple"), "https://media.gametora.com/umamusume/ui/rank/simple/%02d.png", image.Pt(50, 50), image.Pt(32, 32), image.Pt(16, 16))
idouts(ctx, g, tick, supps, filepath.Join(out, "support"), "https://gametora.com/images/umamusume/supports/support_card_s_%d.png", image.Pt(128, 128), image.Pt(64, 64), image.Pt(32, 32))
if err := g.Wait(); err != nil {
slog.Error("output", slog.Any("err", err))
}
@@ -88,6 +93,12 @@ func rankIDs(ctx context.Context, db *sqlitex.Pool) ([]int32, error) {
})
}
func suppIDs(ctx context.Context, db *sqlitex.Pool) ([]int32, error) {
return load(ctx, db, nil, "SELECT id FROM support_card_data", func(s *sqlite.Stmt) int32 {
return s.ColumnInt32(0)
})
}
var pngenc = &png.Encoder{CompressionLevel: png.BestCompression}
func idouts(ctx context.Context, g *errgroup.Group, tick *time.Ticker, ids []int32, p, urlf string, sizes ...image.Point) {
-424
View File
@@ -1,424 +0,0 @@
/**
* TypeScript schema for JSON files generated by horsegen.
*/
/**
* Character definitions.
*/
export interface Character {
/**
* Character ID.
*/
chara_id: number;
/**
* Regional name of the character.
* E.g., Special Week for Global, or スペシャルウィーク for JP.
*/
name: string;
}
/**
* Precomputed character pair and trio affinity.
*/
export interface Affinity {
/**
* First character in the relation.
*/
chara_a: number;
/**
* Second character in the relation.
* chara_a < chara_b is an invariant.
*/
chara_b: number;
/**
* Third character in the relation, if it is a trio relation.
* If defined, chara_b < chara_c is an invariant.
*/
chara_c?: number;
/**
* Total base compatibility between characters in the relation.
*/
affinity: number;
}
/**
* Uma or character card definitions.
*/
export interface Uma {
/**
* Uma ID.
*/
chara_card_id: number;
/**
* Character ID that the Uma is a variant of.
*/
chara_id: number;
/**
* Regional name of the Uma, comprised of the variant name and the character name.
* E.g. "[Special Dreamer] Special Week".
*/
name: string;
/**
* Regional variant name.
* E.g. "[Special Dreamer]".
*/
variant: string;
sprint: AptitudeLevel;
mile: AptitudeLevel;
medium: AptitudeLevel;
long: AptitudeLevel;
front: AptitudeLevel;
pace: AptitudeLevel;
late: AptitudeLevel;
end: AptitudeLevel;
turf: AptitudeLevel;
dirt: AptitudeLevel;
/**
* ID of the Uma's unique skill.
*/
unique: number;
/**
* ID of the Uma's first built-in skill.
*/
skill1: number;
/**
* ID of the Uma's second built-in skill.
*/
skill2: number;
/**
* ID of the Uma's third built-in skill.
*/
skill3: number;
/**
* ID of the skill unlocked at potential level 2.
*/
skill_pl2: number;
/**
* ID of the skill unlocked at potential level 3.
*/
skill_pl3: number;
/**
* ID of the skill unlocked at potential level 4.
*/
skill_pl4: number;
/**
* ID of the skill unlocked at potential level 5.
*/
skill_pl5: number;
}
export type AptitudeLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
/**
* Race data.
*/
export interface Race {
/**
* Race ID.
*/
race_id: number;
/**
* Regional name of the race.
*/
name: string;
/**
* Thumbnail asset ID number.
*/
thumbnail: number;
/**
* Primary race ID.
* For most races, this is the same as race_id. Some races are alternate
* versions for certain careers; this holds the ID of the normal version of
* the race.
*/
primary: number;
}
/**
* Race saddle data.
*/
export interface Saddle {
/**
* Saddle ID.
*/
saddle_id: number;
/**
* Regional name of the saddle.
*/
name: string;
/**
* IDs of race wins required to earn the saddle.
*/
races: number[];
/**
* Saddle type: 0 for multi-race honors, 3 for G1, 2 for G2, 1 for G3.
*/
type: 0 | 1 | 2 | 3;
/**
* Primary saddle ID.
* Respective for races.
*/
primary: number;
}
/**
* Scenario data.
*/
export interface Scenario {
/**
* Scenario ID.
*/
scenario_id: number;
/**
* Regional scenario name, e.g. "TS Climax".
*/
name: string;
/**
* Regional full title, e.g. "Trackblazer: Start of the Climax".
*/
title: string;
}
/**
* Skill data.
*/
export interface Skill {
/**
* Skill ID.
*/
skill_id: number;
/**
* Regional skill name.
*/
name: string;
/**
* Regional skil description.
*/
description: string;
/**
* Skill group ID.
*/
group: number;
/**
* Skill rarity. 3-5 are uniques for various star levels.
*/
rarity: 1 | 2 | 3 | 4 | 5;
/**
* Upgrade position within the skill's group.
* -1 is for negative (purple) skills.
*/
group_rate: 1 | 2 | 3 | -1;
/**
* Grade value, or the amount of rating gained for having the skill with
* appropriate aptitude.
*/
grade_value?: number;
/**
* Whether the skill requires a wit check.
*/
wit_check: boolean;
/**
* Conditions and results of skill activation.
*/
activations: [Activation] | [Activation, Activation];
/**
* Name of the Uma which owns this skill as a unique, if applicable.
*/
unique_owner?: string;
/**
* Skill tags, numeric IDs for matching against other effects.
*/
tags: number[];
/**
* SP cost to purchase the skill, if applicable.
*/
sp_cost?: number;
/**
* Skill icon ID.
*/
icon_id: number;
}
/**
* Conditions and results of skill activation.
*/
export interface Activation {
/**
* Precondition which must be satisfied before the condition is checked.
*/
precondition?: string;
/**
* Activation conditions.
*/
condition: string;
/**
* Skill duration in ten thousandths of a second.
* Generally undefined for activations which only affect HP.
*/
duration?: number;
/**
* Special skill duration scaling mode.
*/
dur_scale: 1 | 2 | 3 | 4 | 5 | 7;
/**
* Skill cooldown in ten thousandths of a second.
* A value of 5000000 indicates that the cooldown is forever.
* Generally undefined for passive skills.
*/
cooldown?: number;
/**
* Results applied when the skill's conditions are met.
*/
abilities: [Ability] | [Ability, Ability] | [Ability, Ability, Ability];
}
/**
* Effects applied when a skill activates.
*/
export interface Ability {
/**
* Race mechanic affected by the ability.
*/
type: 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 13 | 21 | 27 | 28 | 31 | 35;
/**
* Special scaling type of the skill value.
*/
value_usage: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 19 | 20 | 22 | 23 | 24 | 25;
/**
* Amount that the skill modifies the race mechanic in ten thousandths of
* whatever is the appropriate unit.
*/
value: number;
/**
* Selector for horses targeted by the ability.
*/
target: 1 | 2 | 4 | 7 | 9 | 10 | 11 | 18 | 19 | 20 | 21 | 22 | 23;
/**
* Argument value for the ability target, when appropriate.
*/
target_value?: number;
}
/**
* Skill groups.
* Skills in a skill group replace each other when purchased.
*
* As a special case, horsegen lists both unique skills and their inherited
* versions in the skill groups for both.
*/
export interface SkillGroup {
/**
* Skill group ID.
*/
skill_group: number;
/**
* Base skill in the skill group, if any.
* Either a common (white) skill or an Uma's own unique.
*
* Some skill groups, e.g. for G1 Averseness, have no base skill.
*/
skill1?: number;
/**
* First upgraded version of a skill, if any.
* A rare (gold) skill, double circle skill, or an inherited unique skill.
*/
skill2?: number;
/**
* Highest upgraded version of a skill, if any.
* Gold version of a skill with a double circle version.
*/
skill3?: number;
/**
* Negative (purple) version of a skill, if any.
*/
skill_bad?: number;
}
/**
* Sparks, or succession factors.
*/
export interface Spark {
/**
* Spark ID.
*/
spark_id: number;
/**
* Regional spark name.
*/
name: string;
/**
* Regional spark description.
*/
description: string;
/**
* Spark group.
* Different star levels of a given spark are different spark IDs but
* share a spark group.
*/
spark_group: number;
/**
* Spark rarity, or star level.
*/
rarity: 1 | 2 | 3;
/**
* Spark type.
* Roughly the spark color, with extra subdivisions for white sparks.
*/
type: 1 | 2 | 5 | 4 | 6 | 7 | 10 | 8 | 11 | 9 | 3;
/**
* Possible effects applied by the spark during inspiration.
* A random element is selected from this list according to unknown
* distributions, then all effects in that selection are applied.
*/
effects: SparkEffect[][];
}
/**
* Effects that a spark can apply.
*/
export interface SparkEffect {
target: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 21 | 22 | 23 | 24 | 31 | 32 | 33 | 34 | 41 | 51 | 61 | 62 | 63 | 64 | 65;
value1?: number;
value2: number;
}
/**
* Lobby conversation data.
*/
export interface Conversation {
/**
* Character who owns the conversation as a gallery entry.
*/
chara_id: number;
/**
* Number of the conversation within the character's conversation gallery.
*/
number: number;
/**
* Location ID of the conversation.
*/
location: 110 | 120 | 130 | 210 | 220 | 310 | 410 | 420 | 430 | 510 | 520 | 530;
/**
* English name of the location, for convenience.
*/
location_name: string;
/**
* First character in the conversation.
* Not necessarily equal to chara_id.
*/
chara_1: number;
/**
* Second character, if present.
*/
chara_2?: number;
/**
* Third character, if present.
*/
chara_3?: number;
/**
* Some unknown number in the game's local database.
*/
condition_type: 0 | 1 | 2 | 3 | 4;
}
+212
View File
@@ -0,0 +1,212 @@
/**
* Support card definitions.
*/
export interface SupportCard {
/**
* Support card ID.
*/
id: number;
/**
* Support card name including variant, e.g.
* `[The Brightest Star in Japan!] Special Week`.
*/
name: string;
/**
* ID of the card's representative character.
*/
chara_id: number;
/**
* Name of the card's character.
* May differ from the name of the `chara_id` character.
*/
chara_name: string;
/**
* Support card rarity.
*/
rarity: Rarity;
/**
* Support card specialty.
*/
specialty: Specialty;
/**
* Blanket support card type.
*/
type: Type;
/**
* Support card effects per five level increment.
*/
effects: [
Effect[],
Effect[],
Effect[],
Effect[],
Effect[],
Effect[],
Effect[],
Effect[],
Effect[],
Effect[],
Effect[],
Effect[],
];
/**
* Unique effect, for cards that have them.
*/
unique_effect?: UniqueEffect;
/**
* Hints that the card can yield.
*/
hints: Hint[];
/**
* Number of recreation events available with the card,
* not including recreation with the individual characters in a group.
*/
outings?: number;
}
/**
* Support card rarity levels.
*/
export enum Rarity {
R = 1,
SR = 2,
SSR = 3,
}
/**
* Support card specialty attribute.
*/
export enum Specialty {
None = 0, // for pals and groups
Speed = 101,
Power = 102,
Guts = 103,
Stamina = 105,
Wit = 106,
}
/**
* Support card types.
*/
export enum Type {
Normal = 1,
Pal = 2,
Group = 3,
}
/**
* Support card basic effects.
*/
export interface Effect {
/**
* Type of the effect.
*/
type: EffectType;
/**
* When positive, the amount of the effect.
* When -1, interpolate between the previous and next nonnegative values.
*/
value: number;
}
/**
* Support card unique effects.
*/
export interface UniqueEffect {
/**
* Name of the unique effect.
*/
name: string;
/**
* In-game description of the effect.
*/
description: string;
/**
* Card level at which the unique effect unlocks.
*/
card_level: number;
/**
* First type of the effect.
*/
type: EffectType;
/**
* Values parameterizing the first type.
*/
args: number[];
/**
* Second type of the effect, if applicable.
*/
type2?: EffectType;
/**
* Values parameterizing the second type.
*/
args2?: number[];
/**
* Mystery parameter that one day we might figure out.
*/
idle_mode_sub_rate: number;
}
/**
* Basic and unique effect types.
*/
export enum EffectType {
FriendshipBonus = 1,
MoodEffect = 2,
SpeedBonus = 3,
StaminaBonus = 4,
PowerBonus = 5,
GutsBonus = 6,
WitBonus = 7,
TrainingEffectiveness = 8,
InitialSpeed = 9,
InitialStamina = 10,
InitialPower = 11,
InitialGuts = 12,
InitialWit = 13,
InitialFriendship = 14,
RaceBonus = 15,
FanBonus = 16,
HintLevels = 17,
HintFrequency = 18,
SpecialtyPriority = 19,
MaxSpeed = 20,
MaxStamina = 21,
MaxPower = 22,
MaxGuts = 23,
MaxWit = 24,
EventRecovery = 25,
EventEffectiveness = 26,
FailureProtection = 27,
EnergyCostReduction = 28,
MinigameEffectiveness = 29,
SkillPointBonus = 30,
WitFriendshipRecovery = 31,
UniqueFriendshipThreshold = 101,
UniqueOffSpecialty = 102,
UniqueColorThresholdTrainingEffectiveness = 103,
UniqueFanScalingTrainingEffectiveness = 104,
UniqueColorInitialStats = 105,
UniqueRainbowStack = 106,
UniqueLowEnergyScaling = 107,
UniqueMaxEnergyScaling = 108,
UniqueTotalFriendship = 109,
UniqueCardCount = 110,
UniqueFacilityLevel = 111,
UniqueDisableFailure = 112,
UniqueFriendshipTrainingAdditionalEffect = 113,
}
/**
* Hint event bonuses.
*/
export interface Hint {
skill_id?: number;
speed?: number;
stamina?: number;
power?: number;
guts?: number;
wit?: number;
sp?: number;
}