mirror of
https://github.com/NanmiCoder/cc-haha.git
synced 2026-05-06 23:31:17 +08:00
Merge pull request #59 from xiaomingbusi/pr/companion-randomization
feat: fix companion randomization - support 18 species with rarity sy…
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
||||
RARITIES,
|
||||
RARITY_WEIGHTS,
|
||||
type Rarity,
|
||||
type Species,
|
||||
SPECIES,
|
||||
STAT_NAMES,
|
||||
type StatName,
|
||||
@@ -121,13 +122,35 @@ export function companionUserId(): string {
|
||||
return config.oauthAccount?.accountUuid ?? config.userID ?? 'anon'
|
||||
}
|
||||
|
||||
// Regenerate bones from userId, merge with stored soul. Bones never persist
|
||||
// so species renames and SPECIES-array edits can't break stored companions,
|
||||
// and editing config.companion can't fake a rarity.
|
||||
function storedAppearanceSeed(stored: {
|
||||
appearanceSeed?: string
|
||||
hatchedAt: number
|
||||
name: string
|
||||
personality: string
|
||||
}): string {
|
||||
return (
|
||||
stored.appearanceSeed ??
|
||||
`legacy:${stored.hatchedAt}:${stored.name}:${stored.personality}`
|
||||
)
|
||||
}
|
||||
|
||||
function applyStoredOverrides(
|
||||
bones: CompanionBones,
|
||||
stored: { speciesOverride?: Species },
|
||||
): CompanionBones {
|
||||
return stored.speciesOverride
|
||||
? { ...bones, species: stored.speciesOverride }
|
||||
: bones
|
||||
}
|
||||
|
||||
// Regenerate bones from the stored hatch seed, merge with the saved soul.
|
||||
// Old configs without a seed get a deterministic legacy fallback so they stop
|
||||
// changing every render without requiring users to re-hatch.
|
||||
export function getCompanion(): Companion | undefined {
|
||||
const stored = getGlobalConfig().companion
|
||||
if (!stored) return undefined
|
||||
const { bones } = roll(companionUserId())
|
||||
const { bones: rolledBones } = rollWithSeed(storedAppearanceSeed(stored))
|
||||
const bones = applyStoredOverrides(rolledBones, stored)
|
||||
// bones last so stale bones fields in old-format configs get overridden
|
||||
return { ...stored, ...bones }
|
||||
}
|
||||
|
||||
@@ -118,10 +118,13 @@ export type Companion = CompanionBones &
|
||||
hatchedAt: number
|
||||
}
|
||||
|
||||
// What actually persists in config. Bones are regenerated from hash(userId)
|
||||
// on every read so species renames don't break stored companions and users
|
||||
// can't edit their way to a legendary.
|
||||
export type StoredCompanion = CompanionSoul & { hatchedAt: number }
|
||||
// What actually persists in config. The hatch seed locks in a companion's
|
||||
// bones so the sprite/species stop changing between renders and restarts.
|
||||
export type StoredCompanion = CompanionSoul & {
|
||||
hatchedAt: number
|
||||
appearanceSeed?: string
|
||||
speciesOverride?: Species
|
||||
}
|
||||
|
||||
export const RARITY_WEIGHTS = {
|
||||
common: 60,
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { LocalJSXCommandCall } from '../../types/command.js'
|
||||
import {
|
||||
getCompanion,
|
||||
roll,
|
||||
rollWithSeed,
|
||||
companionUserId,
|
||||
} from '../../buddy/companion.js'
|
||||
import { renderSprite } from '../../buddy/sprites.js'
|
||||
@@ -73,8 +74,9 @@ function CompanionCard({
|
||||
)
|
||||
return
|
||||
}
|
||||
// Hatch a new companion with a generated name
|
||||
const { bones } = roll(companionUserId())
|
||||
// Hatch a new companion with a generated name and random seed
|
||||
const appearanceSeed = `hatch:${Date.now()}:${Math.random().toString(36).slice(2)}`
|
||||
const { bones } = rollWithSeed(appearanceSeed)
|
||||
const adjectives = [
|
||||
'Bright', 'Cozy', 'Swift', 'Calm', 'Wise', 'Bold',
|
||||
'Fuzzy', 'Lucky', 'Snappy', 'Quirky',
|
||||
@@ -90,6 +92,7 @@ function CompanionCard({
|
||||
name,
|
||||
personality: `A ${bones.rarity} ${bones.species} who loves debugging and hanging out.`,
|
||||
hatchedAt: Date.now(),
|
||||
appearanceSeed,
|
||||
}
|
||||
saveGlobalConfig(c => ({ ...c, companion: soul }))
|
||||
onDone(
|
||||
|
||||
Reference in New Issue
Block a user