Set-Location 'k:\ghidra\crusader_map_viewer\map_renderer' function Get-Shape([object]$item) { if ($null -eq $item -or $null -eq $item.shapeDefId) { return $null } if ($item.shapeDefId -match '^shape:(\d+)$') { return [int]$Matches[1] } return $null } function Get-Qlo([object]$item) { if ($null -eq $item -or $null -eq $item.quality) { return $null } return ([int]$item.quality) -band 0xff } function Get-Distance([object]$a, [object]$b) { $dx = [double]$a.world.x - [double]$b.world.x $dy = [double]$a.world.y - [double]$b.world.y return [math]::Sqrt(($dx * $dx) + ($dy * $dy)) } $pairs = @( @{ Name = 'BRO_BOOT->SPANEL'; Source = 0x04fe; Target = 0x03aa; Distance = 768 }, @{ Name = 'NPC_ONLY->CMD_LINK'; Source = 0x0366; Target = 0x04b1; Distance = 768 }, @{ Name = 'DEATHBOX->CMD_LINK'; Source = 0x04e7; Target = 0x04b1; Distance = 768 }, @{ Name = 'NPC_ONLY->TRIGGERISH'; Source = 0x0366; Target = 0x0361; Distance = 768 } ) $sceneFiles = Get-ChildItem '.\site\data\maps' -Recurse -Filter 'scene.json' | Sort-Object FullName $lines = New-Object System.Collections.Generic.List[string] foreach ($pair in $pairs) { $matchedSources = 0 $sourceCount = 0 $linkCount = 0 $examples = New-Object System.Collections.Generic.List[string] foreach ($file in $sceneFiles) { $scene = Get-Content $file.FullName -Raw | ConvertFrom-Json $items = @($scene.items) $sources = @($items | Where-Object { (Get-Shape $_) -eq $pair.Source }) if ($sources.Count -eq 0) { continue } $targets = @($items | Where-Object { (Get-Shape $_) -eq $pair.Target }) foreach ($source in $sources) { $sourceCount += 1 $qlo = Get-Qlo $source if ($null -eq $qlo) { continue } $matches = @($targets | Where-Object { (Get-Qlo $_) -eq $qlo -and (Get-Distance $source $_) -le $pair.Distance }) if ($matches.Count -gt 0) { $matchedSources += 1 $linkCount += $matches.Count if ($examples.Count -lt 6) { $examples.Add(('{0}/{1}: source={2} qlo={3} targetIds={4}' -f $file.Directory.Parent.Name, $file.Directory.Name, $source.id, $qlo, (($matches | ForEach-Object { $_.id }) -join ','))) } } } } $rate = if ($sourceCount -gt 0) { [math]::Round(($matchedSources / $sourceCount) * 100, 1) } else { 0 } $lines.Add(('PAIR {0}' -f $pair.Name)) $lines.Add(('sources={0} matched={1} rate={2}% links={3}' -f $sourceCount, $matchedSources, $rate, $linkCount)) foreach ($example in $examples) { $lines.Add($example) } $lines.Add('') } $lines | Set-Content 'k:\ghidra\Crusader_Decomp\_tmp_scene_link_scan.txt'