This commit is contained in:
160
src/types/attributes.ts
Normal file
160
src/types/attributes.ts
Normal file
@@ -0,0 +1,160 @@
|
||||
import type {WorldType} from './core';
|
||||
|
||||
export const WORLD_ATTRIBUTE_SLOT_IDS = [
|
||||
'axis_a',
|
||||
'axis_b',
|
||||
'axis_c',
|
||||
'axis_d',
|
||||
'axis_e',
|
||||
'axis_f',
|
||||
] as const;
|
||||
|
||||
export type WorldAttributeSlotId = typeof WORLD_ATTRIBUTE_SLOT_IDS[number];
|
||||
export type LegacyAttributeKey = 'strength' | 'agility' | 'intelligence' | 'spirit';
|
||||
export type LegacyAttributeSet = Record<LegacyAttributeKey, number>;
|
||||
export type AttributeVector = Record<string, number>;
|
||||
|
||||
export interface WorldAttributeSlot {
|
||||
slotId: WorldAttributeSlotId;
|
||||
name: string;
|
||||
definition: string;
|
||||
positiveSignals: string[];
|
||||
negativeSignals: string[];
|
||||
combatUseText: string;
|
||||
socialUseText: string;
|
||||
explorationUseText: string;
|
||||
}
|
||||
|
||||
export interface WorldAttributeSchema {
|
||||
id: string;
|
||||
worldId: string;
|
||||
schemaVersion: number;
|
||||
generatedFrom: {
|
||||
worldType: WorldType;
|
||||
worldName: string;
|
||||
settingSummary: string;
|
||||
tone: string;
|
||||
conflictCore: string;
|
||||
};
|
||||
schemaName?: string;
|
||||
slots: WorldAttributeSlot[];
|
||||
}
|
||||
|
||||
export interface RoleAttributeEvidence {
|
||||
slotId: WorldAttributeSlotId;
|
||||
reason: string;
|
||||
}
|
||||
|
||||
export interface RoleAttributeProfile {
|
||||
schemaId: string;
|
||||
values: Record<string, number>;
|
||||
topTraits: string[];
|
||||
hiddenTraits?: string[];
|
||||
evidence: RoleAttributeEvidence[];
|
||||
}
|
||||
|
||||
export type RoleRelationStance =
|
||||
| 'hostile'
|
||||
| 'guarded'
|
||||
| 'neutral'
|
||||
| 'cooperative'
|
||||
| 'bonded';
|
||||
|
||||
export interface RoleRelationState {
|
||||
affinity: number;
|
||||
stance: RoleRelationStance;
|
||||
}
|
||||
|
||||
export interface RoleResourceProfile {
|
||||
maxHp: number;
|
||||
maxMana: number;
|
||||
}
|
||||
|
||||
export interface RoleResourceState extends RoleResourceProfile {
|
||||
hp: number;
|
||||
mana: number;
|
||||
cooldowns: Record<string, number>;
|
||||
}
|
||||
|
||||
export type RoleInteractionMode =
|
||||
| 'combat'
|
||||
| 'dialogue'
|
||||
| 'trade'
|
||||
| 'gift'
|
||||
| 'recruit'
|
||||
| 'explore'
|
||||
| 'leave';
|
||||
|
||||
export interface RoleBehaviorProfile {
|
||||
defaultInteractionModes?: RoleInteractionMode[];
|
||||
preferredActionIds?: string[];
|
||||
tabooSlots?: string[];
|
||||
}
|
||||
|
||||
export interface RoleNarrativeProfile {
|
||||
title?: string;
|
||||
identity?: string;
|
||||
backgroundSummary?: string;
|
||||
rumorText?: string[];
|
||||
faction?: string;
|
||||
}
|
||||
|
||||
export interface NarrativeRoleEntity {
|
||||
id: string;
|
||||
roleKind: 'player' | 'npc' | 'monster' | 'boss' | 'companion';
|
||||
worldAttributeSchemaId: string;
|
||||
attributeProfile: RoleAttributeProfile;
|
||||
relationState: RoleRelationState;
|
||||
resourceState: RoleResourceState;
|
||||
behaviorProfile: RoleBehaviorProfile;
|
||||
narrativeProfile: RoleNarrativeProfile;
|
||||
}
|
||||
|
||||
export interface RoleActionDefinition {
|
||||
id: string;
|
||||
name: string;
|
||||
intentVector: AttributeVector;
|
||||
resistVector?: AttributeVector;
|
||||
baseScore: number;
|
||||
category: 'combat' | 'dialogue' | 'trade' | 'gift' | 'recruit' | 'explore';
|
||||
}
|
||||
|
||||
export interface CombatActionAttributeProfile {
|
||||
intentVector: AttributeVector;
|
||||
resistVector?: AttributeVector;
|
||||
}
|
||||
|
||||
export interface DialogueActionProfile {
|
||||
actionId: string;
|
||||
intentVector: AttributeVector;
|
||||
relationBias: 'warm' | 'pressure' | 'truth' | 'distance';
|
||||
}
|
||||
|
||||
export interface ItemAttributeResonance {
|
||||
resonanceVector: AttributeVector;
|
||||
explanation?: string;
|
||||
}
|
||||
|
||||
export interface AttributeMigrationTrace {
|
||||
sourceCharacterId: string;
|
||||
schemaId: string;
|
||||
oldAttributes?: LegacyAttributeSet;
|
||||
inferredReasons: string[];
|
||||
fallbackUsed: boolean;
|
||||
}
|
||||
|
||||
export interface AttributeSchemaGenerationInput {
|
||||
worldType: WorldType;
|
||||
worldName: string;
|
||||
settingText: string;
|
||||
summary: string;
|
||||
tone: string;
|
||||
playerGoal: string;
|
||||
majorFactions: string[];
|
||||
coreConflicts: string[];
|
||||
}
|
||||
|
||||
export interface AttributeSchemaGenerationOutput {
|
||||
schemaName: string;
|
||||
slots: WorldAttributeSlot[];
|
||||
}
|
||||
23
src/types/build.ts
Normal file
23
src/types/build.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import type {AttributeVector} from './attributes';
|
||||
|
||||
export type BuildTagCategory = '流派' | '风格' | '资源' | '防御' | '元素' | '工艺';
|
||||
export type BuildBuffSourceType = 'skill' | 'item' | 'forge';
|
||||
|
||||
export interface BuildTagDefinition {
|
||||
id: string;
|
||||
label: string;
|
||||
category: BuildTagCategory;
|
||||
aliases: string[];
|
||||
description: string;
|
||||
attributeAffinity: AttributeVector;
|
||||
}
|
||||
|
||||
export interface TimedBuildBuff {
|
||||
id: string;
|
||||
sourceType: BuildBuffSourceType;
|
||||
sourceId: string;
|
||||
name: string;
|
||||
tags: string[];
|
||||
durationTurns: number;
|
||||
maxStacks?: number;
|
||||
}
|
||||
157
src/types/characters.ts
Normal file
157
src/types/characters.ts
Normal file
@@ -0,0 +1,157 @@
|
||||
import type {
|
||||
CombatActionAttributeProfile,
|
||||
LegacyAttributeSet,
|
||||
RoleAttributeProfile,
|
||||
RoleResourceProfile,
|
||||
} from './attributes';
|
||||
import type {TimedBuildBuff} from './build';
|
||||
import {
|
||||
AnimationState,
|
||||
type CharacterAnimationConfig,
|
||||
type CharacterGender,
|
||||
type CombatDelivery,
|
||||
type ConversationGuardStyle,
|
||||
type ConversationTruthStyle,
|
||||
type ConversationWarmStyle,
|
||||
type SkillEffectAnchor,
|
||||
type SkillEffectMotion,
|
||||
type SkillEffectPhase,
|
||||
type SkillStyle,
|
||||
WorldType,
|
||||
} from './core';
|
||||
import type { CustomWorldNpcVisual } from './customWorld';
|
||||
|
||||
export type SpriteSequenceDefinition =
|
||||
| {
|
||||
source: 'animation';
|
||||
animation: AnimationState;
|
||||
fps?: number;
|
||||
}
|
||||
| {
|
||||
source: 'asset';
|
||||
folder: string;
|
||||
prefix?: string;
|
||||
frames?: number;
|
||||
startFrame?: number;
|
||||
extension?: string;
|
||||
file?: string;
|
||||
fps?: number;
|
||||
};
|
||||
|
||||
export interface CharacterSkillEffectDefinition {
|
||||
phase: SkillEffectPhase;
|
||||
anchor: SkillEffectAnchor;
|
||||
motion?: SkillEffectMotion;
|
||||
sequence: SpriteSequenceDefinition;
|
||||
durationMs?: number;
|
||||
scale?: number;
|
||||
sizePx?: number;
|
||||
startOffsetX?: number;
|
||||
endOffsetX?: number;
|
||||
startYOffset?: number;
|
||||
endYOffset?: number;
|
||||
}
|
||||
|
||||
export interface CharacterSkillDefinition {
|
||||
id: string;
|
||||
name: string;
|
||||
animation: AnimationState;
|
||||
casterAnimation?: AnimationState;
|
||||
damage: number;
|
||||
manaCost: number;
|
||||
cooldownTurns: number;
|
||||
range: number;
|
||||
style: SkillStyle;
|
||||
delivery?: CombatDelivery;
|
||||
releaseDelayMs?: number;
|
||||
buildBuffs?: TimedBuildBuff[];
|
||||
effects?: CharacterSkillEffectDefinition[];
|
||||
attributeProfile?: CombatActionAttributeProfile | null;
|
||||
}
|
||||
|
||||
export interface CharacterAdventureOpening {
|
||||
reason: string;
|
||||
goal: string;
|
||||
monologue: string;
|
||||
surfaceHook?: string;
|
||||
immediateConcern?: string;
|
||||
guardedMotive?: string;
|
||||
}
|
||||
|
||||
export interface CharacterBackstoryChapter {
|
||||
id: string;
|
||||
title: string;
|
||||
affinityRequired: number;
|
||||
teaser: string;
|
||||
content: string;
|
||||
contextSnippet: string;
|
||||
}
|
||||
|
||||
export interface CharacterBackstoryRevealConfig {
|
||||
publicSummary: string;
|
||||
chapters: CharacterBackstoryChapter[];
|
||||
privateChatUnlockAffinity?: number;
|
||||
}
|
||||
|
||||
export interface CharacterConversationStyle {
|
||||
guardStyle: ConversationGuardStyle;
|
||||
warmStyle: ConversationWarmStyle;
|
||||
truthStyle: ConversationTruthStyle;
|
||||
}
|
||||
|
||||
export interface GeneratedCharacterVisualAsset {
|
||||
id: string;
|
||||
characterId: string;
|
||||
sourceMode: 'text-to-image' | 'image-to-image' | 'upload';
|
||||
promptText?: string;
|
||||
masterImagePath: string;
|
||||
previewImagePaths: string[];
|
||||
width: number;
|
||||
height: number;
|
||||
facing: 'right';
|
||||
locked: boolean;
|
||||
}
|
||||
|
||||
export interface GeneratedCharacterAnimationAsset {
|
||||
id: string;
|
||||
animationSetId: string;
|
||||
characterId: string;
|
||||
visualAssetId: string;
|
||||
action: string;
|
||||
frameCount: number;
|
||||
fps: number;
|
||||
loop: boolean;
|
||||
frameWidth: number;
|
||||
frameHeight: number;
|
||||
previewVideoPath?: string;
|
||||
spriteSheetPath?: string;
|
||||
framePaths: string[];
|
||||
}
|
||||
|
||||
export interface Character {
|
||||
id: string;
|
||||
name: string;
|
||||
title: string;
|
||||
gender?: CharacterGender;
|
||||
description: string;
|
||||
backstory: string;
|
||||
backstoryReveal?: CharacterBackstoryRevealConfig;
|
||||
avatar: string;
|
||||
portrait: string;
|
||||
assetFolder: string;
|
||||
assetVariant: string;
|
||||
generatedVisualAssetId?: string;
|
||||
generatedAnimationSetId?: string;
|
||||
groundOffsetY?: number;
|
||||
visual?: CustomWorldNpcVisual;
|
||||
animationMap?: Partial<Record<AnimationState, CharacterAnimationConfig>>;
|
||||
attributes: LegacyAttributeSet;
|
||||
attributeProfile?: RoleAttributeProfile;
|
||||
attributeProfiles?: Partial<Record<WorldType, RoleAttributeProfile>>;
|
||||
resourceProfile?: RoleResourceProfile;
|
||||
personality: string;
|
||||
combatTags?: string[];
|
||||
conversationStyle?: CharacterConversationStyle;
|
||||
skills: CharacterSkillDefinition[];
|
||||
adventureOpenings: Partial<Record<WorldType, CharacterAdventureOpening>>;
|
||||
}
|
||||
105
src/types/core.ts
Normal file
105
src/types/core.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
export enum WorldType {
|
||||
WUXIA = 'WUXIA',
|
||||
XIANXIA = 'XIANXIA',
|
||||
CUSTOM = 'CUSTOM',
|
||||
}
|
||||
|
||||
export type WorldTemplateType = Exclude<WorldType, WorldType.CUSTOM>;
|
||||
|
||||
export enum AnimationState {
|
||||
IDLE = 'idle',
|
||||
ACQUIRE = 'acquire',
|
||||
ATTACK = 'attack',
|
||||
RUN = 'run',
|
||||
JUMP = 'jump',
|
||||
DOUBLE_JUMP = 'double jump',
|
||||
JUMP_ATTACK = 'jump attack',
|
||||
DASH = 'dash',
|
||||
HURT = 'hurt',
|
||||
DIE = 'die',
|
||||
CLIMB = 'climb',
|
||||
SKILL1 = 'skill1',
|
||||
SKILL1_JUMP = 'skill1 jump',
|
||||
SKILL1_BULLET = 'skill1 bullet',
|
||||
SKILL1_BULLET_FX = 'skill1 bullet FX',
|
||||
SKILL2 = 'skill2',
|
||||
SKILL2_JUMP = 'skill2 jump',
|
||||
SKILL3 = 'skill3',
|
||||
SKILL3_JUMP = 'skill3 jump',
|
||||
SKILL3_BULLET = 'skill3 bullet',
|
||||
SKILL3_BULLET_FX = 'skill3 bullet FX',
|
||||
SKILL4 = 'skill4',
|
||||
WALL_SLIDE = 'Wall Slide',
|
||||
}
|
||||
|
||||
export interface CharacterAnimationConfig {
|
||||
folder: string;
|
||||
prefix: string;
|
||||
frames: number;
|
||||
startFrame?: number;
|
||||
extension?: string;
|
||||
file?: string;
|
||||
basePath?: string;
|
||||
frameWidth?: number;
|
||||
frameHeight?: number;
|
||||
fps?: number;
|
||||
loop?: boolean;
|
||||
previewVideoPath?: string;
|
||||
}
|
||||
|
||||
export type SkillStyle = 'burst' | 'steady' | 'mobility' | 'finisher' | 'projectile';
|
||||
export type PlayerStateMode = 'battle' | 'idle';
|
||||
export type FunctionCategory = 'battle' | 'escape' | 'idle' | 'recovery';
|
||||
export type ItemRarity = 'common' | 'uncommon' | 'rare' | 'epic' | 'legendary';
|
||||
export type EquipmentSlotId = 'weapon' | 'armor' | 'relic';
|
||||
export type CharacterGender = 'male' | 'female' | 'unknown';
|
||||
export type ItemWorldAffinity = 'neutral' | 'wuxia' | 'xianxia';
|
||||
export type ConversationGuardStyle = 'blunt' | 'wary' | 'evasive' | 'measured';
|
||||
export type ConversationWarmStyle = 'dry' | 'steady' | 'gentle' | 'teasing';
|
||||
export type ConversationTruthStyle = 'direct' | 'fragmented' | 'deflecting';
|
||||
export type NpcDisclosureStage = 'guarded' | 'partial' | 'honest' | 'deep';
|
||||
export type NpcWarmthStage = 'distant' | 'neutral' | 'cooperative' | 'warm';
|
||||
export type NpcAnswerMode = 'situational_only' | 'half_truth' | 'true_but_incomplete' | 'candid';
|
||||
export type ConversationSituation =
|
||||
| 'first_contact_cautious'
|
||||
| 'camp_first_contact'
|
||||
| 'camp_followup'
|
||||
| 'post_battle_breath'
|
||||
| 'shared_danger_coordination'
|
||||
| 'private_followup';
|
||||
export type ConversationPressure = 'high' | 'medium' | 'low';
|
||||
export type NpcFunctionType = 'trade' | 'fight' | 'spar' | 'help' | 'chat' | 'recruit' | 'gift' | 'quest';
|
||||
export type QuestObjectiveKind =
|
||||
| 'defeat_hostile_npc'
|
||||
| 'inspect_treasure'
|
||||
| 'spar_with_npc'
|
||||
| 'talk_to_npc'
|
||||
| 'reach_scene'
|
||||
| 'deliver_item';
|
||||
export type QuestStatus =
|
||||
| 'discovered'
|
||||
| 'active'
|
||||
| 'ready_to_turn_in'
|
||||
| 'completed'
|
||||
| 'turned_in'
|
||||
| 'failed'
|
||||
| 'expired';
|
||||
export type NpcInteractionAction =
|
||||
| NpcFunctionType
|
||||
| 'leave'
|
||||
| 'quest_accept'
|
||||
| 'quest_offer_abandon'
|
||||
| 'quest_offer_replace'
|
||||
| 'quest_offer_view'
|
||||
| 'quest_turn_in';
|
||||
export type TreasureInteractionAction = 'secure' | 'inspect' | 'leave';
|
||||
export type NpcBattleMode = 'fight' | 'spar';
|
||||
export type NpcBattleOutcome = 'fight_victory' | 'spar_complete';
|
||||
export type CombatDelivery = 'melee' | 'ranged';
|
||||
export type CombatActionMode = 'idle' | CombatDelivery;
|
||||
export type SkillEffectPhase = 'cast' | 'travel' | 'impact';
|
||||
export type SkillEffectAnchor = 'caster' | 'target';
|
||||
export type SkillEffectMotion = 'stationary' | 'projectile';
|
||||
export type HostileNpcRenderAnimation = 'idle' | 'move' | 'attack' | 'die';
|
||||
export type MonsterRenderAnimation = HostileNpcRenderAnimation;
|
||||
export type FacingDirection = 'left' | 'right';
|
||||
438
src/types/customWorld.ts
Normal file
438
src/types/customWorld.ts
Normal file
@@ -0,0 +1,438 @@
|
||||
import type { EightAnchorContent } from '../../packages/shared/src/contracts/customWorldAgent';
|
||||
import type {
|
||||
ItemAttributeResonance,
|
||||
RoleAttributeProfile,
|
||||
WorldAttributeSchema,
|
||||
} from './attributes';
|
||||
import type { CharacterBackstoryRevealConfig } from './characters';
|
||||
import {
|
||||
AnimationState,
|
||||
type CharacterAnimationConfig,
|
||||
type EquipmentSlotId,
|
||||
type ItemRarity,
|
||||
type WorldTemplateType,
|
||||
} from './core';
|
||||
import type {ItemStatProfile, ItemUseProfile} from './items';
|
||||
import type {
|
||||
ActorNarrativeProfile,
|
||||
KnowledgeFact,
|
||||
SceneNarrativeResidue,
|
||||
ThemePack,
|
||||
ThreadContract,
|
||||
WorldStoryGraph,
|
||||
} from './storyEngine';
|
||||
|
||||
export type CustomWorldCreatorInputMode = 'freeform' | 'card';
|
||||
export type CustomWorldGenerationMode = 'fast' | 'full';
|
||||
export type CustomWorldGenerationStatus = 'key_only' | 'complete';
|
||||
export type CustomWorldCoverSourceType = 'default' | 'uploaded' | 'generated';
|
||||
export type CustomWorldAgentUiState = {
|
||||
activeSessionId?: string | null;
|
||||
activeOperationId?: string | null;
|
||||
customWorldGenerationSource?: 'agent-draft-foundation' | null;
|
||||
ownerUserId?: string | null;
|
||||
};
|
||||
|
||||
export interface CustomWorldCoverProfile {
|
||||
sourceType: CustomWorldCoverSourceType;
|
||||
imageSrc?: string | null;
|
||||
characterRoleIds?: string[];
|
||||
}
|
||||
|
||||
export interface CustomWorldCoverCropRect {
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface CreatorFactionSeed {
|
||||
id: string;
|
||||
name: string;
|
||||
publicGoal: string;
|
||||
tension: string;
|
||||
notes: string;
|
||||
locked?: boolean;
|
||||
}
|
||||
|
||||
export interface CreatorCharacterSeed {
|
||||
id: string;
|
||||
name: string;
|
||||
role: string;
|
||||
publicMask: string;
|
||||
hiddenHook: string;
|
||||
relationToPlayer: string;
|
||||
notes: string;
|
||||
locked?: boolean;
|
||||
}
|
||||
|
||||
export interface CreatorLandmarkSeed {
|
||||
id: string;
|
||||
name: string;
|
||||
purpose: string;
|
||||
mood: string;
|
||||
secret: string;
|
||||
locked?: boolean;
|
||||
}
|
||||
|
||||
export interface ActorAnchor {
|
||||
id: string;
|
||||
name: string;
|
||||
summary: string;
|
||||
}
|
||||
|
||||
export interface LandmarkAnchor {
|
||||
id: string;
|
||||
name: string;
|
||||
summary: string;
|
||||
}
|
||||
|
||||
export interface CustomWorldCreatorIntent {
|
||||
sourceMode: CustomWorldCreatorInputMode;
|
||||
rawSettingText: string;
|
||||
worldHook: string;
|
||||
themeKeywords: string[];
|
||||
toneDirectives: string[];
|
||||
playerPremise: string;
|
||||
openingSituation: string;
|
||||
coreConflicts: string[];
|
||||
keyFactions: CreatorFactionSeed[];
|
||||
keyCharacters: CreatorCharacterSeed[];
|
||||
keyLandmarks: CreatorLandmarkSeed[];
|
||||
iconicElements: string[];
|
||||
forbiddenDirectives: string[];
|
||||
}
|
||||
|
||||
export interface CustomWorldAnchorPack {
|
||||
worldSummary: string;
|
||||
creatorIntentSummary: string;
|
||||
lockedAnchorIds: string[];
|
||||
keyConflictSummaries: string[];
|
||||
keyFactionSummaries: string[];
|
||||
keyCharacterAnchors: ActorAnchor[];
|
||||
keyLandmarkAnchors: LandmarkAnchor[];
|
||||
motifDirectives: string[];
|
||||
}
|
||||
|
||||
export interface CustomWorldLockState {
|
||||
worldLockedFields: string[];
|
||||
lockedCharacterIds: string[];
|
||||
lockedLandmarkIds: string[];
|
||||
lockedConflictIds: string[];
|
||||
lockedFactionIds: string[];
|
||||
}
|
||||
|
||||
export interface CustomWorldSemanticAnchor {
|
||||
genreSignals: string[];
|
||||
conflictForms: string[];
|
||||
institutionTypes: string[];
|
||||
tabooTypes: string[];
|
||||
carrierTypes: string[];
|
||||
forceSystemTypes: string[];
|
||||
atmosphereTags: string[];
|
||||
}
|
||||
|
||||
export interface CustomWorldRuleProfile {
|
||||
attributeSchema: WorldAttributeSchema;
|
||||
resourceLabels: {
|
||||
hp: string;
|
||||
mp: string;
|
||||
maxHp: string;
|
||||
maxMp: string;
|
||||
damage: string;
|
||||
guard: string;
|
||||
range: string;
|
||||
cooldown: string;
|
||||
manaCost: string;
|
||||
currency: string;
|
||||
};
|
||||
economyProfile: {
|
||||
initialCurrency: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface RoleArchetypeProfile {
|
||||
id: string;
|
||||
label: string;
|
||||
combatFocus: string;
|
||||
narrativeFunction: string;
|
||||
sourceRoleIds: string[];
|
||||
sourceTemplateCharacterIds: string[];
|
||||
tags: string[];
|
||||
}
|
||||
|
||||
export interface SceneArchetypeBucket {
|
||||
id: string;
|
||||
label: string;
|
||||
moodTags: string[];
|
||||
keywords: string[];
|
||||
referenceLandmarkIds: string[];
|
||||
}
|
||||
|
||||
export interface CreatureArchetypeProfile {
|
||||
id: string;
|
||||
label: string;
|
||||
threatStyle: string;
|
||||
keywords: string[];
|
||||
}
|
||||
|
||||
export interface CustomWorldReferenceProfile {
|
||||
roleArchetypes: RoleArchetypeProfile[];
|
||||
sceneBuckets: SceneArchetypeBucket[];
|
||||
creatureArchetypes: CreatureArchetypeProfile[];
|
||||
}
|
||||
|
||||
export interface CustomWorldExpressionProfile {
|
||||
themePack: ThemePack;
|
||||
presentationTone: string[];
|
||||
namingDirectives: string[];
|
||||
clueDirectives: string[];
|
||||
revealDirectives: string[];
|
||||
}
|
||||
|
||||
export interface CustomWorldCompatibilityProfile {
|
||||
compatibilityTemplateWorldType?: WorldTemplateType | null;
|
||||
legacyTemplateWorldType?: WorldTemplateType | null;
|
||||
migrationVersion: string;
|
||||
}
|
||||
|
||||
export interface CustomWorldOwnedSettingLayers {
|
||||
semanticAnchor: CustomWorldSemanticAnchor;
|
||||
ruleProfile: CustomWorldRuleProfile;
|
||||
expressionProfile: CustomWorldExpressionProfile;
|
||||
referenceProfile: CustomWorldReferenceProfile;
|
||||
compatibilityProfile?: CustomWorldCompatibilityProfile | null;
|
||||
}
|
||||
|
||||
export interface CustomWorldRoleSkill {
|
||||
id: string;
|
||||
name: string;
|
||||
summary: string;
|
||||
style: string;
|
||||
actionPromptText?: string;
|
||||
actionPreviewConfig?: CharacterAnimationConfig;
|
||||
}
|
||||
|
||||
export interface CustomWorldRoleInitialItem {
|
||||
id: string;
|
||||
name: string;
|
||||
category: string;
|
||||
quantity: number;
|
||||
rarity: ItemRarity;
|
||||
description: string;
|
||||
tags: string[];
|
||||
iconSrc?: string;
|
||||
}
|
||||
|
||||
export interface CustomWorldRoleRelation {
|
||||
id: string;
|
||||
targetRoleId: string;
|
||||
summary: string;
|
||||
}
|
||||
|
||||
export interface CustomWorldRoleProfile {
|
||||
id: string;
|
||||
name: string;
|
||||
title: string;
|
||||
role: string;
|
||||
description: string;
|
||||
visualDescription?: string;
|
||||
actionDescription?: string;
|
||||
sceneVisualDescription?: string;
|
||||
backstory: string;
|
||||
personality: string;
|
||||
motivation: string;
|
||||
combatStyle: string;
|
||||
initialAffinity: number;
|
||||
relationshipHooks: string[];
|
||||
relations?: CustomWorldRoleRelation[];
|
||||
tags: string[];
|
||||
backstoryReveal: CharacterBackstoryRevealConfig;
|
||||
skills: CustomWorldRoleSkill[];
|
||||
initialItems: CustomWorldRoleInitialItem[];
|
||||
imageSrc?: string;
|
||||
generatedVisualAssetId?: string;
|
||||
generatedAnimationSetId?: string;
|
||||
animationMap?: Partial<Record<AnimationState, CharacterAnimationConfig>>;
|
||||
attributeProfile?: RoleAttributeProfile;
|
||||
narrativeProfile?: ActorNarrativeProfile | null;
|
||||
}
|
||||
|
||||
export type CustomWorldNpcVisualRace = 'human' | 'elf' | 'orc' | 'goblin';
|
||||
export type CustomWorldNpcVisualGearType = 'cloth' | 'leather' | 'metal' | 'melee' | 'magic' | 'ranged';
|
||||
|
||||
export interface CustomWorldNpcVisualGear {
|
||||
type: CustomWorldNpcVisualGearType;
|
||||
file: string;
|
||||
frameIndex: number;
|
||||
}
|
||||
|
||||
export interface CustomWorldNpcVisual {
|
||||
race: CustomWorldNpcVisualRace;
|
||||
bodyColor: string;
|
||||
headIndex: number;
|
||||
hairColorIndex: number;
|
||||
hairStyleFrame: number;
|
||||
facialHairEnabled: boolean;
|
||||
facialHairColorIndex: number;
|
||||
facialHairStyleFrame: number;
|
||||
headgear?: CustomWorldNpcVisualGear | null;
|
||||
mainHand?: CustomWorldNpcVisualGear | null;
|
||||
offHand?: CustomWorldNpcVisualGear | null;
|
||||
}
|
||||
|
||||
export interface CustomWorldPlayableNpc extends CustomWorldRoleProfile {}
|
||||
|
||||
export interface CustomWorldNpc extends CustomWorldRoleProfile {
|
||||
visual?: CustomWorldNpcVisual;
|
||||
}
|
||||
|
||||
export interface CustomWorldItem {
|
||||
id: string;
|
||||
name: string;
|
||||
category: string;
|
||||
rarity: ItemRarity;
|
||||
description: string;
|
||||
tags: string[];
|
||||
iconSrc?: string;
|
||||
sourcePath?: string;
|
||||
origin?: 'generated' | 'catalog';
|
||||
equipmentSlotId?: EquipmentSlotId | null;
|
||||
statProfile?: ItemStatProfile | null;
|
||||
useProfile?: ItemUseProfile | null;
|
||||
value?: number;
|
||||
attributeResonance?: ItemAttributeResonance | null;
|
||||
}
|
||||
|
||||
export type CustomWorldSceneRelativePosition =
|
||||
| 'forward'
|
||||
| 'back'
|
||||
| 'left'
|
||||
| 'right'
|
||||
| 'north'
|
||||
| 'south'
|
||||
| 'east'
|
||||
| 'west'
|
||||
| 'up'
|
||||
| 'down'
|
||||
| 'inside'
|
||||
| 'outside'
|
||||
| 'portal';
|
||||
|
||||
export interface CustomWorldSceneConnection {
|
||||
targetLandmarkId: string;
|
||||
relativePosition: CustomWorldSceneRelativePosition;
|
||||
summary: string;
|
||||
}
|
||||
|
||||
export type SceneActStage =
|
||||
| 'opening'
|
||||
| 'expansion'
|
||||
| 'turning_point'
|
||||
| 'climax'
|
||||
| 'aftermath';
|
||||
|
||||
export type SceneActAdvanceRule =
|
||||
| 'after_primary_contact'
|
||||
| 'after_active_step_complete'
|
||||
| 'after_chapter_resolution';
|
||||
|
||||
export interface SceneActBlueprint {
|
||||
id: string;
|
||||
sceneId: string;
|
||||
title: string;
|
||||
summary: string;
|
||||
stageCoverage: SceneActStage[];
|
||||
backgroundPromptText?: string | null;
|
||||
backgroundImageSrc?: string | null;
|
||||
backgroundAssetId?: string | null;
|
||||
encounterNpcIds: string[];
|
||||
primaryNpcId: string;
|
||||
/** 当前幕对面的角色,草稿阶段默认与 primaryNpcId 保持一致。 */
|
||||
oppositeNpcId: string;
|
||||
/** 当前幕发生的事件描述,需强绑定对面角色与场景主线压力。 */
|
||||
eventDescription: string;
|
||||
linkedThreadIds: string[];
|
||||
advanceRule: SceneActAdvanceRule;
|
||||
actGoal: string;
|
||||
transitionHook: string;
|
||||
}
|
||||
|
||||
export interface SceneChapterBlueprint {
|
||||
id: string;
|
||||
sceneId: string;
|
||||
title: string;
|
||||
summary: string;
|
||||
/** 首次进入该场景时生成章节任务所需的核心上下文。 */
|
||||
sceneTaskDescription: string;
|
||||
linkedThreadIds: string[];
|
||||
linkedLandmarkIds: string[];
|
||||
acts: SceneActBlueprint[];
|
||||
}
|
||||
|
||||
export interface CustomWorldCampScene {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
visualDescription?: string;
|
||||
imageSrc?: string;
|
||||
sceneNpcIds: string[];
|
||||
connections: CustomWorldSceneConnection[];
|
||||
narrativeResidues?: SceneNarrativeResidue[] | null;
|
||||
}
|
||||
|
||||
export interface CustomWorldLandmark {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
visualDescription?: string;
|
||||
imageSrc?: string;
|
||||
sceneNpcIds: string[];
|
||||
connections: CustomWorldSceneConnection[];
|
||||
narrativeResidues?: SceneNarrativeResidue[] | null;
|
||||
}
|
||||
|
||||
export interface CustomWorldProfile {
|
||||
id: string;
|
||||
settingText: string;
|
||||
name: string;
|
||||
subtitle: string;
|
||||
summary: string;
|
||||
tone: string;
|
||||
playerGoal: string;
|
||||
/**
|
||||
* 发布门槛直接读取的世界一句话钩子。
|
||||
* Agent 结果页回写 session 时需要保留该字段,避免只剩 UI 归一化字段导致后端误判缺失。
|
||||
*/
|
||||
worldHook?: string | null;
|
||||
/**
|
||||
* 发布门槛直接读取的玩家身份与切入前提。
|
||||
* 即使 creatorIntent / anchorContent 中已有结构化信息,也要保留顶层字段作为 SpacetimeDB 发布快照的稳定兼容槽位。
|
||||
*/
|
||||
playerPremise?: string | null;
|
||||
cover?: CustomWorldCoverProfile | null;
|
||||
templateWorldType: WorldTemplateType;
|
||||
compatibilityTemplateWorldType?: WorldTemplateType | null;
|
||||
majorFactions: string[];
|
||||
coreConflicts: string[];
|
||||
attributeSchema: WorldAttributeSchema;
|
||||
playableNpcs: CustomWorldPlayableNpc[];
|
||||
storyNpcs: CustomWorldNpc[];
|
||||
items: CustomWorldItem[];
|
||||
camp?: CustomWorldCampScene | null;
|
||||
landmarks: CustomWorldLandmark[];
|
||||
themePack?: ThemePack | null;
|
||||
storyGraph?: WorldStoryGraph | null;
|
||||
knowledgeFacts?: KnowledgeFact[] | null;
|
||||
threadContracts?: ThreadContract[] | null;
|
||||
sceneChapterBlueprints?: SceneChapterBlueprint[] | null;
|
||||
anchorContent?: EightAnchorContent | null;
|
||||
creatorIntent?: CustomWorldCreatorIntent | null;
|
||||
anchorPack?: CustomWorldAnchorPack | null;
|
||||
lockState?: CustomWorldLockState | null;
|
||||
ownedSettingLayers?: CustomWorldOwnedSettingLayers | null;
|
||||
generationMode?: CustomWorldGenerationMode | null;
|
||||
generationStatus?: CustomWorldGenerationStatus | null;
|
||||
scenarioPackId?: string | null;
|
||||
campaignPackId?: string | null;
|
||||
}
|
||||
105
src/types/game.ts
Normal file
105
src/types/game.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import type { TimedBuildBuff } from './build';
|
||||
import type { Character } from './characters';
|
||||
import {
|
||||
AnimationState,
|
||||
type CombatActionMode,
|
||||
type NpcBattleMode,
|
||||
type NpcBattleOutcome,
|
||||
WorldType,
|
||||
} from './core';
|
||||
import type { CustomWorldProfile } from './customWorld';
|
||||
import type { EquipmentLoadout, InventoryItem } from './items';
|
||||
import type {
|
||||
CombatVisualEffect,
|
||||
CompanionState,
|
||||
Encounter,
|
||||
NpcPersistentState,
|
||||
SceneEncounterResult,
|
||||
SceneHostileNpc,
|
||||
ScenePresetInfo,
|
||||
} from './scene';
|
||||
import type { CharacterChatRecord, QuestLogEntry, StoryMoment } from './story';
|
||||
import type {
|
||||
CampaignState,
|
||||
ChapterState,
|
||||
StoryEngineMemoryState,
|
||||
} from './storyEngine';
|
||||
|
||||
export interface GameRuntimeStats {
|
||||
playTimeMs: number;
|
||||
lastPlayTickAt: string | null;
|
||||
hostileNpcsDefeated: number;
|
||||
questsAccepted: number;
|
||||
itemsUsed: number;
|
||||
scenesTraveled: number;
|
||||
}
|
||||
|
||||
export type PlayerProgressionGrantSource = 'quest' | 'hostile_npc';
|
||||
|
||||
export interface PlayerProgressionState {
|
||||
level: number;
|
||||
currentLevelXp: number;
|
||||
totalXp: number;
|
||||
xpToNextLevel: number;
|
||||
pendingLevelUps?: number;
|
||||
lastGrantedSource?: PlayerProgressionGrantSource | null;
|
||||
}
|
||||
|
||||
export interface GameState {
|
||||
worldType: WorldType | null;
|
||||
customWorldProfile: CustomWorldProfile | null;
|
||||
playerCharacter: Character | null;
|
||||
runtimeSessionId?: string | null;
|
||||
runtimeActionVersion?: number;
|
||||
runtimeStats: GameRuntimeStats;
|
||||
playerProgression?: PlayerProgressionState | null;
|
||||
currentScene: string;
|
||||
storyHistory: StoryMoment[];
|
||||
storyEngineMemory?: StoryEngineMemoryState;
|
||||
chapterState?: ChapterState | null;
|
||||
campaignState?: CampaignState | null;
|
||||
activeScenarioPackId?: string | null;
|
||||
activeCampaignPackId?: string | null;
|
||||
characterChats: Record<string, CharacterChatRecord>;
|
||||
ambientIdleMode?: 'observe_signs';
|
||||
lastObserveSignsSceneId?: string | null;
|
||||
lastObserveSignsReport?: string | null;
|
||||
animationState: AnimationState;
|
||||
currentEncounter: Encounter | null;
|
||||
npcInteractionActive: boolean;
|
||||
currentScenePreset: ScenePresetInfo | null;
|
||||
sceneHostileNpcs: SceneHostileNpc[];
|
||||
playerX: number;
|
||||
playerOffsetY: number;
|
||||
playerFacing: 'left' | 'right';
|
||||
playerActionMode: CombatActionMode;
|
||||
scrollWorld: boolean;
|
||||
inBattle: boolean;
|
||||
playerHp: number;
|
||||
playerMaxHp: number;
|
||||
playerMana: number;
|
||||
playerMaxMana: number;
|
||||
playerSkillCooldowns: Record<string, number>;
|
||||
activeBuildBuffs?: TimedBuildBuff[];
|
||||
activeCombatEffects: CombatVisualEffect[];
|
||||
playerCurrency: number;
|
||||
playerInventory: InventoryItem[];
|
||||
playerEquipment: EquipmentLoadout;
|
||||
npcStates: Record<string, NpcPersistentState>;
|
||||
quests: QuestLogEntry[];
|
||||
roster: CompanionState[];
|
||||
companions: CompanionState[];
|
||||
currentBattleNpcId: string | null;
|
||||
currentNpcBattleMode: NpcBattleMode | null;
|
||||
currentNpcBattleOutcome: NpcBattleOutcome | null;
|
||||
sparReturnEncounter: Encounter | null;
|
||||
sparPlayerHpBefore: number | null;
|
||||
sparPlayerMaxHpBefore: number | null;
|
||||
sparStoryHistoryBefore: StoryMoment[] | null;
|
||||
}
|
||||
|
||||
export interface AIResponse {
|
||||
storyText: string;
|
||||
options: StoryMoment['options'];
|
||||
encounter?: SceneEncounterResult;
|
||||
}
|
||||
110
src/types/items.ts
Normal file
110
src/types/items.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import type {AttributeVector, ItemAttributeResonance} from './attributes';
|
||||
import type {TimedBuildBuff} from './build';
|
||||
import {
|
||||
type EquipmentSlotId,
|
||||
type ItemRarity,
|
||||
type ItemWorldAffinity,
|
||||
WorldType,
|
||||
} from './core';
|
||||
import type {RuntimeItemMetadata} from './runtimeItem';
|
||||
|
||||
export interface InventoryItem {
|
||||
id: string;
|
||||
category: string;
|
||||
name: string;
|
||||
quantity: number;
|
||||
rarity: ItemRarity;
|
||||
tags: string[];
|
||||
catalogId?: string;
|
||||
iconSrc?: string;
|
||||
description?: string;
|
||||
worldAffinity?: ItemWorldAffinity;
|
||||
equipmentSlotId?: EquipmentSlotId | null;
|
||||
worldProfiles?: Partial<Record<WorldType, ItemWorldProfile>>;
|
||||
statProfile?: ItemStatProfile | null;
|
||||
useProfile?: ItemUseProfile | null;
|
||||
buildProfile?: ItemBuildProfile | null;
|
||||
value?: number;
|
||||
attributeResonance?: ItemAttributeResonance | null;
|
||||
runtimeMetadata?: RuntimeItemMetadata | null;
|
||||
}
|
||||
|
||||
export interface MonsterLootEntry {
|
||||
id: string;
|
||||
item: InventoryItem;
|
||||
dropRate: number;
|
||||
}
|
||||
|
||||
export interface ItemCatalogEntry {
|
||||
id: string;
|
||||
sourcePath: string;
|
||||
iconSrc: string;
|
||||
name: string;
|
||||
category: string;
|
||||
rarity: ItemRarity;
|
||||
tags: string[];
|
||||
description: string;
|
||||
worldAffinity: ItemWorldAffinity;
|
||||
equipmentSlotId?: EquipmentSlotId | null;
|
||||
worldProfiles?: Partial<Record<WorldType, ItemWorldProfile>>;
|
||||
statProfile?: ItemStatProfile | null;
|
||||
useProfile?: ItemUseProfile | null;
|
||||
buildProfile?: ItemBuildProfile | null;
|
||||
value?: number;
|
||||
attributeResonance?: ItemAttributeResonance | null;
|
||||
runtimeMetadata?: RuntimeItemMetadata | null;
|
||||
}
|
||||
|
||||
export interface ItemCatalogOverride {
|
||||
name?: string;
|
||||
category?: string;
|
||||
rarity?: ItemRarity;
|
||||
tags?: string[];
|
||||
description?: string;
|
||||
worldAffinity?: ItemWorldAffinity;
|
||||
equipmentSlotId?: EquipmentSlotId | null;
|
||||
worldProfiles?: Partial<Record<WorldType, ItemWorldProfile>>;
|
||||
statProfile?: ItemStatProfile | null;
|
||||
useProfile?: ItemUseProfile | null;
|
||||
buildProfile?: ItemBuildProfile | null;
|
||||
value?: number;
|
||||
attributeResonance?: ItemAttributeResonance | null;
|
||||
runtimeMetadata?: RuntimeItemMetadata | null;
|
||||
}
|
||||
|
||||
export interface ItemWorldProfile {
|
||||
name: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export interface ItemStatProfile {
|
||||
maxHpBonus?: number;
|
||||
maxManaBonus?: number;
|
||||
outgoingDamageBonus?: number;
|
||||
incomingDamageMultiplier?: number;
|
||||
}
|
||||
|
||||
export interface ItemUseProfile {
|
||||
hpRestore?: number;
|
||||
manaRestore?: number;
|
||||
cooldownReduction?: number;
|
||||
buildBuffs?: TimedBuildBuff[];
|
||||
}
|
||||
|
||||
export interface ItemBuildProfile {
|
||||
role: string;
|
||||
tags: string[];
|
||||
setId?: string;
|
||||
setName?: string;
|
||||
pieceName?: string;
|
||||
synergy?: string[];
|
||||
craftTags?: string[];
|
||||
forgeRank?: number;
|
||||
resonanceVector?: AttributeVector;
|
||||
}
|
||||
|
||||
export interface EquipmentLoadout {
|
||||
weapon: InventoryItem | null;
|
||||
armor: InventoryItem | null;
|
||||
relic: InventoryItem | null;
|
||||
}
|
||||
1
src/types/navigation.ts
Normal file
1
src/types/navigation.ts
Normal file
@@ -0,0 +1 @@
|
||||
export type BottomTab = 'character' | 'adventure' | 'inventory';
|
||||
122
src/types/runtimeItem.ts
Normal file
122
src/types/runtimeItem.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
import type {WorldType} from './core';
|
||||
import type {CustomWorldProfile} from './customWorld';
|
||||
import type {InventoryItem} from './items';
|
||||
import type {Encounter, NpcPersistentState, ScenePresetInfo} from './scene';
|
||||
import type {
|
||||
ActorNarrativeProfile,
|
||||
CarrierStoryFingerprint,
|
||||
} from './storyEngine';
|
||||
|
||||
export type RuntimeItemGenerationChannel =
|
||||
| 'treasure'
|
||||
| 'npc_trade'
|
||||
| 'npc_reward'
|
||||
| 'monster_drop'
|
||||
| 'quest_reward'
|
||||
| 'discovery';
|
||||
|
||||
export type RuntimeItemOrigin = 'catalog' | 'procedural' | 'ai_compiled';
|
||||
|
||||
export type RuntimeItemKind = 'equipment' | 'consumable' | 'material' | 'relic' | 'quest';
|
||||
export type RuntimeItemPermanence = 'permanent' | 'timed' | 'resource';
|
||||
export type RuntimeNarrativeWeight = 'light' | 'medium' | 'heavy';
|
||||
export type RuntimeItemPlanSlot = 'primary' | 'secondary' | 'support';
|
||||
|
||||
export type RuntimeRelationAnchor =
|
||||
| {type: 'npc'; npcId?: string; npcName: string; roleText?: string}
|
||||
| {type: 'scene'; sceneId?: string; sceneName: string}
|
||||
| {type: 'landmark'; landmarkName: string}
|
||||
| {type: 'monster'; monsterId?: string; monsterName: string}
|
||||
| {type: 'faction'; factionName: string}
|
||||
| {type: 'quest'; questId?: string; questName: string};
|
||||
|
||||
export interface RuntimeItemMetadata {
|
||||
origin: RuntimeItemOrigin;
|
||||
generationChannel: RuntimeItemGenerationChannel;
|
||||
seedKey: string;
|
||||
relationAnchor?: RuntimeRelationAnchor;
|
||||
sourceReason: string;
|
||||
recentEventHook?: string;
|
||||
storyFingerprint?: CarrierStoryFingerprint | null;
|
||||
}
|
||||
|
||||
export interface RuntimeItemGenerationContext {
|
||||
worldType: WorldType | null;
|
||||
customWorldProfile: CustomWorldProfile | null;
|
||||
sceneId: string | null;
|
||||
sceneName: string | null;
|
||||
sceneDescription: string | null;
|
||||
sceneTags: string[];
|
||||
treasureHints: string[];
|
||||
encounter: Encounter | null;
|
||||
encounterNpcId: string | null;
|
||||
encounterNpcName: string | null;
|
||||
encounterContextText: string | null;
|
||||
relatedNpcState: NpcPersistentState | null;
|
||||
relatedNpcNarrativeProfile?: ActorNarrativeProfile | null;
|
||||
relatedScene: Pick<ScenePresetInfo, 'id' | 'name' | 'description' | 'treasureHints'> | null;
|
||||
recentStorySummary: string;
|
||||
recentActions: string[];
|
||||
activeThreadIds?: string[] | null;
|
||||
playerCharacterId: string;
|
||||
playerBuildTags: string[];
|
||||
playerBuildGaps: string[];
|
||||
playerEquipmentTags: string[];
|
||||
generationChannel: RuntimeItemGenerationChannel;
|
||||
}
|
||||
|
||||
export interface RuntimeItemPlan {
|
||||
slot: RuntimeItemPlanSlot;
|
||||
itemKind: RuntimeItemKind;
|
||||
permanence: RuntimeItemPermanence;
|
||||
narrativeWeight: RuntimeNarrativeWeight;
|
||||
targetBuildDirection: string[];
|
||||
relationAnchor: RuntimeRelationAnchor;
|
||||
}
|
||||
|
||||
export interface RuntimeItemAiPromptInput {
|
||||
worldSummary: string;
|
||||
sceneSummary: string;
|
||||
encounterSummary: string;
|
||||
relatedNpcSummary: string;
|
||||
recentStorySummary: string;
|
||||
activeThreadSummary?: string;
|
||||
generationChannel: RuntimeItemGenerationChannel;
|
||||
playerBuildDirection: string[];
|
||||
playerBuildGaps: string[];
|
||||
desiredItemKind: string;
|
||||
permanence: string;
|
||||
}
|
||||
|
||||
export interface RuntimeItemAiIntent {
|
||||
shortNameSeed: string;
|
||||
sourcePhrase: string;
|
||||
reasonToAppear: string;
|
||||
relationHooks: string[];
|
||||
desiredBuildTags: string[];
|
||||
desiredFunctionalBias: Array<'heal' | 'mana' | 'cooldown' | 'guard' | 'damage'>;
|
||||
tone: 'grim' | 'mysterious' | 'martial' | 'ritual' | 'survival';
|
||||
visibleClue?: string;
|
||||
witnessMark?: string;
|
||||
unfinishedBusiness?: string;
|
||||
hiddenHook?: string;
|
||||
reactionHooks?: string[];
|
||||
namingPattern?: string;
|
||||
}
|
||||
|
||||
export interface RuntimeItemCompileBudget {
|
||||
rarity: InventoryItem['rarity'];
|
||||
buildTagLimit: number;
|
||||
timedBuffTagLimit: number;
|
||||
timedBuffDuration: number;
|
||||
statBudgetTier: number;
|
||||
}
|
||||
|
||||
export interface DirectedRuntimeReward {
|
||||
primaryItem?: InventoryItem | null;
|
||||
supportItems: InventoryItem[];
|
||||
hp?: number;
|
||||
mana?: number;
|
||||
currency?: number;
|
||||
storyHint?: string;
|
||||
}
|
||||
259
src/types/scene.ts
Normal file
259
src/types/scene.ts
Normal file
@@ -0,0 +1,259 @@
|
||||
import type {
|
||||
RoleActionDefinition,
|
||||
RoleAttributeProfile,
|
||||
RoleRelationState,
|
||||
} from './attributes';
|
||||
import type {
|
||||
Character,
|
||||
CharacterBackstoryRevealConfig,
|
||||
} from './characters';
|
||||
import {
|
||||
AnimationState,
|
||||
type CharacterGender,
|
||||
type CombatActionMode,
|
||||
type CombatDelivery,
|
||||
type FacingDirection,
|
||||
type HostileNpcRenderAnimation,
|
||||
type NpcFunctionType,
|
||||
} from './core';
|
||||
import type {
|
||||
CustomWorldNpcVisual,
|
||||
CustomWorldRoleInitialItem,
|
||||
CustomWorldRoleSkill,
|
||||
CustomWorldSceneRelativePosition,
|
||||
} from './customWorld';
|
||||
import type {InventoryItem} from './items';
|
||||
import type {
|
||||
ActorNarrativeProfile,
|
||||
CompanionStanceProfile,
|
||||
SceneNarrativeResidue,
|
||||
} from './storyEngine';
|
||||
|
||||
export interface NpcPersistentState {
|
||||
affinity: number;
|
||||
relationState?: RoleRelationState;
|
||||
helpUsed: boolean;
|
||||
chattedCount: number;
|
||||
giftsGiven: number;
|
||||
inventory: InventoryItem[];
|
||||
tradeStockSignature?: string | null;
|
||||
recruited: boolean;
|
||||
revealedFacts?: string[];
|
||||
knownAttributeRumors?: string[];
|
||||
firstMeaningfulContactResolved?: boolean;
|
||||
seenBackstoryChapterIds?: string[];
|
||||
stanceProfile?: CompanionStanceProfile;
|
||||
}
|
||||
|
||||
export interface CompanionState {
|
||||
npcId: string;
|
||||
characterId: string;
|
||||
joinedAtAffinity: number;
|
||||
hp: number;
|
||||
maxHp: number;
|
||||
mana: number;
|
||||
maxMana: number;
|
||||
skillCooldowns: Record<string, number>;
|
||||
animationState?: AnimationState;
|
||||
actionMode?: CombatActionMode;
|
||||
offsetX?: number;
|
||||
offsetY?: number;
|
||||
transitionMs?: number;
|
||||
}
|
||||
|
||||
export interface CompanionRenderState {
|
||||
npcId: string;
|
||||
character: Character;
|
||||
hp: number;
|
||||
maxHp: number;
|
||||
mana: number;
|
||||
maxMana: number;
|
||||
skillCooldowns: Record<string, number>;
|
||||
animationState: AnimationState;
|
||||
actionMode?: CombatActionMode;
|
||||
slot: 'upper' | 'lower';
|
||||
facing?: FacingDirection;
|
||||
entryOffsetX?: number;
|
||||
entryOffsetY?: number;
|
||||
transitionMs?: number;
|
||||
recruitToken?: number;
|
||||
}
|
||||
|
||||
export interface Encounter {
|
||||
id?: string;
|
||||
kind?: 'npc' | 'treasure';
|
||||
npcName: string;
|
||||
npcDescription: string;
|
||||
npcAvatar: string;
|
||||
context: string;
|
||||
gender?: CharacterGender;
|
||||
specialBehavior?: 'initial_companion' | 'camp_companion';
|
||||
xMeters?: number;
|
||||
characterId?: string;
|
||||
monsterPresetId?: string;
|
||||
initialAffinity?: number;
|
||||
hostile?: boolean;
|
||||
attributeProfile?: RoleAttributeProfile;
|
||||
title?: string;
|
||||
backstory?: string;
|
||||
personality?: string;
|
||||
motivation?: string;
|
||||
combatStyle?: string;
|
||||
relationshipHooks?: string[];
|
||||
tags?: string[];
|
||||
backstoryReveal?: CharacterBackstoryRevealConfig;
|
||||
skills?: CustomWorldRoleSkill[];
|
||||
initialItems?: CustomWorldRoleInitialItem[];
|
||||
imageSrc?: string;
|
||||
visual?: CustomWorldNpcVisual;
|
||||
narrativeProfile?: ActorNarrativeProfile | null;
|
||||
levelProfile?: EntityLevelProfile;
|
||||
experienceReward?: number;
|
||||
}
|
||||
|
||||
export type ProgressionRole =
|
||||
| 'guide'
|
||||
| 'ambient'
|
||||
| 'support'
|
||||
| 'hostile_standard'
|
||||
| 'hostile_elite'
|
||||
| 'hostile_boss'
|
||||
| 'rival';
|
||||
|
||||
export interface EntityLevelProfile {
|
||||
level: number;
|
||||
referenceStrength: number;
|
||||
chapterId?: string | null;
|
||||
chapterIndex?: number | null;
|
||||
progressionRole: ProgressionRole;
|
||||
source: 'chapter_auto' | 'preset_override' | 'manual';
|
||||
}
|
||||
|
||||
export interface SceneHostileNpc {
|
||||
id: string;
|
||||
name: string;
|
||||
action: string;
|
||||
description: string;
|
||||
animation: HostileNpcRenderAnimation;
|
||||
xMeters: number;
|
||||
yOffset: number;
|
||||
facing: FacingDirection;
|
||||
attackRange: number;
|
||||
speed: number;
|
||||
hp: number;
|
||||
maxHp: number;
|
||||
renderKind?: 'npc';
|
||||
encounter?: Encounter;
|
||||
characterAnimation?: AnimationState;
|
||||
combatMode?: CombatDelivery;
|
||||
combatTags?: string[];
|
||||
attributeProfile?: RoleAttributeProfile;
|
||||
behaviorVectors?: RoleActionDefinition[];
|
||||
levelProfile?: EntityLevelProfile;
|
||||
experienceReward?: number;
|
||||
}
|
||||
|
||||
export interface SceneNpc {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
avatar: string;
|
||||
role: string;
|
||||
title?: string;
|
||||
gender?: CharacterGender;
|
||||
characterId?: string;
|
||||
monsterPresetId?: string;
|
||||
initialAffinity?: number;
|
||||
hostile?: boolean;
|
||||
functions?: NpcFunctionType[];
|
||||
recruitable?: boolean;
|
||||
attributeProfile?: RoleAttributeProfile;
|
||||
backstory?: string;
|
||||
personality?: string;
|
||||
motivation?: string;
|
||||
combatStyle?: string;
|
||||
relationshipHooks?: string[];
|
||||
tags?: string[];
|
||||
backstoryReveal?: CharacterBackstoryRevealConfig;
|
||||
skills?: CustomWorldRoleSkill[];
|
||||
initialItems?: CustomWorldRoleInitialItem[];
|
||||
imageSrc?: string;
|
||||
visual?: CustomWorldNpcVisual;
|
||||
narrativeProfile?: ActorNarrativeProfile | null;
|
||||
levelProfile?: EntityLevelProfile;
|
||||
}
|
||||
|
||||
export type SceneEncounterKind = 'npc' | 'treasure' | 'none';
|
||||
|
||||
export interface SceneEncounterResult {
|
||||
kind: SceneEncounterKind;
|
||||
npcId?: string;
|
||||
treasureText?: string;
|
||||
}
|
||||
|
||||
export interface CombatVisualEffect {
|
||||
id: string;
|
||||
frames: string[];
|
||||
fps: number;
|
||||
startX: number;
|
||||
endX?: number;
|
||||
startOrigin: 'player' | 'hostile_npc' | 'monster';
|
||||
endOrigin?: 'player' | 'hostile_npc' | 'monster';
|
||||
startMonsterId?: string;
|
||||
endMonsterId?: string;
|
||||
startHostileNpcId?: string;
|
||||
endHostileNpcId?: string;
|
||||
startAnchorOffsetY?: number;
|
||||
endAnchorOffsetY?: number;
|
||||
startOffsetX?: number;
|
||||
endOffsetX?: number;
|
||||
startYOffset: number;
|
||||
endYOffset?: number;
|
||||
durationMs: number;
|
||||
sizePx: number;
|
||||
scale?: number;
|
||||
facing: FacingDirection;
|
||||
zIndex?: number;
|
||||
traveling?: boolean;
|
||||
}
|
||||
|
||||
export interface SceneHostileNpcChange {
|
||||
id: string;
|
||||
action: string;
|
||||
animation: HostileNpcRenderAnimation;
|
||||
moveMeters?: number;
|
||||
yOffset?: number;
|
||||
}
|
||||
|
||||
export type SceneMonsterChange = SceneHostileNpcChange;
|
||||
|
||||
export interface SceneDirective {
|
||||
playerAnimation: AnimationState;
|
||||
playerMoveMeters: number;
|
||||
playerOffsetY: number;
|
||||
playerFacing: FacingDirection;
|
||||
scrollWorld: boolean;
|
||||
monsterChanges: SceneMonsterChange[];
|
||||
hostileNpcChanges?: SceneHostileNpcChange[];
|
||||
}
|
||||
|
||||
export interface ScenePresetInfo {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
imageSrc: string;
|
||||
forwardSceneId?: string;
|
||||
connectedSceneIds?: string[];
|
||||
npcs?: SceneNpc[];
|
||||
treasureHints?: string[];
|
||||
connections?: SceneConnectionInfo[];
|
||||
narrativeResidues?: SceneNarrativeResidue[];
|
||||
mutationStateText?: string | null;
|
||||
currentPressureLevel?: 'low' | 'medium' | 'high' | 'extreme';
|
||||
}
|
||||
|
||||
export interface SceneConnectionInfo {
|
||||
sceneId: string;
|
||||
relativePosition: CustomWorldSceneRelativePosition;
|
||||
summary: string;
|
||||
}
|
||||
184
src/types/story.ts
Normal file
184
src/types/story.ts
Normal file
@@ -0,0 +1,184 @@
|
||||
import {
|
||||
type NpcInteractionAction,
|
||||
type QuestObjectiveKind,
|
||||
type QuestStatus,
|
||||
type TreasureInteractionAction,
|
||||
} from './core';
|
||||
import type { InventoryItem } from './items';
|
||||
import type { SceneDirective, ScenePresetInfo } from './scene';
|
||||
import type { StoryEngineMemoryState } from './storyEngine';
|
||||
|
||||
export interface StoryOptionGoalAffordance {
|
||||
goalId: string;
|
||||
relation: 'advance' | 'support' | 'detour';
|
||||
label: string;
|
||||
}
|
||||
|
||||
export interface StoryOption {
|
||||
functionId: string;
|
||||
actionText: string;
|
||||
text?: string;
|
||||
detailText?: string;
|
||||
priority?: number;
|
||||
visuals: SceneDirective;
|
||||
skillProbabilities?: Record<string, number>;
|
||||
interaction?: StoryOptionInteraction;
|
||||
goalAffordance?: StoryOptionGoalAffordance | null;
|
||||
runtimePayload?: Record<string, unknown>;
|
||||
disabled?: boolean;
|
||||
disabledReason?: string;
|
||||
}
|
||||
|
||||
export interface QuestReward {
|
||||
affinityBonus: number;
|
||||
currency: number;
|
||||
experience?: number;
|
||||
items: InventoryItem[];
|
||||
storyHint?: string;
|
||||
intel?: {
|
||||
codexEntry?: string;
|
||||
rumorText?: string;
|
||||
unlockedSceneId?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface QuestObjective {
|
||||
kind: QuestObjectiveKind;
|
||||
targetHostileNpcId?: string;
|
||||
targetNpcId?: string;
|
||||
targetSceneId?: string;
|
||||
targetItemId?: string;
|
||||
requiredCount: number;
|
||||
}
|
||||
|
||||
export type QuestNarrativeType =
|
||||
| 'bounty'
|
||||
| 'escort'
|
||||
| 'investigation'
|
||||
| 'retrieval'
|
||||
| 'relationship'
|
||||
| 'trial';
|
||||
|
||||
export interface QuestNarrativeBinding {
|
||||
origin: 'fallback_builder' | 'ai_compiled';
|
||||
narrativeType: QuestNarrativeType;
|
||||
dramaticNeed: string;
|
||||
issuerGoal: string;
|
||||
playerHook: string;
|
||||
worldReason: string;
|
||||
followupHooks: string[];
|
||||
}
|
||||
|
||||
export interface QuestStep extends QuestObjective {
|
||||
id: string;
|
||||
title: string;
|
||||
progress: number;
|
||||
revealText: string;
|
||||
completeText: string;
|
||||
}
|
||||
|
||||
export interface QuestLogEntry {
|
||||
id: string;
|
||||
issuerNpcId: string;
|
||||
issuerNpcName: string;
|
||||
sceneId: string | null;
|
||||
chapterId?: string | null;
|
||||
actId?: string | null;
|
||||
threadId?: string | null;
|
||||
contractId?: string | null;
|
||||
title: string;
|
||||
description: string;
|
||||
summary: string;
|
||||
objective: QuestObjective;
|
||||
progress: number;
|
||||
status: QuestStatus;
|
||||
completionNotified?: boolean;
|
||||
reward: QuestReward;
|
||||
rewardText: string;
|
||||
narrativeBinding?: QuestNarrativeBinding;
|
||||
steps?: QuestStep[];
|
||||
activeStepId?: string | null;
|
||||
visibleStage?: number;
|
||||
hiddenFlags?: string[];
|
||||
discoveredFactIds?: string[];
|
||||
relatedCarrierIds?: string[];
|
||||
consequenceIds?: string[];
|
||||
}
|
||||
|
||||
export interface StoryDialogueTurn {
|
||||
speaker: 'player' | 'npc' | 'companion' | 'system';
|
||||
speakerName?: string;
|
||||
text: string;
|
||||
affinityDelta?: number;
|
||||
}
|
||||
|
||||
export interface StoryNpcAffinityEffect {
|
||||
eventId: string;
|
||||
npcId: string;
|
||||
delta: number;
|
||||
}
|
||||
|
||||
export interface StoryNpcChatState {
|
||||
npcId: string;
|
||||
npcName: string;
|
||||
turnCount: number;
|
||||
customInputPlaceholder?: string;
|
||||
openingSource?: 'npc_initiated' | 'player_reply';
|
||||
sceneActId?: string | null;
|
||||
turnLimit?: number | null;
|
||||
remainingTurns?: number | null;
|
||||
limitReason?: 'negative_affinity' | null;
|
||||
forceExitAfterTurn?: boolean;
|
||||
terminationMode?: 'none' | 'hostile_model' | null;
|
||||
terminationReason?: 'hostile_breakoff' | 'player_exit' | null;
|
||||
isHostileChat?: boolean;
|
||||
pendingQuestOffer?: {
|
||||
quest: QuestLogEntry;
|
||||
} | null;
|
||||
combatContext?: {
|
||||
summary: string;
|
||||
logLines: string[];
|
||||
battleOutcome: 'victory' | 'spar_complete';
|
||||
} | null;
|
||||
}
|
||||
|
||||
export interface CharacterChatTurn {
|
||||
speaker: 'player' | 'character';
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface CharacterChatRecord {
|
||||
history: CharacterChatTurn[];
|
||||
summary: string;
|
||||
updatedAt: string | null;
|
||||
}
|
||||
|
||||
export type StoryHistoryRole = 'action' | 'result';
|
||||
|
||||
export interface StoryMoment {
|
||||
text: string;
|
||||
options: StoryOption[];
|
||||
displayMode?: 'narrative' | 'dialogue';
|
||||
dialogue?: StoryDialogueTurn[];
|
||||
streaming?: boolean;
|
||||
deferredOptions?: StoryOption[];
|
||||
deferredRuntimeState?: {
|
||||
currentScenePreset?: ScenePresetInfo | null;
|
||||
storyEngineMemory?: StoryEngineMemoryState;
|
||||
};
|
||||
historyRole?: StoryHistoryRole;
|
||||
npcChatState?: StoryNpcChatState;
|
||||
npcAffinityEffect?: StoryNpcAffinityEffect | null;
|
||||
}
|
||||
|
||||
export type StoryOptionInteraction =
|
||||
| {
|
||||
kind: 'npc';
|
||||
npcId: string;
|
||||
action: NpcInteractionAction;
|
||||
questId?: string;
|
||||
}
|
||||
| {
|
||||
kind: 'treasure';
|
||||
action: TreasureInteractionAction;
|
||||
};
|
||||
560
src/types/storyEngine.ts
Normal file
560
src/types/storyEngine.ts
Normal file
@@ -0,0 +1,560 @@
|
||||
export type StoryThreadVisibility = 'visible' | 'hidden';
|
||||
|
||||
export type StoryMotifSemanticRole =
|
||||
| 'institution'
|
||||
| 'ritual'
|
||||
| 'technology'
|
||||
| 'taboo'
|
||||
| 'ruin'
|
||||
| 'memory'
|
||||
| 'resource'
|
||||
| 'creature';
|
||||
|
||||
export type SceneNarrativeRevealBudget = 'low' | 'medium' | 'high';
|
||||
|
||||
export type SceneNarrativeCadence =
|
||||
| 'tense'
|
||||
| 'curious'
|
||||
| 'hostile'
|
||||
| 'intimate'
|
||||
| 'tragic'
|
||||
| 'mysterious';
|
||||
|
||||
export interface ThemePack {
|
||||
id: string;
|
||||
displayName: string;
|
||||
toneRange: string[];
|
||||
institutionLexicon: string[];
|
||||
tabooLexicon: string[];
|
||||
artifactClasses: string[];
|
||||
actorArchetypes: string[];
|
||||
conflictForms: string[];
|
||||
clueForms: string[];
|
||||
namingPatterns: string[];
|
||||
revealStyles: string[];
|
||||
}
|
||||
|
||||
export interface StoryThread {
|
||||
id: string;
|
||||
title: string;
|
||||
visibility: StoryThreadVisibility;
|
||||
summary: string;
|
||||
conflictType: string;
|
||||
stakes: string;
|
||||
involvedFactionIds: string[];
|
||||
involvedActorIds: string[];
|
||||
relatedLocationIds: string[];
|
||||
}
|
||||
|
||||
export interface StoryScar {
|
||||
id: string;
|
||||
title: string;
|
||||
pastEvent: string;
|
||||
publicResidue: string;
|
||||
hiddenTruth: string;
|
||||
relatedActorIds: string[];
|
||||
relatedLocationIds: string[];
|
||||
}
|
||||
|
||||
export interface StoryMotif {
|
||||
id: string;
|
||||
label: string;
|
||||
semanticRole: StoryMotifSemanticRole;
|
||||
lexicalHints: string[];
|
||||
}
|
||||
|
||||
export interface WorldStoryGraph {
|
||||
visibleThreads: StoryThread[];
|
||||
hiddenThreads: StoryThread[];
|
||||
scars: StoryScar[];
|
||||
motifs: StoryMotif[];
|
||||
}
|
||||
|
||||
export interface ActorNarrativeProfile {
|
||||
publicMask: string;
|
||||
firstContactMask: string;
|
||||
visibleLine: string;
|
||||
hiddenLine: string;
|
||||
contradiction: string;
|
||||
debtOrBurden: string;
|
||||
taboo: string;
|
||||
immediatePressure: string;
|
||||
relatedThreadIds: string[];
|
||||
relatedScarIds: string[];
|
||||
reactionHooks: string[];
|
||||
}
|
||||
|
||||
export interface KnowledgeFact {
|
||||
id: string;
|
||||
title: string;
|
||||
content: string;
|
||||
ownerActorIds: string[];
|
||||
relatedThreadIds: string[];
|
||||
relatedScarIds: string[];
|
||||
sourceType: 'actor' | 'item' | 'document' | 'scene' | 'monster' | 'quest';
|
||||
visibility: 'public' | 'discoverable' | 'private' | 'forbidden';
|
||||
sayability: 'direct' | 'indirect' | 'reactive_only';
|
||||
aliases?: string[];
|
||||
}
|
||||
|
||||
export interface VisibilitySlice {
|
||||
factIds: string[];
|
||||
sayableFactIds: string[];
|
||||
inferredFactIds: string[];
|
||||
forbiddenFactIds: string[];
|
||||
misdirectionHints: string[];
|
||||
}
|
||||
|
||||
export interface SceneNarrativeDirective {
|
||||
primaryPressure: string;
|
||||
activeThreadIds: string[];
|
||||
foregroundActorIds: string[];
|
||||
foregroundCarrierIds: string[];
|
||||
revealBudget: SceneNarrativeRevealBudget;
|
||||
emotionalCadence: SceneNarrativeCadence;
|
||||
}
|
||||
|
||||
export type GoalSourceKind =
|
||||
| 'quest'
|
||||
| 'chapter'
|
||||
| 'journey_beat'
|
||||
| 'thread_contract'
|
||||
| 'setpiece'
|
||||
| 'relationship'
|
||||
| 'survival';
|
||||
|
||||
export type GoalTrack =
|
||||
| 'main'
|
||||
| 'side'
|
||||
| 'relationship'
|
||||
| 'survival'
|
||||
| 'exploration';
|
||||
|
||||
export type GoalStatus =
|
||||
| 'teased'
|
||||
| 'active'
|
||||
| 'blocked'
|
||||
| 'ready_to_resolve'
|
||||
| 'resolved'
|
||||
| 'archived';
|
||||
|
||||
export type GoalLayer =
|
||||
| 'north_star'
|
||||
| 'active_contract'
|
||||
| 'immediate_step'
|
||||
| 'support';
|
||||
|
||||
export interface GoalStackEntry {
|
||||
id: string;
|
||||
sourceKind: GoalSourceKind;
|
||||
sourceId: string;
|
||||
layer: GoalLayer;
|
||||
track: GoalTrack;
|
||||
title: string;
|
||||
promiseText: string;
|
||||
whyNow: string;
|
||||
nextStepText: string;
|
||||
sceneHint?: string | null;
|
||||
npcHint?: string | null;
|
||||
progressLabel?: string | null;
|
||||
status: GoalStatus;
|
||||
urgency: 'low' | 'medium' | 'high';
|
||||
relatedThreadIds: string[];
|
||||
}
|
||||
|
||||
export interface GoalStackState {
|
||||
northStarGoal: GoalStackEntry | null;
|
||||
activeGoal: GoalStackEntry | null;
|
||||
immediateStepGoal: GoalStackEntry | null;
|
||||
supportGoals: GoalStackEntry[];
|
||||
}
|
||||
|
||||
export interface GoalHandoff {
|
||||
goalId: string;
|
||||
title: string;
|
||||
detail: string;
|
||||
track: GoalTrack;
|
||||
}
|
||||
|
||||
export interface GoalPulseEvent {
|
||||
id: string;
|
||||
goalId: string;
|
||||
pulseType: 'progress' | 'ready_to_turn_in' | 'resolved' | 'handoff';
|
||||
title: string;
|
||||
detail: string;
|
||||
track: GoalTrack;
|
||||
}
|
||||
|
||||
export interface CarrierStoryFingerprint {
|
||||
visibleClue: string;
|
||||
witnessMark: string;
|
||||
unresolvedQuestion: string;
|
||||
currentAppearanceReason: string;
|
||||
relatedThreadIds: string[];
|
||||
relatedScarIds: string[];
|
||||
reactionHooks: string[];
|
||||
}
|
||||
|
||||
export interface ThreadContractStep {
|
||||
id: string;
|
||||
title: string;
|
||||
revealText: string;
|
||||
completionSignalIds: string[];
|
||||
optionalFactIds: string[];
|
||||
}
|
||||
|
||||
export interface ThreadContract {
|
||||
id: string;
|
||||
threadId: string;
|
||||
issuerActorId?: string | null;
|
||||
narrativeType:
|
||||
| 'investigation'
|
||||
| 'escort'
|
||||
| 'hunt'
|
||||
| 'relationship'
|
||||
| 'trial'
|
||||
| 'recovery';
|
||||
currentStepId: string | null;
|
||||
visibleStage: number;
|
||||
steps: ThreadContractStep[];
|
||||
followupThreadIds: string[];
|
||||
}
|
||||
|
||||
export interface StorySignal {
|
||||
id: string;
|
||||
signalType:
|
||||
| 'enter_scene'
|
||||
| 'leave_scene'
|
||||
| 'talk_to_actor'
|
||||
| 'obtain_carrier'
|
||||
| 'inspect_scene'
|
||||
| 'win_battle'
|
||||
| 'give_item'
|
||||
| 'accept_contract'
|
||||
| 'resolve_contract_step';
|
||||
actorId?: string | null;
|
||||
sceneId?: string | null;
|
||||
carrierId?: string | null;
|
||||
threadIds?: string[];
|
||||
}
|
||||
|
||||
export interface CompanionReactionRecord {
|
||||
id: string;
|
||||
characterId: string;
|
||||
reactionType: 'approve' | 'disapprove' | 'concern' | 'silence' | 'curious';
|
||||
reason: string;
|
||||
relatedThreadIds: string[];
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface SceneNarrativeResidue {
|
||||
id: string;
|
||||
title: string;
|
||||
visibleClue: string;
|
||||
linkedFactIds: string[];
|
||||
linkedThreadIds: string[];
|
||||
}
|
||||
|
||||
export interface ChapterState {
|
||||
id: string;
|
||||
title: string;
|
||||
theme: string;
|
||||
primaryThreadIds: string[];
|
||||
stage: 'opening' | 'expansion' | 'turning_point' | 'climax' | 'aftermath';
|
||||
chapterSummary: string;
|
||||
sceneId?: string | null;
|
||||
chapterQuestId?: string | null;
|
||||
}
|
||||
|
||||
export interface SceneActRuntimeState {
|
||||
sceneId: string;
|
||||
chapterId: string;
|
||||
currentActId: string;
|
||||
currentActIndex: number;
|
||||
completedActIds: string[];
|
||||
visitedActIds: string[];
|
||||
}
|
||||
|
||||
export interface JourneyBeat {
|
||||
id: string;
|
||||
beatType:
|
||||
| 'approach'
|
||||
| 'investigation'
|
||||
| 'camp'
|
||||
| 'conflict'
|
||||
| 'boss_prelude'
|
||||
| 'climax'
|
||||
| 'recovery';
|
||||
title: string;
|
||||
triggerThreadIds: string[];
|
||||
recommendedSceneIds: string[];
|
||||
emotionalGoal: string;
|
||||
}
|
||||
|
||||
export interface CompanionArcState {
|
||||
characterId: string;
|
||||
arcTheme: string;
|
||||
currentStage: 'closed' | 'guarded' | 'opening' | 'conflicted' | 'bonded' | 'resolved';
|
||||
activeConflictTags: string[];
|
||||
pendingEventIds: string[];
|
||||
resolvedEventIds: string[];
|
||||
}
|
||||
|
||||
export interface CampEvent {
|
||||
id: string;
|
||||
eventType:
|
||||
| 'private_talk'
|
||||
| 'party_banter'
|
||||
| 'conflict'
|
||||
| 'comfort'
|
||||
| 'reveal'
|
||||
| 'decision';
|
||||
title: string;
|
||||
participantCharacterIds: string[];
|
||||
triggerReason: string;
|
||||
relatedThreadIds: string[];
|
||||
}
|
||||
|
||||
export interface WorldMutation {
|
||||
id: string;
|
||||
mutationType:
|
||||
| 'scene_text'
|
||||
| 'npc_attitude'
|
||||
| 'shop_style'
|
||||
| 'enemy_pressure'
|
||||
| 'route_lock'
|
||||
| 'route_unlock';
|
||||
targetId: string;
|
||||
reason: string;
|
||||
relatedThreadIds: string[];
|
||||
}
|
||||
|
||||
export interface FactionTensionState {
|
||||
factionId: string;
|
||||
temperature: number;
|
||||
pressureSummary: string;
|
||||
activeConflictThreadIds: string[];
|
||||
}
|
||||
|
||||
export interface ChronicleEntry {
|
||||
id: string;
|
||||
category: 'chapter' | 'thread' | 'companion' | 'carrier' | 'scene' | 'world_event';
|
||||
title: string;
|
||||
summary: string;
|
||||
relatedIds: string[];
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface SetpieceDirective {
|
||||
id: string;
|
||||
title: string;
|
||||
setpieceType: 'boss_prelude' | 'showdown' | 'climax' | 'aftermath';
|
||||
relatedThreadIds: string[];
|
||||
sceneFocusId?: string | null;
|
||||
dramaticQuestion: string;
|
||||
}
|
||||
|
||||
export interface CampaignState {
|
||||
id: string;
|
||||
title: string;
|
||||
currentActId: string | null;
|
||||
currentActIndex: number;
|
||||
resolvedEndingId?: string | null;
|
||||
}
|
||||
|
||||
export interface ActState {
|
||||
id: string;
|
||||
title: string;
|
||||
actIndex: number;
|
||||
theme: string;
|
||||
primaryThreadIds: string[];
|
||||
status: 'opening' | 'midgame' | 'late_game' | 'finale' | 'resolved';
|
||||
}
|
||||
|
||||
export interface ConsequenceRecord {
|
||||
id: string;
|
||||
category: 'thread' | 'companion' | 'faction' | 'world' | 'ending_flag';
|
||||
title: string;
|
||||
summary: string;
|
||||
weight: number;
|
||||
relatedIds: string[];
|
||||
irreversible: boolean;
|
||||
}
|
||||
|
||||
export interface CompanionResolution {
|
||||
characterId: string;
|
||||
resolutionType:
|
||||
| 'bonded'
|
||||
| 'reconciled'
|
||||
| 'estranged'
|
||||
| 'departed'
|
||||
| 'sacrificed'
|
||||
| 'neutral';
|
||||
summary: string;
|
||||
relatedThreadIds: string[];
|
||||
}
|
||||
|
||||
export interface EndingState {
|
||||
id: string;
|
||||
title: string;
|
||||
endingType: 'heroic' | 'tragic' | 'bitter_sweet' | 'fractured' | 'ascendant';
|
||||
summary: string;
|
||||
contributingThreadIds: string[];
|
||||
companionResolutions: CompanionResolution[];
|
||||
worldOutcomeSummary: string;
|
||||
}
|
||||
|
||||
export interface AuthorialConstraintPack {
|
||||
toneRules: string[];
|
||||
noGoPatterns: string[];
|
||||
branchBudget: {
|
||||
maxMajorDivergences: number;
|
||||
maxEndingFamilies: number;
|
||||
};
|
||||
mandatoryThemes: string[];
|
||||
requiredPayoffs: string[];
|
||||
}
|
||||
|
||||
export interface BranchBudgetStatus {
|
||||
currentMajorDivergences: number;
|
||||
maxMajorDivergences: number;
|
||||
currentEndingFamilies: number;
|
||||
maxEndingFamilies: number;
|
||||
pressure: 'low' | 'medium' | 'high';
|
||||
}
|
||||
|
||||
export interface NarrativeQaIssue {
|
||||
id: string;
|
||||
severity: 'low' | 'medium' | 'high';
|
||||
category: 'consistency' | 'pacing' | 'payoff' | 'branch_budget' | 'reveal_leak';
|
||||
summary: string;
|
||||
relatedIds: string[];
|
||||
}
|
||||
|
||||
export interface NarrativeQaReport {
|
||||
generatedAt: string;
|
||||
issues: NarrativeQaIssue[];
|
||||
summary: string;
|
||||
}
|
||||
|
||||
export interface ScenarioPack {
|
||||
id: string;
|
||||
title: string;
|
||||
version: string;
|
||||
worldPackIds: string[];
|
||||
campaignIds: string[];
|
||||
sharedConstraintPackIds: string[];
|
||||
}
|
||||
|
||||
export interface CampaignPack {
|
||||
id: string;
|
||||
scenarioPackId: string;
|
||||
title: string;
|
||||
authoringStyle: string;
|
||||
campaignStateSeed: CampaignState;
|
||||
actTemplates: ActState[];
|
||||
requiredCompanionIds: string[];
|
||||
}
|
||||
|
||||
export interface PlayerStyleProfile {
|
||||
id: string;
|
||||
preferenceWeights: {
|
||||
story: number;
|
||||
exploration: number;
|
||||
combat: number;
|
||||
companion: number;
|
||||
collection: number;
|
||||
};
|
||||
dominantStyle:
|
||||
| 'story_first'
|
||||
| 'explorer'
|
||||
| 'combat_driver'
|
||||
| 'companion_bond'
|
||||
| 'collector';
|
||||
}
|
||||
|
||||
export interface SimulationRunResult {
|
||||
id: string;
|
||||
scenarioPackId: string;
|
||||
campaignPackId: string;
|
||||
seed: string;
|
||||
endingId?: string | null;
|
||||
activeThreadCountPeak: number;
|
||||
fracturedCompanionCount: number;
|
||||
issueCount: number;
|
||||
summary: string;
|
||||
}
|
||||
|
||||
export interface ReleaseGateReport {
|
||||
generatedAt: string;
|
||||
status: 'pass' | 'warn' | 'block';
|
||||
summary: string;
|
||||
blockingIssues: string[];
|
||||
simulationCoverage: number;
|
||||
}
|
||||
|
||||
export interface SaveMigrationManifest {
|
||||
version: string;
|
||||
requiredTransforms: string[];
|
||||
backwardCompatible: boolean;
|
||||
}
|
||||
|
||||
export interface NarrativeCodexEntry {
|
||||
id: string;
|
||||
title: string;
|
||||
summary: string;
|
||||
category: 'fact' | 'document' | 'scene' | 'thread' | 'companion' | 'ending';
|
||||
relatedIds: string[];
|
||||
}
|
||||
|
||||
export interface NarrativeCodexSection {
|
||||
id: string;
|
||||
title: string;
|
||||
entries: NarrativeCodexEntry[];
|
||||
}
|
||||
|
||||
export interface CompanionStanceProfile {
|
||||
trust: number;
|
||||
warmth: number;
|
||||
ideologicalFit: number;
|
||||
fearOrGuard: number;
|
||||
loyalty: number;
|
||||
currentConflictTag?: string | null;
|
||||
recentApprovals: string[];
|
||||
recentDisapprovals: string[];
|
||||
}
|
||||
|
||||
export interface StoryEngineMemoryState {
|
||||
discoveredFactIds: string[];
|
||||
inferredFactIds?: string[];
|
||||
activeThreadIds: string[];
|
||||
resolvedScarIds: string[];
|
||||
recentCarrierIds: string[];
|
||||
openedSceneChapterIds?: string[];
|
||||
currentSceneActState?: SceneActRuntimeState | null;
|
||||
recentSignalIds?: string[];
|
||||
recentCompanionReactions?: CompanionReactionRecord[];
|
||||
currentChapter?: ChapterState | null;
|
||||
currentJourneyBeatId?: string | null;
|
||||
currentJourneyBeat?: JourneyBeat | null;
|
||||
companionArcStates?: CompanionArcState[];
|
||||
worldMutations?: WorldMutation[];
|
||||
chronicle?: ChronicleEntry[];
|
||||
factionTensionStates?: FactionTensionState[];
|
||||
currentCampEvent?: CampEvent | null;
|
||||
currentSetpieceDirective?: SetpieceDirective | null;
|
||||
continueGameDigest?: string | null;
|
||||
campaignState?: CampaignState | null;
|
||||
actState?: ActState | null;
|
||||
consequenceLedger?: ConsequenceRecord[];
|
||||
companionResolutions?: CompanionResolution[];
|
||||
endingState?: EndingState | null;
|
||||
authorialConstraintPack?: AuthorialConstraintPack | null;
|
||||
branchBudgetStatus?: BranchBudgetStatus | null;
|
||||
narrativeQaReport?: NarrativeQaReport | null;
|
||||
narrativeCodex?: NarrativeCodexSection[];
|
||||
playerStyleProfile?: PlayerStyleProfile | null;
|
||||
simulationRunResults?: SimulationRunResult[];
|
||||
releaseGateReport?: ReleaseGateReport | null;
|
||||
saveMigrationManifest?: SaveMigrationManifest | null;
|
||||
}
|
||||
Reference in New Issue
Block a user