Clean actor runtime baseline after motion fix
This commit is contained in:
@@ -165,17 +165,15 @@ It also now includes an actor/content validator:
|
||||
|
||||
- `scripts/validate_actor_scenarios.py`
|
||||
|
||||
On the current real client runtime, the full actor validator reports five data
|
||||
issues that look like pre-existing content inconsistencies rather than `.m2p`
|
||||
loader regressions:
|
||||
The current actor validator now resolves real `MotionFileName` targets from
|
||||
`.msa` files instead of assuming every motion uses a same-name local `.gr2`.
|
||||
That removed the old false positives from redirected actor motions, and the
|
||||
remaining `orc_lord` mismatch was fixed in the runtime assets by correcting
|
||||
`30_1.msa` to point to `30_1.GR2`.
|
||||
|
||||
- `Monster/misterious_diseased_host` missing `25.gr2`
|
||||
- `Monster/skeleton_king` missing `24.gr2`
|
||||
- `Monster/thief2` missing `03_1.gr2`
|
||||
- `NPC/christmas_tree` missing `wait.gr2`
|
||||
- `NPC/guild_war_flag` missing `wait.gr2`
|
||||
On the current real client runtime, the actor validator now passes cleanly.
|
||||
|
||||
The expanded validator did not find additional breakage in:
|
||||
It still verifies:
|
||||
|
||||
- `.msm` base model references
|
||||
- `.msm` effect script references
|
||||
@@ -205,11 +203,11 @@ previous cross-pack and wrong-path sound references were cleaned up in the
|
||||
runtime assets, and the last remaining `combo7.wav` issue was resolved by
|
||||
aligning `combo_07.mss` with the byte-identical `combo_08` motion variant.
|
||||
|
||||
Those current actor and effect findings are also recorded in:
|
||||
The current effect findings are recorded in:
|
||||
|
||||
- `known_issues/runtime_known_issues.json`
|
||||
|
||||
The current audio findings are recorded there as well.
|
||||
Actor and audio are currently clean in that baseline.
|
||||
|
||||
That file is now the shared runtime baseline used by the validators and the
|
||||
aggregated release gate.
|
||||
|
||||
@@ -208,7 +208,8 @@ python3 scripts/validate_actor_scenarios.py \
|
||||
This validator checks local actor integrity for `Monster`, `NPC`, and `PC`:
|
||||
|
||||
- `motlist.txt` motion files exist
|
||||
- each motion has a paired `.gr2` in the same actor directory
|
||||
- each motion resolves to a valid `.gr2`, including redirected `MotionFileName`
|
||||
targets in `.msa`
|
||||
- `.msm` base model targets resolve against the runtime asset set
|
||||
- `.msm` effect script targets resolve against the runtime asset set
|
||||
- `.msm` default hit effect targets resolve against the runtime asset set
|
||||
@@ -275,7 +276,7 @@ Strict behavior:
|
||||
Current baseline on the real runtime:
|
||||
|
||||
- `world`: `0`
|
||||
- `actor`: `5`
|
||||
- `actor`: `0`
|
||||
- `effect`: `12`
|
||||
- `audio`: `0`
|
||||
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
{
|
||||
"world": [],
|
||||
"actor": [
|
||||
"actor:paired_model:ymir work/monster/misterious_diseased_host:25.gr2",
|
||||
"actor:paired_model:ymir work/monster/skeleton_king:24.gr2",
|
||||
"actor:paired_model:ymir work/monster/thief2:03_1.gr2",
|
||||
"actor:paired_model:ymir work/npc/christmas_tree:wait.gr2",
|
||||
"actor:paired_model:ymir work/npc/guild_war_flag:wait.gr2"
|
||||
],
|
||||
"actor": [],
|
||||
"effect": [
|
||||
"effect:reference:ymir work/effect/background/moonlight_eff_bat.mse:ymir work/effect/pet/halloween_2022_coffin_bat_01.dds",
|
||||
"effect:reference:ymir work/effect/background/moonlight_eff_bat.mse:ymir work/effect/pet/halloween_2022_coffin_bat_02.dds",
|
||||
|
||||
@@ -15,6 +15,7 @@ BASE_MODEL_RE = re.compile(r'^BaseModelFileName\s+"([^"]+)"', re.IGNORECASE)
|
||||
EFFECT_SCRIPT_RE = re.compile(r'^EffectScriptName\s+"([^"]+)"', re.IGNORECASE)
|
||||
DEFAULT_HIT_EFFECT_RE = re.compile(r'^DefaultHitEffectFileName\s+"([^"]*)"', re.IGNORECASE)
|
||||
DEFAULT_HIT_SOUND_RE = re.compile(r'^DefaultHitSoundFileName\s+"([^"]*)"', re.IGNORECASE)
|
||||
MOTION_FILE_RE = re.compile(r'^MotionFileName\s+"([^"]+)"', re.IGNORECASE)
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -110,6 +111,15 @@ def parse_motlist(path: Path) -> list[str]:
|
||||
return motions
|
||||
|
||||
|
||||
def parse_msa_motion_file(path: Path) -> str | None:
|
||||
for raw_line in path.read_text(encoding="utf-8", errors="ignore").splitlines():
|
||||
line = raw_line.strip()
|
||||
match = MOTION_FILE_RE.match(line)
|
||||
if match:
|
||||
return match.group(1)
|
||||
return None
|
||||
|
||||
|
||||
def parse_msm_references(path: Path) -> tuple[str | None, list[str], list[str], list[str]]:
|
||||
base_model: str | None = None
|
||||
effect_scripts: list[str] = []
|
||||
@@ -146,6 +156,13 @@ def validate_actor_dir(pack: str, pack_dir: Path, actor_dir: Path, asset_index:
|
||||
if not msa_path.is_file():
|
||||
missing_msa.append(motion)
|
||||
continue
|
||||
motion_file = parse_msa_motion_file(msa_path)
|
||||
if motion_file:
|
||||
resolved_motion = normalize_virtual_path(motion_file)
|
||||
if resolved_motion not in asset_index:
|
||||
missing_gr2_for_motions.append(resolved_motion)
|
||||
continue
|
||||
|
||||
gr2_name = Path(motion).with_suffix(".gr2").name
|
||||
if not (actor_dir / gr2_name).is_file():
|
||||
missing_gr2_for_motions.append(gr2_name)
|
||||
@@ -234,7 +251,8 @@ def main() -> int:
|
||||
failures.append(message)
|
||||
issue_map[issue_id] = message
|
||||
for gr2_name in check.missing_gr2_for_motions:
|
||||
issue_id = f"actor:paired_model:{check.actor_dir}:{gr2_name.lower()}"
|
||||
normalized_gr2 = normalize_virtual_path(gr2_name)
|
||||
issue_id = f"actor:paired_model:{check.actor_dir}:{normalized_gr2}"
|
||||
message = f"{check.actor_dir}: missing paired model {gr2_name}"
|
||||
failures.append(message)
|
||||
issue_map[issue_id] = message
|
||||
|
||||
Reference in New Issue
Block a user