@linxin666/dsh-pet 0.3.17 → 0.3.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.i18n.yaml +2 -2
  2. package/README.md +16 -1
  3. package/README.zh.md +16 -1
  4. package/assets/blue-throated-bee-eater/pet.json +204 -0
  5. package/assets/blue-throated-bee-eater/previews/failed.gif +0 -0
  6. package/assets/blue-throated-bee-eater/previews/idle.gif +0 -0
  7. package/assets/blue-throated-bee-eater/previews/jumping.gif +0 -0
  8. package/assets/blue-throated-bee-eater/previews/review.gif +0 -0
  9. package/assets/blue-throated-bee-eater/previews/running-left.gif +0 -0
  10. package/assets/blue-throated-bee-eater/previews/running-right.gif +0 -0
  11. package/assets/blue-throated-bee-eater/previews/running.gif +0 -0
  12. package/assets/blue-throated-bee-eater/previews/waiting.gif +0 -0
  13. package/assets/blue-throated-bee-eater/previews/waving.gif +0 -0
  14. package/assets/blue-throated-bee-eater/spritesheet.webp +0 -0
  15. package/assets/blue-throated-bee-eater/voice.json +13 -0
  16. package/contracts/pet-manifest-v2.schema.json +84 -0
  17. package/lib/client.js +176 -27
  18. package/lib/client.js.map +1 -1
  19. package/lib/index.js +170 -6
  20. package/lib/types/client/gameplay-hud.d.ts +2 -0
  21. package/lib/types/client/gameplay-hud.d.ts.map +1 -1
  22. package/lib/types/client/gameplay-hud.js +65 -12
  23. package/lib/types/client/index.d.ts +0 -6
  24. package/lib/types/client/index.d.ts.map +1 -1
  25. package/lib/types/client/index.js +25 -2
  26. package/lib/types/client/locales.d.ts +7 -3
  27. package/lib/types/client/locales.d.ts.map +1 -1
  28. package/lib/types/client/locales.js +7 -3
  29. package/lib/types/client/renderers/Frames2dVisualMount.d.ts.map +1 -1
  30. package/lib/types/client/renderers/Frames2dVisualMount.js +5 -1
  31. package/lib/types/client/renderers/frames2d.d.ts +25 -0
  32. package/lib/types/client/renderers/frames2d.d.ts.map +1 -1
  33. package/lib/types/client/renderers/frames2d.js +84 -7
  34. package/lib/types/manifest-v2.d.ts +45 -0
  35. package/lib/types/manifest-v2.d.ts.map +1 -1
  36. package/lib/types/manifest-v2.js +139 -1
  37. package/lib/types/persist.d.ts +1 -1
  38. package/lib/types/persist.d.ts.map +1 -1
  39. package/lib/types/persist.js +1 -1
  40. package/lib/types/registry.d.ts +22 -0
  41. package/lib/types/registry.d.ts.map +1 -1
  42. package/lib/types/registry.js +45 -1
  43. package/package.json +2 -1
  44. package/src/client/gameplay-hud.test.tsx +64 -0
  45. package/src/client/gameplay-hud.tsx +109 -21
  46. package/src/client/index.ts +26 -2
  47. package/src/client/locales.ts +7 -3
  48. package/src/client/pet.module.css +31 -1
  49. package/src/client/renderers/Frames2dVisualMount.tsx +5 -1
  50. package/src/client/renderers/frames2d.test.ts +43 -0
  51. package/src/client/renderers/frames2d.ts +100 -7
  52. package/src/manifest-v2.ts +167 -1
  53. package/src/persist.ts +1 -1
  54. package/src/registry.test.ts +19 -5
  55. package/src/registry.ts +66 -1
@@ -52,7 +52,60 @@ function validateFrames2dConfig(config) {
52
52
  if (typeof phases.idle !== 'string' || tracks[phases.idle] === undefined) {
53
53
  throw new Error('frames2d phases.idle must name an existing track');
54
54
  }
55
- return { tracks, phases: phases };
55
+ // Skins: keep entries whose idleTrack survives validation and loops —
56
+ // a non-looping base idle would settle into itself forever. Click actions
57
+ // with an unresolvable track are dropped from that skin.
58
+ let skins;
59
+ if (Array.isArray(config.skins)) {
60
+ const resolved = [];
61
+ for (const skin of config.skins) {
62
+ if (!isRecord(skin) || typeof skin.id !== 'string' || typeof skin.label !== 'string'
63
+ || typeof skin.idleTrack !== 'string' || skin.idleTrack === '')
64
+ continue;
65
+ const target = tracks[skin.idleTrack];
66
+ if (target === undefined || !target.loop)
67
+ continue;
68
+ let clickActions;
69
+ if (Array.isArray(skin.clickActions)) {
70
+ const kept = [];
71
+ for (const action of skin.clickActions) {
72
+ if (!isRecord(action) || typeof action.track !== 'string' || action.track === ''
73
+ || typeof action.probability !== 'number' || !(action.probability > 0) || action.probability > 1)
74
+ continue;
75
+ if (tracks[action.track] === undefined)
76
+ continue;
77
+ kept.push({
78
+ track: action.track,
79
+ probability: action.probability,
80
+ ...(Array.isArray(action.phrases) ? { phrases: action.phrases } : {}),
81
+ });
82
+ }
83
+ if (kept.length > 0)
84
+ clickActions = kept;
85
+ }
86
+ let gameplayTracks;
87
+ if (isRecord(skin.gameplayTracks)) {
88
+ const kept = {};
89
+ for (const [state, trackName] of Object.entries(skin.gameplayTracks)) {
90
+ if (typeof trackName !== 'string' || trackName === '' || tracks[trackName] === undefined)
91
+ continue;
92
+ kept[state] = trackName;
93
+ }
94
+ if (Object.keys(kept).length > 0)
95
+ gameplayTracks = kept;
96
+ }
97
+ resolved.push({
98
+ id: skin.id,
99
+ label: skin.label,
100
+ idleTrack: skin.idleTrack,
101
+ ...(clickActions === undefined ? {} : { clickActions }),
102
+ ...(gameplayTracks === undefined ? {} : { gameplayTracks }),
103
+ });
104
+ }
105
+ if (resolved.length > 0)
106
+ skins = resolved;
107
+ }
108
+ return { tracks, phases: phases, ...(skins === undefined ? {} : { skins }) };
56
109
  }
57
110
  export const frames2dRenderer = {
58
111
  id: 'frames2d',
@@ -146,11 +199,18 @@ export const frames2dRenderer = {
146
199
  let frameIndex = 0;
147
200
  let lastAdvance = Date.now();
148
201
  let override;
202
+ // Skin base idle: every "back to idle" target resolves through this
203
+ // (idle phase, unmapped phases and fallbacks), so a selected skin swaps
204
+ // the pet's resting look without touching gameplay tracks.
205
+ let baseIdle = config.phases.idle;
149
206
  let drawToken = 0;
150
207
  let lastDrawnUrl;
151
208
  const trackForPhase = (phase) => {
152
209
  const mapped = config.phases[phase];
153
- return mapped !== undefined && config.tracks[mapped] !== undefined ? mapped : config.phases.idle;
210
+ if (mapped === undefined)
211
+ return baseIdle;
212
+ const target = mapped === config.phases.idle ? baseIdle : mapped;
213
+ return config.tracks[target] !== undefined ? target : baseIdle;
154
214
  };
155
215
  /** Canvas path: paints the newest requested frame; stale draws drop out. */
156
216
  const paintCanvas = (url) => {
@@ -211,11 +271,14 @@ export const frames2dRenderer = {
211
271
  schedule(def.durations[frameIndex] ?? 200);
212
272
  return;
213
273
  }
214
- // Non-loop completion: settle into the fallback; when the fallback is
215
- // what the phase map would play anyway, release the gameplay override.
274
+ // Non-loop completion: settle into the fallback an explicit fallback to
275
+ // a real track wins, except when it points back at the manifest idle
276
+ // (that resolves through the skin base idle); anything else lands on
277
+ // the skin base idle. When the settle target is what the phase map
278
+ // plays anyway, release the gameplay override.
216
279
  const target = def.fallback !== undefined && config.tracks[def.fallback] !== undefined
217
- ? def.fallback
218
- : config.phases.idle;
280
+ ? (def.fallback === config.phases.idle ? baseIdle : def.fallback)
281
+ : baseIdle;
219
282
  if (target === trackForPhase(ctx.phase.get()))
220
283
  override = undefined;
221
284
  play(target);
@@ -224,7 +287,7 @@ export const frames2dRenderer = {
224
287
  if (disposed)
225
288
  return;
226
289
  if (config.tracks[trackId] === undefined)
227
- trackId = config.phases.idle;
290
+ trackId = baseIdle;
228
291
  if (timer !== undefined)
229
292
  clearTimeout(timer);
230
293
  track = trackId;
@@ -313,6 +376,20 @@ export const frames2dRenderer = {
313
376
  if (next !== track)
314
377
  play(next);
315
378
  },
379
+ setIdleTrack(next) {
380
+ if (disposed)
381
+ return;
382
+ if (next === undefined || (config.tracks[next] !== undefined && config.tracks[next].loop)) {
383
+ baseIdle = next ?? config.phases.idle;
384
+ }
385
+ // A skin only owns the resting look: re-resolve only when no
386
+ // gameplay override is active (active overrides end into baseIdle).
387
+ if (override === undefined) {
388
+ const target = trackForPhase(ctx.phase.get());
389
+ if (target !== track)
390
+ play(target);
391
+ }
392
+ },
316
393
  currentTrack() {
317
394
  return track;
318
395
  },
@@ -99,6 +99,41 @@ export interface PetManifestFrames2d {
99
99
  phases: Partial<Record<ActivityPhase, string>> & {
100
100
  idle: string;
101
101
  };
102
+ /**
103
+ * Optional selectable skins: a skin swaps the base idle target (the idle
104
+ * phase, unmapped phases, and every fallback back to idle) to its own
105
+ * looping idle track. Gameplay tracks (shy/work/sleep...) are not replaced.
106
+ */
107
+ skins?: PetManifestSkin[];
108
+ }
109
+ /** One selectable frames2d skin. */
110
+ export interface PetManifestSkin {
111
+ id: string;
112
+ label: string;
113
+ /** A declared, looping track that becomes the base idle while selected. */
114
+ idleTrack: string;
115
+ /**
116
+ * Optional click-triggered actions exclusive to this skin: while the skin
117
+ * is selected, a tap rolls each action by probability (in order) and plays
118
+ * its track once if hit. Misses fall through to the regular touch zones.
119
+ */
120
+ clickActions?: PetManifestSkinClickAction[];
121
+ /**
122
+ * Optional gameplay-track overrides: gameplay state name (e.g. 'sleep' or
123
+ * 'work') -> a declared track the skin swaps in while selected. Lets a skin
124
+ * restyle a gameplay loop (e.g. its own sleep animation) without touching
125
+ * the default pet's tracks.
126
+ */
127
+ gameplayTracks?: Record<string, string>;
128
+ }
129
+ /** One probability-rolled tap action a skin may declare. */
130
+ export interface PetManifestSkinClickAction {
131
+ /** A declared track played once on hit (usually non-looping). */
132
+ track: string;
133
+ /** Hit probability for this action (0..1). */
134
+ probability: number;
135
+ /** Optional lines spoken when the action fires. */
136
+ phrases?: string[];
102
137
  }
103
138
  /** Normalized v2 manifest the registry consumes. */
104
139
  export interface PetManifestV2 {
@@ -150,6 +185,16 @@ export declare const KNOWN_LIVE2D: Set<string>;
150
185
  export declare const KNOWN_FRAMES2D: Set<string>;
151
186
  /** frames2d track field allow-list (drift-locked to the schema file). */
152
187
  export declare const KNOWN_FRAMES2D_TRACK: Set<string>;
188
+ /** frames2d skin entry field allow-list (drift-locked to the schema file). */
189
+ export declare const KNOWN_SKIN: Set<string>;
190
+ /** frames2d skin click-action field allow-list (drift-locked to the schema file). */
191
+ export declare const KNOWN_SKIN_CLICK: Set<string>;
192
+ /** Max selectable skins a frames2d manifest may declare. */
193
+ export declare const FRAMES2D_MAX_SKINS = 16;
194
+ /** Max click actions one skin may declare. */
195
+ export declare const FRAMES2D_MAX_SKIN_CLICKS = 8;
196
+ /** Max gameplay-state overrides one skin may declare. */
197
+ export declare const FRAMES2D_MAX_SKIN_GAMEPLAY = 8;
153
198
  /**
154
199
  * Validate a manifest-relative asset path: no absolute paths, no backslashes,
155
200
  * no traversal, plain safe segments only. Returns the normalized path.
@@ -1 +1 @@
1
- {"version":3,"file":"manifest-v2.d.ts","sourceRoot":"","sources":["../../src/manifest-v2.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"manifest-v2.d.ts","sourceRoot":"","sources":["../../src/manifest-v2.ts"],"names":[],"mappings":"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"}
@@ -50,9 +50,35 @@ export const KNOWN_SPRITE2D = new Set(['spritesheetPath', 'cell', 'columns', 'at
50
50
  /** live2d block field allow-list (drift-locked to the schema file). */
51
51
  export const KNOWN_LIVE2D = new Set(['model', 'scale', 'translate', 'motions', 'expressions', 'hitAreas', 'lipSync']);
52
52
  /** frames2d block field allow-list (drift-locked to the schema file). */
53
- export const KNOWN_FRAMES2D = new Set(['dir', 'defaultFrameMs', 'tracks', 'phases']);
53
+ export const KNOWN_FRAMES2D = new Set(['dir', 'defaultFrameMs', 'tracks', 'phases', 'skins']);
54
54
  /** frames2d track field allow-list (drift-locked to the schema file). */
55
55
  export const KNOWN_FRAMES2D_TRACK = new Set(['frames', 'frameMs', 'loop', 'fallback']);
56
+ /** frames2d skin entry field allow-list (drift-locked to the schema file). */
57
+ export const KNOWN_SKIN = new Set(['id', 'label', 'idleTrack', 'clickActions', 'gameplayTracks']);
58
+ /** frames2d skin click-action field allow-list (drift-locked to the schema file). */
59
+ export const KNOWN_SKIN_CLICK = new Set(['track', 'probability', 'phrases']);
60
+ /** Max selectable skins a frames2d manifest may declare. */
61
+ export const FRAMES2D_MAX_SKINS = 16;
62
+ /** Max click actions one skin may declare. */
63
+ export const FRAMES2D_MAX_SKIN_CLICKS = 8;
64
+ /** Max gameplay-state overrides one skin may declare. */
65
+ export const FRAMES2D_MAX_SKIN_GAMEPLAY = 8;
66
+ /** Max spoken lines one skin click action may declare. */
67
+ const SKIN_CLICK_MAX_PHRASES = 5;
68
+ /** Max length of one spoken line. */
69
+ const SKIN_CLICK_PHRASE_MAX_LENGTH = 120;
70
+ /** Validate a skin click action's optional phrase pool (same spirit as gameplay phrases). */
71
+ function parseSkinPhrases(raw, field, diag) {
72
+ if (raw === undefined)
73
+ return undefined;
74
+ if (!Array.isArray(raw) || raw.length === 0 || raw.length > SKIN_CLICK_MAX_PHRASES
75
+ || raw.some(line => typeof line !== 'string' || line.trim() === '' || line.length > SKIN_CLICK_PHRASE_MAX_LENGTH)) {
76
+ diag.error(field + ' must be 1..' + SKIN_CLICK_MAX_PHRASES + ' non-empty lines of at most '
77
+ + SKIN_CLICK_PHRASE_MAX_LENGTH + ' chars');
78
+ return undefined;
79
+ }
80
+ return raw;
81
+ }
56
82
  class Diagnostics {
57
83
  list = [];
58
84
  source;
@@ -391,6 +417,118 @@ function parseFrames2dBlock(raw, diag) {
391
417
  diag.error('frames2d.tracks.' + name + '.fallback references unknown track ' + JSON.stringify(track.fallback));
392
418
  }
393
419
  }
420
+ // Optional skins: each selects a declared looping idle track as the base
421
+ // idle while active (id/label are UI-facing, idleTrack is structure).
422
+ if (raw.skins !== undefined) {
423
+ if (!Array.isArray(raw.skins) || raw.skins.length === 0 || raw.skins.length > FRAMES2D_MAX_SKINS) {
424
+ diag.error('frames2d.skins must be an array of 1..' + FRAMES2D_MAX_SKINS + ' skins');
425
+ }
426
+ else {
427
+ const skins = [];
428
+ const seen = new Set();
429
+ for (const [index, entry] of raw.skins.entries()) {
430
+ const field = 'frames2d.skins[' + index + ']';
431
+ if (!isRecord(entry)) {
432
+ diag.error(field + ' must be an object');
433
+ continue;
434
+ }
435
+ const extra = unknownKeys(entry, KNOWN_SKIN);
436
+ if (extra.length > 0)
437
+ diag.error(field + ': unknown field(s) ' + extra.map(k => JSON.stringify(k)).join(', '));
438
+ const id = typeof entry.id === 'string' ? entry.id.trim() : '';
439
+ if (id === '' || id.length > 24 || !FRAMES2D_TRACK_NAME.test(id)) {
440
+ diag.error(field + '.id must be a lowercase kebab id of at most 24 chars');
441
+ continue;
442
+ }
443
+ if (seen.has(id)) {
444
+ diag.error(field + ': duplicate skin id ' + JSON.stringify(id));
445
+ continue;
446
+ }
447
+ seen.add(id);
448
+ const label = typeof entry.label === 'string' ? entry.label.trim() : '';
449
+ if (label === '' || label.length > 40) {
450
+ diag.error(field + '.label must be a non-empty string of at most 40 chars');
451
+ continue;
452
+ }
453
+ const idleTrack = typeof entry.idleTrack === 'string' ? entry.idleTrack : '';
454
+ if (!validTrackName(idleTrack) || tracks[idleTrack] === undefined) {
455
+ diag.error(field + '.idleTrack must name a declared frames2d track');
456
+ continue;
457
+ }
458
+ // Optional click actions: each names a declared track and a hit
459
+ // probability; phrases reuse the gameplay phrase constraints.
460
+ let clickActions;
461
+ if (entry.clickActions !== undefined) {
462
+ if (!Array.isArray(entry.clickActions) || entry.clickActions.length === 0 || entry.clickActions.length > FRAMES2D_MAX_SKIN_CLICKS) {
463
+ diag.error(field + '.clickActions must be an array of 1..' + FRAMES2D_MAX_SKIN_CLICKS + ' actions');
464
+ }
465
+ else {
466
+ const resolved = [];
467
+ for (const [cIndex, action] of entry.clickActions.entries()) {
468
+ const cField = field + '.clickActions[' + cIndex + ']';
469
+ if (!isRecord(action)) {
470
+ diag.error(cField + ' must be an object');
471
+ continue;
472
+ }
473
+ const cExtra = unknownKeys(action, KNOWN_SKIN_CLICK);
474
+ if (cExtra.length > 0)
475
+ diag.error(cField + ': unknown field(s) ' + cExtra.map(k => JSON.stringify(k)).join(', '));
476
+ const trackName = typeof action.track === 'string' ? action.track : '';
477
+ if (!validTrackName(trackName) || tracks[trackName] === undefined) {
478
+ diag.error(cField + '.track must name a declared frames2d track');
479
+ continue;
480
+ }
481
+ if (typeof action.probability !== 'number' || !Number.isFinite(action.probability)
482
+ || action.probability <= 0 || action.probability > 1) {
483
+ diag.error(cField + '.probability must be a number in (0, 1]');
484
+ continue;
485
+ }
486
+ const phrases = parseSkinPhrases(action.phrases, cField + '.phrases', diag);
487
+ resolved.push({ track: trackName, probability: action.probability, ...(phrases === undefined ? {} : { phrases }) });
488
+ }
489
+ if (resolved.length > 0)
490
+ clickActions = resolved;
491
+ }
492
+ }
493
+ // Optional gameplay-track overrides: gameplay state name -> declared
494
+ // track swapped in while this skin is selected (e.g. a skin variant of
495
+ // the sleep loop). State names mirror gameplay blocks (sleep/work...);
496
+ // values must reference declared tracks.
497
+ let gameplayTracks;
498
+ if (entry.gameplayTracks !== undefined) {
499
+ if (!isRecord(entry.gameplayTracks)) {
500
+ diag.error(field + '.gameplayTracks must be an object mapping gameplay state names to tracks');
501
+ }
502
+ else {
503
+ const states = Object.keys(entry.gameplayTracks);
504
+ if (states.length === 0 || states.length > FRAMES2D_MAX_SKIN_GAMEPLAY) {
505
+ diag.error(field + '.gameplayTracks must map 1..' + FRAMES2D_MAX_SKIN_GAMEPLAY + ' gameplay states');
506
+ }
507
+ else {
508
+ const resolvedTracks = {};
509
+ for (const state of states) {
510
+ if (!/^[a-z0-9][a-z0-9-]*$/.test(state)) {
511
+ diag.error(field + '.gameplayTracks key ' + JSON.stringify(state) + ' must be a lowercase kebab state name');
512
+ continue;
513
+ }
514
+ const gTrack = entry.gameplayTracks[state];
515
+ if (typeof gTrack !== 'string' || !validTrackName(gTrack) || tracks[gTrack] === undefined) {
516
+ diag.error(field + '.gameplayTracks[' + JSON.stringify(state) + '] must name a declared frames2d track');
517
+ continue;
518
+ }
519
+ resolvedTracks[state] = gTrack;
520
+ }
521
+ if (Object.keys(resolvedTracks).length > 0)
522
+ gameplayTracks = resolvedTracks;
523
+ }
524
+ }
525
+ }
526
+ skins.push({ id, label, idleTrack, ...(clickActions === undefined ? {} : { clickActions }), ...(gameplayTracks === undefined ? {} : { gameplayTracks }) });
527
+ }
528
+ if (skins.length > 0)
529
+ block.skins = skins;
530
+ }
531
+ }
394
532
  return diag.hasErrors ? undefined : block;
395
533
  }
396
534
  /** v1 compat read: map the legacy flat manifest onto the v2 sprite2d shape. */
@@ -22,7 +22,7 @@ export interface PetDisplayConfig {
22
22
  export declare const defaultDisplayConfig: PetDisplayConfig;
23
23
  /** Display value bounds (shared by load-time validation and setConfig). */
24
24
  export declare const DISPLAY_SIZE_MIN = 32;
25
- export declare const DISPLAY_SIZE_MAX = 512;
25
+ export declare const DISPLAY_SIZE_MAX = 1024;
26
26
  export declare const DISPLAY_INSET_MAX = 10000;
27
27
  /** Everything persisted for the pet. */
28
28
  export interface PetPersist {
@@ -1 +1 @@
1
- {"version":3,"file":"persist.d.ts","sourceRoot":"","sources":["../../src/persist.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAA+B,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AAC/E,OAAO,EAAwC,KAAK,WAAW,EAAE,MAAM,aAAa,CAAA;AAEpF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAErD,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAEhE,gDAAgD;AAChD,MAAM,WAAW,gBAAgB;IAC/B,qBAAqB;IACrB,OAAO,EAAE,OAAO,CAAA;IAChB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAA;IACZ,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAA;IACb,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAA;CACf;AAED,eAAO,MAAM,oBAAoB,EAAE,gBAKlC,CAAA;AAED,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAClC,eAAO,MAAM,gBAAgB,MAAM,CAAA;AACnC,eAAO,MAAM,iBAAiB,QAAS,CAAA;AAEvC,wCAAwC;AACxC,MAAM,WAAW,UAAU;IACzB,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,QAAQ,EAAE,aAAa,CAAA;IACvB,gCAAgC;IAChC,MAAM,EAAE,WAAW,CAAA;IACnB,OAAO,EAAE,gBAAgB,CAAA;IACzB,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;CAC3C;AAED,wBAAwB;AACxB,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAErC,wBAAgB,YAAY,IAAI,UAAU,CASzC;AAED;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AA+DD,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAqB,GAAG,UAAU,CAoDrE;AAED,sDAAsD;AACtD,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,GAAE,MAAqB,GAAG,IAAI,CAMjF"}
1
+ {"version":3,"file":"persist.d.ts","sourceRoot":"","sources":["../../src/persist.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAA+B,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AAC/E,OAAO,EAAwC,KAAK,WAAW,EAAE,MAAM,aAAa,CAAA;AAEpF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAErD,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAEhE,gDAAgD;AAChD,MAAM,WAAW,gBAAgB;IAC/B,qBAAqB;IACrB,OAAO,EAAE,OAAO,CAAA;IAChB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAA;IACZ,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAA;IACb,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAA;CACf;AAED,eAAO,MAAM,oBAAoB,EAAE,gBAKlC,CAAA;AAED,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAClC,eAAO,MAAM,gBAAgB,OAAO,CAAA;AACpC,eAAO,MAAM,iBAAiB,QAAS,CAAA;AAEvC,wCAAwC;AACxC,MAAM,WAAW,UAAU;IACzB,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,QAAQ,EAAE,aAAa,CAAA;IACvB,gCAAgC;IAChC,MAAM,EAAE,WAAW,CAAA;IACnB,OAAO,EAAE,gBAAgB,CAAA;IACzB,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;CAC3C;AAED,wBAAwB;AACxB,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAErC,wBAAgB,YAAY,IAAI,UAAU,CASzC;AAED;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AA+DD,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAqB,GAAG,UAAU,CAoDrE;AAED,sDAAsD;AACtD,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,GAAE,MAAqB,GAAG,IAAI,CAMjF"}
@@ -19,7 +19,7 @@ export const defaultDisplayConfig = {
19
19
  };
20
20
  /** Display value bounds (shared by load-time validation and setConfig). */
21
21
  export const DISPLAY_SIZE_MIN = 32;
22
- export const DISPLAY_SIZE_MAX = 512;
22
+ export const DISPLAY_SIZE_MAX = 1024;
23
23
  export const DISPLAY_INSET_MAX = 10_000;
24
24
  /** Name constraints. */
25
25
  export const PET_NAME_MAX_LENGTH = 20;
@@ -159,6 +159,28 @@ export interface PetFrames2dDefinition {
159
159
  phases: Partial<Record<ActivityPhase, string>> & {
160
160
  idle: string;
161
161
  };
162
+ /** Selectable skins; each swaps the base idle target to its idleTrack. */
163
+ skins?: PetSkinDefinition[];
164
+ }
165
+ /** One selectable frames2d skin as served to the browser half. */
166
+ export interface PetSkinDefinition {
167
+ id: string;
168
+ label: string;
169
+ /** A declared looping track that becomes the base idle while selected. */
170
+ idleTrack: string;
171
+ /** Click actions exclusive to this skin (roll by probability; miss → touch zones). */
172
+ clickActions?: PetSkinClickActionDefinition[];
173
+ /** Gameplay-state overrides (state -> track) swapped in while selected. */
174
+ gameplayTracks?: Record<string, string>;
175
+ }
176
+ /** One probability-rolled tap action a skin may declare. */
177
+ export interface PetSkinClickActionDefinition {
178
+ /** A declared track played once on hit. */
179
+ track: string;
180
+ /** Hit probability (0..1). */
181
+ probability: number;
182
+ /** Optional lines spoken when the action fires. */
183
+ phrases?: string[];
162
184
  }
163
185
  /** A normalized pet as served to the browser half. */
164
186
  export interface PetDefinition {
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC7D,OAAO,EAAuB,KAAK,UAAU,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAC5F,OAAO,EAAuC,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAGxG,OAAO,EAA8B,KAAK,cAAc,EAAE,MAAM,kCAAkC,CAAA;AAElG,OAAO,EAAgE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACrH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAIxD,yDAAyD;AACzD,eAAO,MAAM,aAAa,EAAE,SAAS,YAAY,EAUhD,CAAA;AAED,6BAA6B;AAC7B,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED,wDAAwD;AACxD,eAAO,MAAM,gBAAgB,EAAE,OAAqC,CAAA;AACpE,8CAA8C;AAC9C,eAAO,MAAM,mBAAmB,IAAI,CAAA;AACpC,2DAA2D;AAC3D,eAAO,MAAM,qBAAqB,IAAI,CAAA;AAEtC;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAAgC,CAAA;AAElF,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,IAAI,GAAE,MAAkB,GAAG,MAAM,CAQnG;AAeD,yDAAyD;AACzD,MAAM,WAAW,WAAW;IAC1B,+CAA+C;IAC/C,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,uDAAuD;IACvD,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,yEAAyE;IACzE,IAAI,EAAE,OAAO,CAAA;IACb,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,YAAY,CAAA;CACxB;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,YAAY,EAAE;IACxD,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,IAAI,EAAE,OAAO,CAAA;IACb,QAAQ,CAAC,EAAE,YAAY,CAAA;CACxB,CAUA,CAAA;AAED,2EAA2E;AAC3E,MAAM,WAAW,WAAW;IAC1B,2CAA2C;IAC3C,EAAE,EAAE,MAAM,CAAA;IACV,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAA;IACnB,4BAA4B;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,uDAAuD;IACvD,eAAe,EAAE,MAAM,CAAA;IACvB,+DAA+D;IAC/D,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1C,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC,CAAA;IACxD,wFAAwF;IACxF,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,YAAY,EAAE,CAAC,CAAC,CAAA;IAC1D;;;;;OAKG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAA;CAC7B;AAED,uDAAuD;AACvD,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,+BAA+B;IAC/B,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,YAAY,CAAA;CACxB;AAED,+EAA+E;AAC/E,MAAM,WAAW,mBAAmB;IAClC,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAA;IAChB,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAA;IACjB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,+DAA+D;IAC/D,SAAS,CAAC,EAAE;QAAE,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACtC,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IAClE,yEAAyE;IACzE,WAAW,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAA;IACpD,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CACpB;AAED,wDAAwD;AACxD,MAAM,WAAW,oBAAoB;IACnC,gDAAgD;IAChD,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,wDAAwD;IACxD,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,uEAAuE;IACvE,IAAI,EAAE,OAAO,CAAA;IACb,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,iEAAiE;AACjE,MAAM,WAAW,qBAAqB;IACpC,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAA;IAC5C,oEAAoE;IACpE,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IACjE,0EAA0E;IAC1E,KAAK,CAAC,EAAE,iBAAiB,EAAE,CAAA;CAC5B;AAED,kEAAkE;AAClE,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAA;IACjB,sFAAsF;IACtF,YAAY,CAAC,EAAE,4BAA4B,EAAE,CAAA;IAC7C,2EAA2E;IAC3E,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACxC;AAED,4DAA4D;AAC5D,MAAM,WAAW,4BAA4B;IAC3C,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAA;IACb,8BAA8B;IAC9B,WAAW,EAAE,MAAM,CAAA;IACnB,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CACnB;AAED,sDAAsD;AACtD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,2DAA2D;IAC3D,QAAQ,EAAE,eAAe,CAAA;IACzB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,mBAAmB,CAAA;IAC5B,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,qBAAqB,CAAA;IAChC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,mBAAmB,CAAA;IAC9B,6BAA6B;IAC7B,IAAI,EAAE,OAAO,CAAA;IACb,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAA;IACf,wDAAwD;IACxD,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAA;IACjB,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC,CAAA;IACzC,sFAAsF;IACtF,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,YAAY,EAAE,CAAC,CAAC,CAAA;IAC1D,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAA;IAChB,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAA;IACnB,wEAAwE;IACxE,KAAK,CAAC,EAAE,YAAY,CAAA;CACrB;AAED,uDAAuD;AACvD,MAAM,WAAW,QAAS,SAAQ,aAAa;IAC7C,yDAAyD;IACzD,GAAG,EAAE,MAAM,CAAA;IACX,+DAA+D;IAC/D,eAAe,EAAE,MAAM,CAAA;IACvB;;;;OAIG;IACH,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IAC3B,2EAA2E;IAC3E,OAAO,CAAC,EAAE,UAAU,CAAA;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB;AAED,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,QAAQ,EAAE,CAAA;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,uFAAuF;IACvF,WAAW,EAAE,qBAAqB,EAAE,CAAA;IACpC,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAA;IACtC,2EAA2E;IAC3E,YAAY,IAAI,QAAQ,CAAA;IACxB;;;OAGG;IACH,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,eAAe,EAAE,CAAA;IAC/B,oCAAoC;IACpC,cAAc,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAAA;CACzD;AAED,uEAAuE;AACvE,MAAM,WAAW,eAAgB,SAAQ,cAAc;IACrD,2DAA2D;IAC3D,GAAG,EAAE,MAAM,CAAA;IACX,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAA;IACjB,sEAAsE;IACtE,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IAC3B,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,4DAA4D;AAC5D,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,OAAO,GAAG,SAAS,CAAA;IAC1B,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,wBAAwB;AACxB,MAAM,WAAW,kBAAkB;IACjC,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAA;IACnB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,oEAAoE;IACpE,KAAK,CAAC,EAAE,SAAS,WAAW,EAAE,CAAA;CAC/B;AAkFD;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,GAC1D,QAAQ,GAAG,SAAS,CAoEtB;AAoYD;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,QAAY,CAAA;AAE1C;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,QAAmB,CAAA;AA8DzD,wEAAwE;AACxE,eAAO,MAAM,uBAAuB,wBAAwB,CAAA;AAuG5D;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,CAmFxE;AAED,6EAA6E;AAC7E,eAAO,MAAM,qBAAqB,UAAU,CAAA;AAE5C,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,GAAG,cAAc,CAYrE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,WAAW,CAAC,EAAE,SAAS,GAAG,aAAa,CAsBpF;AAED,sEAAsE;AACtE,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAEpD"}
@@ -478,6 +478,50 @@ function resolveFrames2dEntry(manifest, dir, options) {
478
478
  phases[phase] = idleTrack;
479
479
  }
480
480
  }
481
+ // Skins: keep only entries whose idleTrack survived track resolution, and
482
+ // drop click actions whose track did not (the skin itself stays usable).
483
+ let skins;
484
+ if (block.skins !== undefined) {
485
+ const resolved = [];
486
+ for (const skin of block.skins) {
487
+ if (tracks[skin.idleTrack] === undefined) {
488
+ record('warning', 'pet ' + manifest.id + ': frames2d skin ' + JSON.stringify(skin.id) + ' idleTrack dropped; skipping');
489
+ continue;
490
+ }
491
+ let clickActions;
492
+ if (skin.clickActions !== undefined) {
493
+ const kept = [];
494
+ for (const action of skin.clickActions) {
495
+ if (tracks[action.track] === undefined) {
496
+ record('warning', 'pet ' + manifest.id + ': frames2d skin ' + JSON.stringify(skin.id)
497
+ + ' click action track ' + JSON.stringify(action.track) + ' dropped');
498
+ continue;
499
+ }
500
+ kept.push(action);
501
+ }
502
+ if (kept.length > 0)
503
+ clickActions = kept;
504
+ }
505
+ // Gameplay track overrides: drop entries whose track did not survive.
506
+ let gameplayTracks;
507
+ if (skin.gameplayTracks !== undefined) {
508
+ const kept = {};
509
+ for (const [state, gTrack] of Object.entries(skin.gameplayTracks)) {
510
+ if (tracks[gTrack] === undefined) {
511
+ record('warning', 'pet ' + manifest.id + ': frames2d skin ' + JSON.stringify(skin.id)
512
+ + ' gameplay track override ' + JSON.stringify(state) + ' -> ' + JSON.stringify(gTrack) + ' dropped');
513
+ continue;
514
+ }
515
+ kept[state] = gTrack;
516
+ }
517
+ if (Object.keys(kept).length > 0)
518
+ gameplayTracks = kept;
519
+ }
520
+ resolved.push({ ...skin, ...(clickActions === undefined ? {} : { clickActions }), ...(gameplayTracks === undefined ? {} : { gameplayTracks }) });
521
+ }
522
+ if (resolved.length > 0)
523
+ skins = resolved;
524
+ }
481
525
  const remarks = normalizePetRemarks(manifest.remarks, message => record('warning', 'pet ' + manifest.id + ': ' + message));
482
526
  // Gameplay layer: shop item icons are manifest-relative frame paths —
483
527
  // verify them, promote them to browser URLs, and add them to the servable
@@ -516,7 +560,7 @@ function resolveFrames2dEntry(manifest, dir, options) {
516
560
  displayName: manifest.displayName,
517
561
  description: manifest.description ?? '',
518
562
  renderer: 'frames2d',
519
- frames2d: { tracks, phases },
563
+ frames2d: { tracks, phases, ...(skins === undefined ? {} : { skins }) },
520
564
  ...(gameplay === undefined ? {} : { gameplay }),
521
565
  cell,
522
566
  columns: DEFAULT_PET_COLUMNS,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@linxin666/dsh-pet",
3
3
  "description": "Multi-pet companion plugin for the dsh web GUI: a registry-driven floating pet that reacts to model activity, with per-pet naming, petting/feeding interactions and an affinity score",
4
- "version": "0.3.17",
4
+ "version": "0.3.19",
5
5
  "type": "module",
6
6
  "engines": {
7
7
  "node": "^22.19.0 || >=24.0.0"
@@ -34,6 +34,7 @@
34
34
  "assets/whale",
35
35
  "assets/whale-refined",
36
36
  "assets/ouo-neko",
37
+ "assets/blue-throated-bee-eater",
37
38
  "assets/decorations",
38
39
  "contracts"
39
40
  ],
@@ -271,6 +271,70 @@ describe('GameplayHud', () => {
271
271
  expect(api.touch).not.toHaveBeenCalled()
272
272
  })
273
273
 
274
+ it('skin taps never fall through to the default touch zones', async () => {
275
+ // A skinned pet whose skin has no click actions: taps must resolve to
276
+ // the plain click boost (touch() without a zone) instead of playing the
277
+ // default pet's touch reactions (safety: skin ≠ default gameplay).
278
+ const def = petDefinition()
279
+ def.frames2d!.skins = [
280
+ { id: 'lanhainishang', label: '蓝海霓裳', idleTrack: 'lanhainishang-idle' },
281
+ ]
282
+ const store = createPetStore().create()
283
+ store.actions.setSnapshot(snapshot(gameplayView()))
284
+ const api = {
285
+ touch: vi.fn(async () => ({ ok: true, view: gameplayView() })),
286
+ setMode: vi.fn(), workTick: vi.fn(), buy: vi.fn(),
287
+ } as unknown as Harness['api']
288
+ const setTrack = vi.fn()
289
+ const bus: GameplayBus = { setTrack }
290
+ render(<GameplayHud definition={def} store={store} api={api} bus={bus} drag={createDragStream()} t={t} />)
291
+ // Select the skin through the menu card so skinIdRef is active.
292
+ await act(async () => {
293
+ bus.openCard?.()
294
+ })
295
+ fireEvent.click(screen.getByText('皮肤'))
296
+ fireEvent.click(screen.getByText('蓝海霓裳'))
297
+ await act(async () => {
298
+ bus.tap!(0.5, 0.3) // head zone → default would be the 'happy' state
299
+ })
300
+ // No zone verb, no default track: the tap is a plain boost only.
301
+ expect(api.touch).toHaveBeenCalledWith()
302
+ expect(api.touch).not.toHaveBeenCalledWith('head')
303
+ expect(setTrack).not.toHaveBeenCalledWith('happy')
304
+ })
305
+
306
+ it('plays the skin click action on a rolled hit and skips the default touch', async () => {
307
+ const def = petDefinition()
308
+ def.frames2d!.skins = [
309
+ {
310
+ id: 'lanhainishang', label: '蓝海霓裳', idleTrack: 'lanhainishang-idle',
311
+ clickActions: [{ track: 'lanhainishang-lift-skirt', probability: 0.3 }],
312
+ },
313
+ ]
314
+ const store = createPetStore().create()
315
+ store.actions.setSnapshot(snapshot(gameplayView()))
316
+ const api = {
317
+ touch: vi.fn(async () => ({ ok: true, view: gameplayView() })),
318
+ setMode: vi.fn(), workTick: vi.fn(), buy: vi.fn(),
319
+ } as unknown as Harness['api']
320
+ const setTrack = vi.fn()
321
+ const bus: GameplayBus = { setTrack }
322
+ render(<GameplayHud definition={def} store={store} api={api} bus={bus} drag={createDragStream()} t={t} />)
323
+ await act(async () => {
324
+ bus.openCard?.()
325
+ })
326
+ fireEvent.click(screen.getByText('皮肤'))
327
+ fireEvent.click(screen.getByText('蓝海霓裳'))
328
+ // Force a hit (roll < 0.3).
329
+ vi.spyOn(Math, 'random').mockReturnValue(0.1)
330
+ await act(async () => {
331
+ bus.tap!(0.5, 0.3)
332
+ })
333
+ vi.restoreAllMocks()
334
+ expect(setTrack).toHaveBeenCalledWith('lanhainishang-lift-skirt')
335
+ expect(api.touch).not.toHaveBeenCalledWith('head')
336
+ })
337
+
274
338
  it('runs the idle director: weighted act rolls on the interval', async () => {
275
339
  const h = harness()
276
340
  await act(async () => {