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
+59
View File
@@ -0,0 +1,59 @@
"""Audit the formal partner presentation bank and all nine TangoFlux sound receipts."""
import hashlib
import json
from pathlib import Path
import numpy as np
from scipy.io import wavfile
ROOT=Path(__file__).resolve().parents[1]
DESIGN=ROOT/'Doc/Design/Combat/PartnerSkills'
def load(path):return json.loads(path.read_text(encoding='utf-8-sig'))
def digest(path):return hashlib.sha256(path.read_bytes()).hexdigest()
def main():
plan=load(ROOT/'Config/Combat/partner_presentations_v1.json')
game=load(ROOT/'Config/Gameplay/greenfield.json')
assert len(plan['profiles'])==len(game['pets'])==10
assert [p['pet'] for p in plan['profiles']]==list(range(10))
assert [e['id'] for e in plan['effects']]==list(range(5,15))
assert len(set(e['path'] for e in plan['effects']))==10
for e in plan['effects']:
assert (ROOT/'AIClient'/e['path']).is_file()
assert e['poolSize']==4 and .1<=e['lifetime']<=1
assert e['loop']==(e['id'] in (5,14))
assert e['beam']==(e['id'] in (8,13))
for p in plan['profiles']:
for name,value in p.items():
if name.endswith('Effect'):assert -1<=value<15
if name.endswith('Sound'):assert -1<=value<9
assert p['abilityEffect']==p['pet']+5
manifest=load(ROOT/'Doc/Design/Sound/BattleSkills/manifest.json')
assert manifest['status']=='generated'
assert {i['id'] for i in manifest['items']}=={'Sfx_'+s for s in plan['soundIds']}
rows=[]
for item in manifest['items']:
production=item['production']
receipt=load(ROOT/production['receipt'])
record=next(r for r in receipt['items'] if r['id']==item['id'])
target=ROOT/production['output']
assert digest(target)==production['sha256']==record['outputSha256']
assert digest(ROOT/record['source'])==record['sourceSha256']
assert hashlib.sha256(json.dumps(record['request'],sort_keys=True).encode()).hexdigest()==record['requestHash']
assert record['job']['status']=='succeeded'
assert record['job']['seed']==record['request']['seed']
if item['id'] in ('Sfx_Heal','Sfx_Slow','Sfx_Lightning','Sfx_EnemyHit'):assert item['seed']==record['request']['seed']
rate,samples=wavfile.read(target);x=samples.astype(float)/32768
assert rate==44100 and samples.dtype==np.int16 and x.ndim==2 and x.shape[1]==2
assert .1<len(x)/rate<1 and np.isfinite(x).all()
peak=float(np.abs(x).max());rms=float(20*np.log10(np.sqrt(np.mean(x*x))))
assert peak<.95 and np.abs(x[:4410]).max()>.05 and np.abs(x[-10:]).max()<.003 and rms>-36
rows.append(dict(id=item['id'],seconds=len(x)/rate,peakDb=20*np.log10(peak),rmsDb=rms,
clippedSamples=int(np.sum(np.abs(x)>=.999)),sha256=digest(target),actualSeed=record['request']['seed']))
assert len(rows)==9
result=dict(status='pass',profiles=10,signaturePrefabs=10,poolRoots=76,voices=8,audio=rows,
subjectiveListening='not_asserted',releaseLicenseReview=manifest['releaseLicenseReview'])
DESIGN.mkdir(parents=True,exist_ok=True)
(DESIGN/'audio_config_validation.json').write_text(json.dumps(result,indent=2)+'\n',encoding='utf-8')
print('PASS ten partner profiles and prefabs; nine PCM sounds, source/request/output hashes, onset, fades, level, zero clipping')
if __name__=='__main__':main()