411 lines
19 KiB
PowerShell
411 lines
19 KiB
PowerShell
param(
|
|
[string]$ProjectRoot = (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path,
|
|
[string]$ClientPath
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
function Get-EnvValue([string]$Path, [string]$Name) {
|
|
$line = Get-Content -LiteralPath $Path | Where-Object { $_ -match "^$([regex]::Escape($Name))=" } | Select-Object -First 1
|
|
if ($line) { return $line.Substring($Name.Length + 1).Trim() }
|
|
return $null
|
|
}
|
|
|
|
if (-not $ClientPath) {
|
|
$ClientPath = Get-EnvValue (Join-Path $ProjectRoot '.env') 'WOW_HOME'
|
|
}
|
|
if (-not $ClientPath -or -not (Test-Path -LiteralPath (Join-Path $ClientPath 'Data\ruRU'))) {
|
|
throw 'A valid WoW 3.3.5 client path is required.'
|
|
}
|
|
|
|
$reader = Join-Path $ProjectRoot 'tool\target\release\mpqread.exe'
|
|
if (-not (Test-Path -LiteralPath $reader)) {
|
|
throw "MPQ reader not found: $reader"
|
|
}
|
|
|
|
$work = Join-Path $ProjectRoot 'build\customization-compat'
|
|
New-Item -ItemType Directory -Path $work -Force | Out-Null
|
|
|
|
function Export-MpqFile([string]$Archive, [string]$VirtualPath, [string]$OutputName) {
|
|
$output = Join-Path $work $OutputName
|
|
& $reader $Archive $VirtualPath $output 2>$null
|
|
if ($LASTEXITCODE -ne 0 -or -not (Test-Path -LiteralPath $output)) {
|
|
throw "Cannot extract $VirtualPath from $Archive"
|
|
}
|
|
return $output
|
|
}
|
|
|
|
function Read-U32([byte[]]$Bytes, [int]$Offset) {
|
|
return [BitConverter]::ToUInt32($Bytes, $Offset)
|
|
}
|
|
|
|
function Write-U32([byte[]]$Bytes, [int]$Field, [uint32]$Value) {
|
|
[BitConverter]::GetBytes($Value).CopyTo($Bytes, $Field * 4)
|
|
}
|
|
|
|
function Read-Wdbc([string]$Path) {
|
|
[byte[]]$bytes = [IO.File]::ReadAllBytes($Path)
|
|
if ($bytes.Length -lt 20 -or [Text.Encoding]::ASCII.GetString($bytes, 0, 4) -ne 'WDBC') {
|
|
throw "Not a WDBC file: $Path"
|
|
}
|
|
$count = Read-U32 $bytes 4
|
|
$fields = Read-U32 $bytes 8
|
|
$recordSize = Read-U32 $bytes 12
|
|
$stringSize = Read-U32 $bytes 16
|
|
$recordsEnd = 20 + ($count * $recordSize)
|
|
if ($recordsEnd + $stringSize -ne $bytes.Length) {
|
|
throw "Invalid WDBC size: $Path"
|
|
}
|
|
$records = [Collections.Generic.Dictionary[uint32,byte[]]]::new()
|
|
for ($index = 0; $index -lt $count; $index++) {
|
|
[byte[]]$row = New-Object byte[] $recordSize
|
|
[Array]::Copy($bytes, 20 + ($index * $recordSize), $row, 0, $recordSize)
|
|
$records.Add((Read-U32 $row 0), $row)
|
|
}
|
|
[byte[]]$strings = New-Object byte[] $stringSize
|
|
[Array]::Copy($bytes, $recordsEnd, $strings, 0, $stringSize)
|
|
return [pscustomobject]@{
|
|
Path = $Path
|
|
Fields = [uint32]$fields
|
|
RecordSize = [uint32]$recordSize
|
|
Records = $records
|
|
Strings = $strings
|
|
}
|
|
}
|
|
|
|
function Read-WdbcRows([string]$Path) {
|
|
[byte[]]$bytes = [IO.File]::ReadAllBytes($Path)
|
|
if ($bytes.Length -lt 20 -or [Text.Encoding]::ASCII.GetString($bytes, 0, 4) -ne 'WDBC') {
|
|
throw "Not a WDBC file: $Path"
|
|
}
|
|
$count = Read-U32 $bytes 4
|
|
$fields = Read-U32 $bytes 8
|
|
$recordSize = Read-U32 $bytes 12
|
|
$stringSize = Read-U32 $bytes 16
|
|
$recordsEnd = 20 + ($count * $recordSize)
|
|
if ($recordsEnd + $stringSize -ne $bytes.Length) {
|
|
throw "Invalid WDBC size: $Path"
|
|
}
|
|
$rows = New-Object Collections.Generic.List[byte[]]
|
|
for ($index = 0; $index -lt $count; $index++) {
|
|
[byte[]]$row = New-Object byte[] $recordSize
|
|
[Array]::Copy($bytes, 20 + ($index * $recordSize), $row, 0, $recordSize)
|
|
$rows.Add($row)
|
|
}
|
|
[byte[]]$strings = New-Object byte[] $stringSize
|
|
[Array]::Copy($bytes, $recordsEnd, $strings, 0, $stringSize)
|
|
return [pscustomobject]@{
|
|
Path = $Path
|
|
Fields = [uint32]$fields
|
|
RecordSize = [uint32]$recordSize
|
|
Rows = $rows
|
|
Strings = $strings
|
|
}
|
|
}
|
|
|
|
function Get-StringBytes($Table, [uint32]$Offset) {
|
|
if ($Offset -eq 0) { return ,([byte[]]@()) }
|
|
if ($Offset -ge $Table.Strings.Length) { throw "Bad string offset $Offset in $($Table.Path)" }
|
|
$end = [int]$Offset
|
|
while ($end -lt $Table.Strings.Length -and $Table.Strings[$end] -ne 0) { $end++ }
|
|
[byte[]]$value = New-Object byte[] ($end - [int]$Offset)
|
|
if ($value.Length) { [Array]::Copy($Table.Strings, $Offset, $value, 0, $value.Length) }
|
|
return ,$value
|
|
}
|
|
|
|
function Get-RowSignature($Table, [byte[]]$Row, [int[]]$StringFields) {
|
|
$parts = New-Object Collections.Generic.List[string]
|
|
for ($field = 0; $field -lt $Table.Fields; $field++) {
|
|
$value = Read-U32 $Row ($field * 4)
|
|
if ($StringFields -contains $field) {
|
|
$parts.Add('s:' + [Convert]::ToBase64String((Get-StringBytes $Table $value)))
|
|
} else {
|
|
$parts.Add('u:' + $value)
|
|
}
|
|
}
|
|
return $parts -join '|'
|
|
}
|
|
|
|
function Select-DeltaMerge($Base, $Old, $New, [int[]]$StringFields, [string]$Label) {
|
|
$ids = [Collections.Generic.HashSet[uint32]]::new()
|
|
foreach ($id in $Base.Records.Keys) { [void]$ids.Add($id) }
|
|
foreach ($id in $Old.Records.Keys) { [void]$ids.Add($id) }
|
|
foreach ($id in $New.Records.Keys) { [void]$ids.Add($id) }
|
|
$selected = [Collections.Generic.Dictionary[uint32,object]]::new()
|
|
$oldOnly = 0
|
|
$newChanges = 0
|
|
$conflicts = 0
|
|
foreach ($id in $ids) {
|
|
$baseRow = $null; $oldRow = $null; $newRow = $null
|
|
[void]$Base.Records.TryGetValue($id, [ref]$baseRow)
|
|
[void]$Old.Records.TryGetValue($id, [ref]$oldRow)
|
|
[void]$New.Records.TryGetValue($id, [ref]$newRow)
|
|
$baseSig = if ($baseRow) { Get-RowSignature $Base $baseRow $StringFields } else { $null }
|
|
$oldSig = if ($oldRow) { Get-RowSignature $Old $oldRow $StringFields } else { $null }
|
|
$newSig = if ($newRow) { Get-RowSignature $New $newRow $StringFields } else { $null }
|
|
$oldChanged = $oldRow -and ($null -eq $baseRow -or $oldSig -ne $baseSig)
|
|
$newChanged = $newRow -and ($null -eq $baseRow -or $newSig -ne $baseSig)
|
|
if ($oldChanged -and $newChanged -and $oldSig -ne $newSig) { $conflicts++ }
|
|
if ($newChanged) {
|
|
$selected.Add($id, [pscustomobject]@{ Table = $New; Row = $newRow })
|
|
$newChanges++
|
|
} elseif ($oldChanged) {
|
|
$selected.Add($id, [pscustomobject]@{ Table = $Old; Row = $oldRow })
|
|
$oldOnly++
|
|
} elseif ($newRow) {
|
|
$selected.Add($id, [pscustomobject]@{ Table = $New; Row = $newRow })
|
|
} elseif ($oldRow) {
|
|
$selected.Add($id, [pscustomobject]@{ Table = $Old; Row = $oldRow })
|
|
} else {
|
|
$selected.Add($id, [pscustomobject]@{ Table = $Base; Row = $baseRow })
|
|
}
|
|
}
|
|
Write-Host "${Label}: rows=$($selected.Count), retained-old=$oldOnly, applied-new=$newChanges, same-id-conflicts=$conflicts"
|
|
return $selected
|
|
}
|
|
|
|
function Select-DisplayExtraMerge($Base, $OldItem, $New) {
|
|
$ids = [Collections.Generic.HashSet[uint32]]::new()
|
|
foreach ($id in $OldItem.Records.Keys) { [void]$ids.Add($id) }
|
|
foreach ($id in $New.Records.Keys) { [void]$ids.Add($id) }
|
|
$selected = [Collections.Generic.Dictionary[uint32,object]]::new()
|
|
$itemFieldsApplied = 0
|
|
foreach ($id in $ids) {
|
|
$baseRow = $null; $oldRow = $null; $newRow = $null
|
|
[void]$Base.Records.TryGetValue($id, [ref]$baseRow)
|
|
[void]$OldItem.Records.TryGetValue($id, [ref]$oldRow)
|
|
[void]$New.Records.TryGetValue($id, [ref]$newRow)
|
|
if ($newRow) {
|
|
[byte[]]$merged = $newRow.Clone()
|
|
if ($oldRow) {
|
|
for ($field = 8; $field -le 18; $field++) {
|
|
$oldValue = Read-U32 $oldRow ($field * 4)
|
|
$baseValue = if ($baseRow) { Read-U32 $baseRow ($field * 4) } else { 0 }
|
|
if (-not $baseRow -or $oldValue -ne $baseValue) {
|
|
Write-U32 $merged $field $oldValue
|
|
$itemFieldsApplied++
|
|
}
|
|
}
|
|
}
|
|
$selected.Add($id, [pscustomobject]@{ Table = $New; Row = $merged })
|
|
} else {
|
|
$selected.Add($id, [pscustomobject]@{ Table = $OldItem; Row = $oldRow })
|
|
}
|
|
}
|
|
Write-Host "CreatureDisplayInfoExtra: rows=$($selected.Count), retained item fields from patch I=$itemFieldsApplied"
|
|
return $selected
|
|
}
|
|
|
|
function Write-Wdbc($Template, $Selected, [int[]]$StringFields, [string]$Path) {
|
|
$stringOffsets = [Collections.Generic.Dictionary[string,uint32]]::new([StringComparer]::Ordinal)
|
|
$strings = New-Object Collections.Generic.List[byte]
|
|
$strings.Add(0)
|
|
$stringOffsets.Add('', 0)
|
|
$rows = New-Object Collections.Generic.List[byte[]]
|
|
foreach ($id in ($Selected.Keys | Sort-Object)) {
|
|
$choice = $Selected[$id]
|
|
[byte[]]$row = $choice.Row.Clone()
|
|
foreach ($field in $StringFields) {
|
|
$sourceOffset = Read-U32 $row ($field * 4)
|
|
[byte[]]$value = Get-StringBytes $choice.Table $sourceOffset
|
|
$key = [Convert]::ToBase64String($value)
|
|
[uint32]$targetOffset = 0
|
|
if (-not $stringOffsets.TryGetValue($key, [ref]$targetOffset)) {
|
|
$targetOffset = [uint32]$strings.Count
|
|
if ($value.Length) { $strings.AddRange($value) }
|
|
$strings.Add(0)
|
|
$stringOffsets.Add($key, $targetOffset)
|
|
}
|
|
Write-U32 $row $field $targetOffset
|
|
}
|
|
$rows.Add($row)
|
|
}
|
|
$parent = Split-Path -Parent $Path
|
|
New-Item -ItemType Directory -Path $parent -Force | Out-Null
|
|
$stream = [IO.File]::Open($Path, [IO.FileMode]::Create, [IO.FileAccess]::Write)
|
|
try {
|
|
$writer = New-Object IO.BinaryWriter($stream)
|
|
$writer.Write([Text.Encoding]::ASCII.GetBytes('WDBC'))
|
|
$writer.Write([uint32]$rows.Count)
|
|
$writer.Write([uint32]$Template.Fields)
|
|
$writer.Write([uint32]$Template.RecordSize)
|
|
$writer.Write([uint32]$strings.Count)
|
|
foreach ($row in $rows) { $writer.Write($row) }
|
|
$writer.Write($strings.ToArray())
|
|
$writer.Flush()
|
|
} finally {
|
|
$stream.Dispose()
|
|
}
|
|
}
|
|
|
|
function Write-ExtendedBarberShopStyle($Base, $HairGeosets, $FacialHairStyles, [string]$Path) {
|
|
if ($Base.Fields -ne 40 -or $Base.RecordSize -ne 160) {
|
|
throw "Unexpected BarberShopStyle schema in $($Base.Path)"
|
|
}
|
|
if ($HairGeosets.Fields -ne 6 -or $HairGeosets.RecordSize -ne 24) {
|
|
throw "Unexpected CharHairGeosets schema in $($HairGeosets.Path)"
|
|
}
|
|
if ($FacialHairStyles.Fields -ne 8 -or $FacialHairStyles.RecordSize -ne 32) {
|
|
throw "Unexpected CharacterFacialHairStyles schema in $($FacialHairStyles.Path)"
|
|
}
|
|
|
|
$templates = [Collections.Generic.Dictionary[string,byte[]]]::new([StringComparer]::Ordinal)
|
|
$existing = [Collections.Generic.HashSet[string]]::new([StringComparer]::Ordinal)
|
|
[uint32]$nextId = 1
|
|
foreach ($row in $Base.Rows) {
|
|
$id = Read-U32 $row 0
|
|
if ($id -ge $nextId) { $nextId = $id + 1 }
|
|
$type = Read-U32 $row 4
|
|
if ($type -ne 0 -and $type -ne 2) { continue }
|
|
$race = Read-U32 $row (37 * 4)
|
|
$gender = Read-U32 $row (38 * 4)
|
|
$style = Read-U32 $row (39 * 4)
|
|
$groupKey = "${race}:${gender}:${type}"
|
|
if (-not $templates.ContainsKey($groupKey)) { $templates.Add($groupKey, $row) }
|
|
[void]$existing.Add("${groupKey}:${style}")
|
|
}
|
|
|
|
$targets = New-Object Collections.Generic.List[object]
|
|
$targetKeys = [Collections.Generic.HashSet[string]]::new([StringComparer]::Ordinal)
|
|
foreach ($row in $HairGeosets.Rows) {
|
|
$race = Read-U32 $row 4
|
|
$gender = Read-U32 $row 8
|
|
$style = Read-U32 $row 12
|
|
$groupKey = "${race}:${gender}:0"
|
|
$targetKey = "${groupKey}:${style}"
|
|
if ($templates.ContainsKey($groupKey) -and $targetKeys.Add($targetKey)) {
|
|
$targets.Add([pscustomobject]@{ Race = $race; Gender = $gender; Type = 0; Style = $style; GroupKey = $groupKey; TargetKey = $targetKey })
|
|
}
|
|
}
|
|
foreach ($row in $FacialHairStyles.Rows) {
|
|
$race = Read-U32 $row 0
|
|
$gender = Read-U32 $row 4
|
|
$style = Read-U32 $row 8
|
|
$groupKey = "${race}:${gender}:2"
|
|
$targetKey = "${groupKey}:${style}"
|
|
if ($templates.ContainsKey($groupKey) -and $targetKeys.Add($targetKey)) {
|
|
$targets.Add([pscustomobject]@{ Race = $race; Gender = $gender; Type = 2; Style = $style; GroupKey = $groupKey; TargetKey = $targetKey })
|
|
}
|
|
}
|
|
|
|
foreach ($groupKey in $templates.Keys) {
|
|
if (-not ($targets | Where-Object { $_.GroupKey -eq $groupKey } | Select-Object -First 1)) {
|
|
throw "No customization rows found for BarberShopStyle group $groupKey"
|
|
}
|
|
}
|
|
|
|
$rows = New-Object Collections.Generic.List[byte[]]
|
|
foreach ($row in $Base.Rows) { $rows.Add($row.Clone()) }
|
|
$strings = New-Object Collections.Generic.List[byte]
|
|
$strings.AddRange($Base.Strings)
|
|
$newStringOffsets = [Collections.Generic.Dictionary[string,uint32]]::new([StringComparer]::Ordinal)
|
|
$addedHair = 0
|
|
$addedFacial = 0
|
|
|
|
foreach ($target in ($targets | Sort-Object Race, Gender, Type, Style)) {
|
|
if ($existing.Contains($target.TargetKey)) { continue }
|
|
[byte[]]$row = $templates[$target.GroupKey].Clone()
|
|
Write-U32 $row 0 $nextId
|
|
Write-U32 $row 39 ([uint32]$target.Style)
|
|
|
|
# patch-ruRU-3 stores its localized display name in locale slot 8
|
|
# (field 10). New names are intentionally generic because the source
|
|
# customization archive contains no BarberShopStyle names.
|
|
for ($field = 2; $field -le 17; $field++) { Write-U32 $row $field 0 }
|
|
$label = if ($target.Type -eq 0) {
|
|
"New hairstyle $([uint32]$target.Style + 1)"
|
|
} else {
|
|
"New appearance $([uint32]$target.Style + 1)"
|
|
}
|
|
[uint32]$nameOffset = 0
|
|
if (-not $newStringOffsets.TryGetValue($label, [ref]$nameOffset)) {
|
|
$nameOffset = [uint32]$strings.Count
|
|
$strings.AddRange([Text.Encoding]::UTF8.GetBytes($label))
|
|
$strings.Add(0)
|
|
$newStringOffsets.Add($label, $nameOffset)
|
|
}
|
|
Write-U32 $row 10 $nameOffset
|
|
|
|
$rows.Add($row)
|
|
[void]$existing.Add($target.TargetKey)
|
|
$nextId++
|
|
if ($target.Type -eq 0) { $addedHair++ } else { $addedFacial++ }
|
|
}
|
|
|
|
foreach ($target in $targets) {
|
|
if (-not $existing.Contains($target.TargetKey)) {
|
|
throw "Missing generated BarberShopStyle row $($target.TargetKey)"
|
|
}
|
|
}
|
|
|
|
$parent = Split-Path -Parent $Path
|
|
New-Item -ItemType Directory -Path $parent -Force | Out-Null
|
|
$stream = [IO.File]::Open($Path, [IO.FileMode]::Create, [IO.FileAccess]::Write)
|
|
try {
|
|
$writer = New-Object IO.BinaryWriter($stream)
|
|
$writer.Write([Text.Encoding]::ASCII.GetBytes('WDBC'))
|
|
$writer.Write([uint32]$rows.Count)
|
|
$writer.Write([uint32]$Base.Fields)
|
|
$writer.Write([uint32]$Base.RecordSize)
|
|
$writer.Write([uint32]$strings.Count)
|
|
foreach ($row in $rows) { $writer.Write($row) }
|
|
$writer.Write($strings.ToArray())
|
|
$writer.Flush()
|
|
} finally {
|
|
$stream.Dispose()
|
|
}
|
|
|
|
Write-Host "BarberShopStyle: rows=$($rows.Count), added-hair=$addedHair, added-appearance=$addedFacial"
|
|
}
|
|
|
|
$locale = Join-Path $ClientPath 'Data\ruRU'
|
|
$baseArchive = Join-Path $locale 'patch-ruRU-3.MPQ'
|
|
$oldA = Join-Path $locale 'patch-ruRU-A.mpq'
|
|
$oldB = Join-Path $locale 'patch-ruRU-B.mpq'
|
|
$oldI = Join-Path $locale 'patch-ruRU-I.mpq'
|
|
$oldS = Join-Path $locale 'patch-ruRU-S.mpq'
|
|
$newB = Join-Path $ProjectRoot 'new customization mpqs\patch-b-002.mpq'
|
|
|
|
$baseModel = Read-Wdbc (Export-MpqFile $baseArchive 'DBFilesClient\CreatureModelData.dbc' 'base-CreatureModelData.dbc')
|
|
$baseDisplay = Read-Wdbc (Export-MpqFile $baseArchive 'DBFilesClient\CreatureDisplayInfo.dbc' 'base-CreatureDisplayInfo.dbc')
|
|
$baseExtra = Read-Wdbc (Export-MpqFile $baseArchive 'DBFilesClient\CreatureDisplayInfoExtra.dbc' 'base-CreatureDisplayInfoExtra.dbc')
|
|
$oldModel = Read-Wdbc (Export-MpqFile $oldA 'DBFilesClient\CreatureModelData.dbc' 'old-CreatureModelData.dbc')
|
|
$oldDisplay = Read-Wdbc (Export-MpqFile $oldB 'DBFilesClient\CreatureDisplayInfo.dbc' 'old-CreatureDisplayInfo.dbc')
|
|
$oldExtra = Read-Wdbc (Export-MpqFile $oldI 'DBFilesClient\CreatureDisplayInfoExtra.dbc' 'old-CreatureDisplayInfoExtra.dbc')
|
|
$newModel = Read-Wdbc (Export-MpqFile $newB 'DBFilesClient\CreatureModelData.dbc' 'new-CreatureModelData.dbc')
|
|
$newDisplay = Read-Wdbc (Export-MpqFile $newB 'DBFilesClient\CreatureDisplayInfo.dbc' 'new-CreatureDisplayInfo.dbc')
|
|
$newExtra = Read-Wdbc (Export-MpqFile $newB 'DBFilesClient\CreatureDisplayInfoExtra.dbc' 'new-CreatureDisplayInfoExtra.dbc')
|
|
$spellAttach = Export-MpqFile $oldS 'DBFilesClient\SpellVisualKitModelAttach.dbc' 'SpellVisualKitModelAttach.dbc'
|
|
$baseBarber = Read-WdbcRows (Export-MpqFile $baseArchive 'DBFilesClient\BarberShopStyle.dbc' 'base-BarberShopStyle.dbc')
|
|
$newHairGeosets = Read-WdbcRows (Export-MpqFile $newB 'DBFilesClient\CharHairGeosets.dbc' 'new-CharHairGeosets.dbc')
|
|
$newFacialHair = Read-WdbcRows (Export-MpqFile $newB 'DBFilesClient\CharacterFacialHairStyles.dbc' 'new-CharacterFacialHairStyles.dbc')
|
|
|
|
$modelSelected = Select-DeltaMerge $baseModel $oldModel $newModel @(2) 'CreatureModelData'
|
|
$displaySelected = Select-DeltaMerge $baseDisplay $oldDisplay $newDisplay @(6,7,8,9) 'CreatureDisplayInfo'
|
|
$extraSelected = Select-DisplayExtraMerge $baseExtra $oldExtra $newExtra
|
|
|
|
$mergedModel = Join-Path $work 'merged-CreatureModelData.dbc'
|
|
$mergedDisplay = Join-Path $work 'merged-CreatureDisplayInfo.dbc'
|
|
$mergedExtra = Join-Path $work 'merged-CreatureDisplayInfoExtra.dbc'
|
|
$extendedBarber = Join-Path $work 'extended-BarberShopStyle.dbc'
|
|
Write-Wdbc $newModel $modelSelected @(2) $mergedModel
|
|
Write-Wdbc $newDisplay $displaySelected @(6,7,8,9) $mergedDisplay
|
|
Write-Wdbc $newExtra $extraSelected @(20) $mergedExtra
|
|
Write-ExtendedBarberShopStyle $baseBarber $newHairGeosets $newFacialHair $extendedBarber
|
|
|
|
$baseTarget = Join-Path $ProjectRoot 'assets\dbc\3.3.5a'
|
|
$compatTarget = Join-Path $ProjectRoot 'src\Data\ruRU\patch-ruRU-Z\DBFilesClient'
|
|
New-Item -ItemType Directory -Path $compatTarget -Force | Out-Null
|
|
Copy-Item -LiteralPath $mergedModel -Destination (Join-Path $baseTarget 'CreatureModelData.dbc') -Force
|
|
Copy-Item -LiteralPath $mergedDisplay -Destination (Join-Path $baseTarget 'CreatureDisplayInfo.dbc') -Force
|
|
Copy-Item -LiteralPath $mergedExtra -Destination (Join-Path $compatTarget 'CreatureDisplayInfoExtra.dbc') -Force
|
|
Copy-Item -LiteralPath $spellAttach -Destination (Join-Path $compatTarget 'SpellVisualKitModelAttach.dbc') -Force
|
|
Copy-Item -LiteralPath $extendedBarber -Destination (Join-Path $compatTarget 'BarberShopStyle.dbc') -Force
|
|
|
|
$serverTarget = Join-Path $work 'server-dbc'
|
|
New-Item -ItemType Directory -Path $serverTarget -Force | Out-Null
|
|
Copy-Item -LiteralPath $extendedBarber -Destination (Join-Path $serverTarget 'BarberShopStyle.dbc') -Force
|
|
|
|
Write-Host "Compatibility sources updated in $baseTarget and $compatTarget"
|
|
Write-Host "Matching server DBC staged in $serverTarget"
|