Add rank, friends, fishing, and camp treasure with T2 studio models and skill presentation.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
udx
2026-10-21 23:01:31 +08:00
co-authored by Cursor
parent 89e0fa246f
commit 079313fb06
677 changed files with 395371 additions and 9692 deletions
+15 -3
View File
@@ -1,6 +1,7 @@
"""Validate proposed battle skill contracts without touching the running game."""
from __future__ import annotations
import argparse
import hashlib
from decimal import Decimal,ROUND_CEILING
import json
from pathlib import Path,PurePosixPath
@@ -79,21 +80,32 @@ def validate(plan,view,sound,gameplay,root=ROOT):
if cue['kind']=='animation':
mark=assets[cue['asset']]['releaseNormalized']
require(abs(mark-release/(release+recovery))<=1/(release+recovery),'Animation release marker is not aligned: '+skill['id'])
require(sound['status']=='planned_not_generated','SFX design manifest must not claim generated assets')
require(sound['status'] in ('planned_not_generated','partially_generated','generated'),'Invalid SFX production status')
require(1<=sound['maxInflight']<=4,'TangoFlux in-flight limit exceeds guide')
require(sound['sourceFormat']==dict(container='wav',sampleRate=44100,channels=2),'TangoFlux source format mismatch')
items=index(sound['items'],'SFX')
generated=0
for item in items.values():
require(item['prompt'].isascii() and 0<len(item['prompt'])<=2000,'SFX prompt must be specific English within service limit')
require(1<=item.get('duration',sound['defaults']['duration'])<=30,'TangoFlux duration must be 1..30 seconds')
require(type(item['seed']) is int,'Reproducible SFX seed required')
production=item.get('production')
if production:
output=root/production['output'];receipt=root/production['receipt']
require(output.is_file() and receipt.is_file(),'Generated SFX output/receipt missing')
require(hashlib.sha256(output.read_bytes()).hexdigest()==production['sha256'],'Generated SFX hash mismatch')
rows=json.loads(receipt.read_text(encoding='utf-8'))['items']
require(any(r['id']==item['id'] and r['outputSha256']==production['sha256'] and r['job']['status']=='succeeded' for r in rows),'Generated SFX receipt mismatch')
generated+=1
expected='planned_not_generated' if generated==0 else 'generated' if generated==len(items) else 'partially_generated'
require(sound['status']==expected,'SFX production status does not match receipts')
for asset in assets.values():
if asset['type']=='sfx':require(PurePosixPath(asset['path']).stem in items,'SFX production recipe missing: '+asset['id'])
return dict(status='design_contract_validated',runtimeIntegrated=False,generatedAudio=False,
return dict(status='design_contract_validated',runtimeIntegrated=False,generatedAudio=generated==len(items),generatedSfxCount=generated,
skills=len(skills),pets=len(gameplay['pets']),enemies=len(gameplay['enemies']),stages=len(gameplay['stages']),
presentationProfiles=len(profiles),existingAssets=sum(a['status']=='existing' for a in assets.values()),
plannedAssets=sum(a['status']=='planned' for a in assets.values()),sfxRecipes=len(items),
note='Configuration and reference validation only; no combat runtime or audio generation executed')
note='Design proposal validation only; formal runtime integration is validated separately by validate_skill_runtime.py')
def load(path):return json.loads(path.read_text(encoding='utf-8-sig'))