Add formal enemies, remaining formal partners and synthesized UI SFX

- UI SFX v3: procedurally synthesized one-shots (Tools/synth_ui_sfx.py) wired to
  buttons, rewards, errors and red dots via UiSfx, gated by the SFX setting.
- Five formal enemies (Hornlet, Dashlet, Shellhorn, HornCaptain, GreatHorn):
  Hunyuan 50k -> 2000-tri XPbr, DGXA TokenRig, Idle/Walk/Attack, nested per type
  in PrototypeArena; PrototypeBattle.Enemy gains presentation-only Moving/Strikes.
- Formal partners for all ten pets in the arena and portraits, including new
  VineSprite, ThunderLeopard and TideWhale.
- Pipeline fixes: reject local TokenRig fallback, drop loose mesh islands,
  configurable Unity run_script timeout, companion static stage.
- Also includes concurrent work from another tool in this working tree
  (FlameLion, enemy combat FX, challenge mode, home explorer, server updates).
- Resources registered in Doc/ResDesc_*.md; verified on isolated :18081.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
udx
2026-10-21 12:23:55 +08:00
co-authored by Claude Opus 5.5
parent 6c64210331
commit 89e0fa246f
780 changed files with 7117051 additions and 15906 deletions
+12 -4
View File
@@ -1,6 +1,7 @@
"""Rig a same-character GLB on configured DGXA and retain source provenance.
Only explicit --generate starts inference. Reuses a byte-verified cached result.
--backend remote requires a verified remote receipt and refuses local fallback.
The approved low-poly mesh is preserved and receives these weights later.
"""
import argparse
@@ -22,6 +23,7 @@ def main():
parser.add_argument('--source',type=Path,required=True)
parser.add_argument('--out',type=Path,required=True)
parser.add_argument('--generate',action='store_true')
parser.add_argument('--backend',choices=('auto','remote'),default='auto',help='remote refuses an implicit local fallback')
args=parser.parse_args()
source=args.source.resolve();out=args.out.resolve()
if not source.is_relative_to(REPO) or not out.is_relative_to(REPO):
@@ -31,19 +33,25 @@ def main():
source_hash=digest(source);receipt=out/'rig_request.json';target=out/'rigged.glb'
if receipt.is_file() and target.is_file():
record=json.loads(receipt.read_text(encoding='utf-8'))
if record['source_sha256']==source_hash and record['rig_sha256']==digest(target):
if record['source_sha256']==source_hash and record['rig_sha256']==digest(target) and (args.backend=='auto' or record.get('backend')=='remote'):
print('PASS cached same-source rig',target);return
if not args.generate:
parser.error('No verified cache. --generate explicitly requests DGXA rigging')
sys.path.insert(0,str(REPO/'Tools'))
from dgx3d_animal_pipeline import _ensure_llm3d
_ensure_llm3d()
from backend.tokenrig_runner import run_tokenrig
from backend.tokenrig_runner import run_tokenrig,_run_remote
stage=out/'generations'/uuid.uuid4().hex;stage.mkdir(parents=True)
result=Path(run_tokenrig(source,stage,stage/'tokenrig.log',skeleton_template='original'))
runner=_run_remote if args.backend=='remote' else run_tokenrig
result=Path(runner(source,stage,stage/'tokenrig.log',skeleton_template='original'))
if not result.is_file() or result.stat().st_size<100:
raise RuntimeError('Missing TokenRig result')
record=dict(status='generated',source=str(source.relative_to(REPO)),source_sha256=source_hash,
# The local SkinTokens fallback produced a degenerate single-chain skeleton (Hornlet 2026-10-21); only accept DGXA runs.
if 'tokenrig remote failed' in (stage/'tokenrig.log').read_text(encoding='utf-8',errors='replace'):
raise RuntimeError('TokenRig fell back to local SkinTokens; reconnect DGXA (Tools/dgx_ensure_ready.py) and retry')
log=(stage/'tokenrig.log').read_text(encoding='utf-8',errors='replace')
backend='local' if 'tokenrig local:' in log else 'remote'
record=dict(status='generated',backend=backend,source=str(source.relative_to(REPO)),source_sha256=source_hash,
rig_sha256=digest(result),template='original',stage=str(stage.relative_to(REPO)),
generated_at_utc=time.strftime('%Y-%m-%dT%H:%M:%SZ',time.gmtime()))
shutil.copy2(result,target)