mirror of
https://github.com/Sarjuuk/aowow.git
synced 2025-11-29 15:58:16 +08:00
Setup/img-maps
* script cleanup * fixed subzone generation and made color less garish * fixed alphamap generation and alphamapcheck not pointing to the same path * fixed padding UtilityScript args with unexpected var types
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -3,8 +3,8 @@
|
||||
|
||||
# cache
|
||||
/cache/template/*
|
||||
/setup/generated/alphaMaps/*.png
|
||||
/cache/firstrun
|
||||
/cache/alphaMaps/*
|
||||
/cache/setup/*
|
||||
|
||||
# extract from MPQ
|
||||
/setup/mpqdata/*
|
||||
|
||||
@@ -244,7 +244,7 @@ class Game
|
||||
|
||||
private static function alphaMapCheck(int $areaId, array &$set) : bool
|
||||
{
|
||||
$file = 'setup/generated/alphaMaps/'.$areaId.'.png';
|
||||
$file = 'cache/alphaMaps/'.$areaId.'.png';
|
||||
if (!file_exists($file)) // file does not exist (probably instanced area)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -1151,6 +1151,7 @@ $lang = array(
|
||||
'Miscellaneous' => "Diverse",
|
||||
'Azeroth' => "Azeroth",
|
||||
'CosmicMap' => "Kosmische Karte",
|
||||
'floorN' => "%d. Stockwerk"
|
||||
),
|
||||
'privileges' => array(
|
||||
'main' => "Auf unserer Seite könnt Ihr <a href=\"?reputation\">Ruf</a> erringen. Hauptsächlich erringt man Ruf dadurch, dass Eure Kommentare positiv bewertet werden.<br><br>Das heißt, Euer Ruf hängt in gewissem Maße davon ab, wie sehr Ihr der Community beiträgt.<br><br>Mit dem Sammeln von Ruf verdient Ihr Euch auch das Vertrauen der Gemeinschaft ein, und Ihr erhält Privilegien. Unten könnt Ihr eine vollständige Liste einsehen.",
|
||||
|
||||
@@ -1152,6 +1152,7 @@ $lang = array(
|
||||
'Miscellaneous' => "Miscellaneous",
|
||||
'Azeroth' => "Azeroth",
|
||||
'CosmicMap' => "Cosmic Map",
|
||||
'floorN' => "Level %d"
|
||||
),
|
||||
'privileges' => array(
|
||||
'main' => "Here on our Site you can generate <a href=\"?reputation\">reputation</a>. The main way to generate it is to get your comments upvotes.<br><br>So, reputation is a rough measure of how much you contributed to the community.<br><br>As you amass reputation you earn the community's trust and you will be granted with additional privileges. You can find a full list below.",
|
||||
|
||||
@@ -1151,6 +1151,7 @@ $lang = array(
|
||||
'Miscellaneous' => "Miscelánea",
|
||||
'Azeroth' => "Azeroth",
|
||||
'CosmicMap' => "Mapa cósmico",
|
||||
'floorN' => "Nivel %d"
|
||||
),
|
||||
'privileges' => array(
|
||||
'main' => "Aquí, en AoWoW, puedes conseguir <a href=\"?reputation\">reputación</a>. La forma principal de conseguirla es conseguir que tus comentarios sean votados de forma positiva.<br /><br />Así pues, la reputación es algo que mide, más o menos, cúanto has contribuido a la comunidad.<br /><br />Conforme consigues reputación, te ganas la confianza de la comunidad y tendrás privilegios adicionales. Puedes encontrar una lista completa debajo.",
|
||||
|
||||
@@ -1151,6 +1151,7 @@ $lang = array(
|
||||
'Miscellaneous' => "Divers",
|
||||
'Azeroth' => "Azeroth",
|
||||
'CosmicMap' => "Carte cosmique",
|
||||
'floorN' => "Plancher %d"
|
||||
),
|
||||
'privileges' => array(
|
||||
'main' => "Sur AoWoW, vous pouvez accumuler de la <a href=\"?reputation\">réputation</a>. Le principal moyen d'en accumuler est d'avoir un score élevé pour vos commentaires.<br><br>Ainsi, la réputation est une vision sommaire de vos contributions à la communauté.<br><br>En amassant de la réputation, vous gagnez le respect de la communauté et vous obtiendrez certains privilèges. Vous pouvez en trouver la liste complète ci-dessous.",
|
||||
|
||||
@@ -1151,6 +1151,7 @@ $lang = array(
|
||||
'Miscellaneous' => "Разное",
|
||||
'Azeroth' => "Азерот",
|
||||
'CosmicMap' => "Звёздная карта",
|
||||
'floorN' => "Уровень %d"
|
||||
),
|
||||
'privileges' => array(
|
||||
'main' => "Здесь на AoWoW вы можете зарабатывать <a href=\"?reputation\">репутацию</a>. Основной источник получения репутации — увеличение рейтинга ваших комментариев другими пользователями.<br><br>Репутация примерно измеряет количество вашего вклада в сообщество.<br><br>По мере того, как вы зарабатываете репутацию, вы получаете доверие сообщества и особые привилегии. Полный список привилегий расположен ниже.",
|
||||
|
||||
@@ -1150,7 +1150,8 @@ $lang = array(
|
||||
'Battlegrounds' => "战场",
|
||||
'Miscellaneous' => "其他",
|
||||
'Azeroth' => "艾泽拉斯",
|
||||
'CosmicMap' => "宇宙地图"
|
||||
'CosmicMap' => "宇宙地图",
|
||||
'floorN' => "[Level %d]"
|
||||
),
|
||||
'privileges' => array(
|
||||
'main' => "在我们的网站上,你可以通过 <a href=\"?reputation\">声望</a>. 来获取特权。获取声望的主要途径是获得评论的赞同。<br><br>因此,声望是衡量你对社区的贡献程度的一个大致指标。<br><br>随着声望的积累,你将获得社区的信任,并被赋予额外的特权。以下是完整的特权列表。",
|
||||
|
||||
@@ -341,7 +341,7 @@ class CLISetup
|
||||
return false;
|
||||
}
|
||||
|
||||
$args = array_pad($args, 4, []);
|
||||
$args = array_pad($args, 4, null);
|
||||
|
||||
$success = $us->run($args);
|
||||
|
||||
|
||||
@@ -483,7 +483,7 @@ class DBC
|
||||
|
||||
$this->writeToDB();
|
||||
|
||||
$this->endCLean();
|
||||
$this->endClean();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
private const A_THRESHOLD = 95; // alpha threshold to define subZones: set it too low and you have unspawnable areas inside a zone; set it too high and the border regions overlap
|
||||
private const COLOR_WHITE = [255, 255, 255]; // rgb
|
||||
private const COLOR_BLACK = [ 0, 0, 0]; // rgb
|
||||
private const COLOR_SUBZONE = [255, 64, 192, 64]; // rgba
|
||||
private const COLOR_SUBZONE = [ 0, 230, 255, 74]; // rgba - note: rgb is 0-255, a is 0-127
|
||||
|
||||
private const AREA_FLAG_DEFAULT_FLOOR_TERRAIN = 0x004; // Default Dungeon Floor is Terrain
|
||||
private const AREA_FLAG_NO_DEFAULT_FLOOR = 0x100; // Don't use Default Dungeon Floor (typically 1)
|
||||
@@ -54,22 +54,13 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
[9, 10, 11, 12]
|
||||
);
|
||||
|
||||
private const LEVEL_N = array( // todo: move this hackfix to locales?
|
||||
LOCALE_EN => 'Level %d',
|
||||
LOCALE_FR => 'Plancher %d',
|
||||
LOCALE_DE => '%d. Stockwerk',
|
||||
LOCALE_CN => '[Level %d]',
|
||||
LOCALE_ES => 'Nivel %d',
|
||||
LOCALE_RU => 'Уровень %d'
|
||||
);
|
||||
|
||||
private const MAP_FILE_PATTERN = '/((\w{4})\/interface\/worldmap(?:\/microdungeon\/([^\/]+))?\/([^\/]+)\/)(\4)(?:(\d{1,2})_)?(\d{1,2})\.(?:blp|png)/i';
|
||||
|
||||
// src, resourcePath, localized, [tileOrder], [[dest, destW, destH]]
|
||||
private $genSteps = array(
|
||||
self::M_MAPS => ['WorldMap/', null, true, self::TILEORDER, self::DEST_DIRS ],
|
||||
self::M_SPAWNS => ['WorldMap/', null, true, self::TILEORDER, [['cache/setup/alphaMaps/', 0, 0]]],
|
||||
self::M_SUBZONES => ['WorldMap/', null, true, self::TILEORDER, self::DEST_DIRS ]
|
||||
self::M_MAPS => ['WorldMap/', null, true, self::TILEORDER, self::DEST_DIRS ],
|
||||
self::M_SPAWNS => ['WorldMap/', null, true, self::TILEORDER, [['cache/alphaMaps/', 0, 0]]],
|
||||
self::M_SUBZONES => ['WorldMap/', null, true, self::TILEORDER, self::DEST_DIRS ]
|
||||
);
|
||||
|
||||
private $progress = 0;
|
||||
@@ -114,8 +105,8 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
$mask |= self::M_MAPS;
|
||||
|
||||
// unless manually prompted drop spawnmap generation if 90% of spawns have core generated area info
|
||||
$npcPct = DB::World()->selectCell('SELECT SUM(IF(zoneId > 0, 1, 0)) / COUNT(*) FROM creature') ?? 0;
|
||||
$goPct = DB::World()->selectCell('SELECT SUM(IF(zoneId > 0, 1, 0)) / COUNT(*) FROM gameobject') ?? 0;
|
||||
$npcPct = DB::World()->selectCell('SELECT SUM(IF(`zoneId` > 0, 1, 0)) / COUNT(*) FROM creature') ?? 0;
|
||||
$goPct = DB::World()->selectCell('SELECT SUM(IF(`zoneId` > 0, 1, 0)) / COUNT(*) FROM gameobject') ?? 0;
|
||||
|
||||
if (!($mask & self::M_SPAWNS) && $npcPct > 0.9 && $goPct > 0.9)
|
||||
$this->modeMask &= ~self::M_SPAWNS;
|
||||
@@ -132,7 +123,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
|
||||
if (!$this->checkSourceDirs())
|
||||
{
|
||||
CLI::write('one or more source directories are missing:', CLI::LOG_ERROR);
|
||||
CLI::write('[img-maps] One or more source directories are missing.', CLI::LOG_ERROR);
|
||||
$this->success = false;
|
||||
return false;
|
||||
}
|
||||
@@ -190,15 +181,15 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
{
|
||||
ksort($floorData);
|
||||
|
||||
$overlay = null;
|
||||
$resOverlay = null;
|
||||
if (!$isMultilevel)
|
||||
$overlay = $this->generateOverlay($wmaId, $name, $basePath);
|
||||
$resOverlay = $this->generateOverlay($wmaId, $name, $basePath);
|
||||
|
||||
// create spawn-maps if wanted
|
||||
if ($overlay && $this->modeMask & self::M_SPAWNS)
|
||||
if ($resOverlay && $this->modeMask & self::M_SPAWNS)
|
||||
{
|
||||
$outFile = $this->genSteps[self::M_SPAWNS][self::$GEN_IDX_DEST_INFO][0][0] . $zoneId . '.png';
|
||||
if (!$this->generateSpawnMap($overlay, $outFile))
|
||||
if (!$this->buildSpawnMap($resOverlay, $outFile))
|
||||
$this->success = false;
|
||||
}
|
||||
|
||||
@@ -293,84 +284,16 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
continue;
|
||||
}
|
||||
|
||||
$overlay = null;
|
||||
$resOverlay = null;
|
||||
|
||||
// zone has overlays (is in open world; is not multilevel)
|
||||
if (isset($this->wmOverlays[$wmaId]))
|
||||
{
|
||||
$overlay = $this->createAlphaImage(self::MAP_W, self::MAP_H);
|
||||
|
||||
foreach ($this->wmOverlays[$wmaId] as &$row)
|
||||
{
|
||||
$i = 1;
|
||||
$y = 0;
|
||||
while ($y < $row['h'])
|
||||
{
|
||||
$x = 0;
|
||||
while ($x < $row['w'])
|
||||
{
|
||||
$img = $this->loadImageFile($srcPath . '/' . $row['textureString'] . $i);
|
||||
if (!$img)
|
||||
{
|
||||
CLI::write(' - complexImg: tile '.$srcPath.'/'.$row['textureString'].$i.'.blp missing.', CLI::LOG_ERROR);
|
||||
break 2;
|
||||
}
|
||||
|
||||
imagecopy($overlay, $img, $row['x'] + $x, $row['y'] + $y, 0, 0, imagesx($img), imagesy($img));
|
||||
|
||||
// prepare subzone image
|
||||
if ($this->modeMask & self::M_SUBZONES)
|
||||
{
|
||||
if (!isset($row['maskimage']))
|
||||
{
|
||||
$row['maskimage'] = $this->createAlphaImage($row['w'], $row['h']);
|
||||
$row['maskcolor'] = imagecolorallocatealpha($row['maskimage'], ...self::COLOR_SUBZONE);
|
||||
}
|
||||
|
||||
for ($my = 0; $my < imagesy($img); $my++)
|
||||
for ($mx = 0; $mx < imagesx($img); $mx++)
|
||||
if ((imagecolorat($img, $mx, $my) >> 24) < self::A_THRESHOLD)
|
||||
imagesetpixel($row['maskimage'], $x + $mx, $y + $my, $row['maskcolor']);
|
||||
}
|
||||
|
||||
imagedestroy($img);
|
||||
|
||||
$x += 256;
|
||||
$i++;
|
||||
}
|
||||
$y += 256;
|
||||
}
|
||||
}
|
||||
$resOverlay = $this->generateOverlay($wmaId, $srcPath);
|
||||
|
||||
// create spawn-maps if wanted
|
||||
if ($this->modeMask & self::M_SPAWNS)
|
||||
{
|
||||
$outFile = $this->genSteps[self::M_SPAWNS][self::$GEN_IDX_DEST_INFO][0][0] . $zoneId . '.png';
|
||||
|
||||
if (CLISetup::getOpt('force') || !file_exists($outFile))
|
||||
{
|
||||
$tmp = imagecreate(self::SPAWNMAP_WH, self::SPAWNMAP_WH);
|
||||
$cbg = imagecolorallocate($tmp, ...self::COLOR_WHITE);
|
||||
$cfg = imagecolorallocate($tmp, ...self::COLOR_BLACK);
|
||||
|
||||
for ($y = 0; $y < self::SPAWNMAP_WH; $y++)
|
||||
{
|
||||
for ($x = 0; $x < self::SPAWNMAP_WH; $x++)
|
||||
{
|
||||
$a = imagecolorat($overlay, ($x * self::MAP_W) / self::SPAWNMAP_WH, ($y * self::MAP_H) / self::SPAWNMAP_WH) >> 24;
|
||||
imagesetpixel($tmp, $x, $y, $a < self::A_THRESHOLD ? $cfg : $cbg);
|
||||
}
|
||||
}
|
||||
|
||||
imagecolordeallocate($tmp, $cbg);
|
||||
imagecolordeallocate($tmp, $cfg);
|
||||
|
||||
if (!$this->writeImageFile($tmp, $outFile, self::SPAWNMAP_WH, self::SPAWNMAP_WH))
|
||||
$this->success = false;
|
||||
}
|
||||
else
|
||||
CLI::write($this->status.' - file '.$outFile.' was already processed', CLI::LOG_BLANK, true, true);
|
||||
}
|
||||
$this->buildSpawnMap($resOverlay, $zoneId);
|
||||
}
|
||||
|
||||
if (!($this->modeMask & self::M_MAPS))
|
||||
@@ -385,7 +308,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
if ($zoneId == 4494)
|
||||
$floors[] = 2;
|
||||
|
||||
$map = null;
|
||||
$resMap = null;
|
||||
foreach ($floors as $floorIdx)
|
||||
{
|
||||
ini_set('max_execution_time', $this->maxExecTime);
|
||||
@@ -430,18 +353,18 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
if ($doSkip == 0xF)
|
||||
continue;
|
||||
|
||||
$map = $this->assembleImage($file, self::TILEORDER, self::MAP_W, self::MAP_H);
|
||||
if (!$map)
|
||||
$resMap = $this->assembleImage($file, self::TILEORDER, self::MAP_W, self::MAP_H);
|
||||
if (!$resMap)
|
||||
{
|
||||
CLI::write(' - could not create image resource for zone '.$zoneId.($nFloors ? ' floor '.$floorIdx : ''), CLI::LOG_ERROR);
|
||||
$this->success = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($overlay && !$floorIdx)
|
||||
if ($resOverlay && !$floorIdx)
|
||||
{
|
||||
imagecopymerge($map, $overlay, 0, 0, 0, 0, imagesx($overlay), imagesy($overlay), 100);
|
||||
imagedestroy($overlay);
|
||||
imagecopymerge($resMap, $resOverlay, 0, 0, 0, 0, imagesx($resOverlay), imagesy($resOverlay), 100);
|
||||
imagedestroy($resOverlay);
|
||||
}
|
||||
|
||||
// create map
|
||||
@@ -452,52 +375,18 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
if ($doSkip & (1 << $sizeIdx))
|
||||
continue;
|
||||
|
||||
if (!$this->writeImageFile($map, $outFile[$sizeIdx], $width ?: self::MAP_W, $height ?: self::MAP_H))
|
||||
if (!$this->writeImageFile($resMap, $outFile[$sizeIdx], $width ?: self::MAP_W, $height ?: self::MAP_H))
|
||||
$this->success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// also create subzone-maps
|
||||
if ($map && isset($this->wmOverlays[$wmaId]) && $this->modeMask & self::M_SUBZONES)
|
||||
{
|
||||
foreach ($this->wmOverlays[$wmaId] as &$row)
|
||||
{
|
||||
$doSkip = 0x0;
|
||||
$outFile = [];
|
||||
if ($resMap && isset($this->wmOverlays[$wmaId]) && $this->modeMask & self::M_SUBZONES)
|
||||
$this->buildSubZones($resMap, $wmaId, $l);
|
||||
|
||||
foreach (self::DEST_DIRS as $sizeIdx => [$path, , ])
|
||||
{
|
||||
$outFile[$sizeIdx] = sprintf($path, strtolower(Util::$localeStrings[$l]).'/') . $row['areaTableId'].'.jpg';
|
||||
if (!CLISetup::getOpt('force') && file_exists($outFile[$sizeIdx]))
|
||||
{
|
||||
CLI::write($this->status.' - file '.$outFile[$sizeIdx].' was already processed', CLI::LOG_BLANK, true, true);
|
||||
$doSkip |= (1 << $sizeIdx);
|
||||
}
|
||||
}
|
||||
|
||||
if ($doSkip == 0xF)
|
||||
continue;
|
||||
|
||||
$subZone = imagecreatetruecolor(self::MAP_W, self::MAP_H);
|
||||
imagecopy($subZone, $map, 0, 0, 0, 0, imagesx($map), imagesy($map));
|
||||
imagecopy($subZone, $row['maskimage'], $row['x'], $row['y'], 0, 0, imagesx($row['maskimage']), imagesy($row['maskimage']));
|
||||
|
||||
foreach (self::DEST_DIRS as $sizeIdx => [, $width, $height])
|
||||
{
|
||||
if ($doSkip & (1 << $sizeIdx))
|
||||
continue;
|
||||
|
||||
if (!$this->writeImageFile($subZone, $outFile[$sizeIdx], $width ?: self::MAP_W, $height ?: self::MAP_H))
|
||||
$this->success = false;
|
||||
}
|
||||
|
||||
imagedestroy($subZone);
|
||||
}
|
||||
}
|
||||
|
||||
if ($map)
|
||||
imagedestroy($map);
|
||||
if ($resMap)
|
||||
imagedestroy($resMap);
|
||||
|
||||
// this takes a while; ping mysql just in case
|
||||
DB::Aowow()->selectCell('SELECT 1');
|
||||
@@ -512,7 +401,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
$this->dmFloorData = DB::Aowow()->select('SELECT IF(`mapId` IN (?a), -`worldMapAreaId`, `mapId`) AS ARRAY_KEY, GROUP_CONCAT(DISTINCT `floor` SEPARATOR " ") AS "0", COUNT(DISTINCT `floor`) AS "1" FROM dbc_dungeonmap WHERE `worldMapAreaId` <> 0 GROUP BY ARRAY_KEY', self::CONTINENTS);
|
||||
if (!$this->wmOverlays || !$this->wmAreas || !$this->dmFloorData)
|
||||
{
|
||||
CLI::write(' - could not read required dbc files: WorldMapArea.dbc ['.count($this->wmAreas ?: []).' entries]; WorldMapOverlay.dbc ['.count($this->wmOverlays ?: []).'] entries; DungeonMap.dbc ['.count($this->dmFloorData ?: []).' entries]', CLI::LOG_ERROR);
|
||||
CLI::write('[img-maps] - could not read required dbc files: WorldMapArea.dbc ['.count($this->wmAreas ?: []).' entries]; WorldMapOverlay.dbc ['.count($this->wmOverlays ?: []).'] entries; DungeonMap.dbc ['.count($this->dmFloorData ?: []).' entries]', CLI::LOG_ERROR);
|
||||
$this->success = false;
|
||||
return false;
|
||||
}
|
||||
@@ -616,7 +505,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
$sumAreas = count($this->wmAreas);
|
||||
$sumMaps = count(CLISetup::$localeIds) * ($sumAreas + $sumFloors);
|
||||
|
||||
CLI::write('Processing '.$sumAreas.' zone maps and '.$sumFloors.' dungeon maps from Interface/WorldMap/ for locale: '.Lang::concat(array_intersect_key(Util::$localeStrings, array_flip(CLISetup::$localeIds))));
|
||||
CLI::write('[img-maps] Processing '.$sumAreas.' zone maps and '.$sumFloors.' dungeon maps from Interface/WorldMap/ for locale: '.Lang::concat(array_intersect_key(Util::$localeStrings, array_flip(CLISetup::$localeIds))));
|
||||
|
||||
foreach (CLISetup::$localeIds as $l)
|
||||
{
|
||||
@@ -630,13 +519,16 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
$mapSrcDir = $this->genSteps[self::M_MAPS][1][$l] ?? '';
|
||||
if (!$mapSrcDir)
|
||||
{
|
||||
CLI::write('[img-maps] - No suitable localized map files found for locale ['.$l.': '.Util::$localeStrings[$l].'].', CLI::LOG_ERROR);
|
||||
$this->success = false;
|
||||
CLI::write(' - no suitable localized map files found for locale '.$l, CLI::LOG_ERROR);
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($this->wmAreas as $areaEntry)
|
||||
{
|
||||
$resOverlay = null;
|
||||
$resMap = null;
|
||||
|
||||
$wmaId = $areaEntry['id'];
|
||||
$zoneId = $areaEntry['areaId'];
|
||||
$mapId = $areaEntry['mapId'];
|
||||
@@ -672,109 +564,40 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
$srcPath = $mapSrcDir.'/'.$textureStr;
|
||||
if (!CLISetup::fileExists($srcPath))
|
||||
{
|
||||
CLI::write('[img-maps] - WorldMap file path '.$srcPath.' missing for selected locale '.Util::$localeStrings[$l], CLI::LOG_ERROR);
|
||||
$this->success = false;
|
||||
CLI::write('worldmap file path '.$srcPath.' missing for selected locale '.Util::$localeStrings[$l], CLI::LOG_ERROR);
|
||||
continue;
|
||||
}
|
||||
|
||||
$overlay = null;
|
||||
$srcPath .= '/';
|
||||
|
||||
// zone has overlays (is in open world; is not multilevel)
|
||||
if (isset($this->wmOverlays[$wmaId]) && ($this->modeMask & (self::M_MAPS | self::M_SPAWNS | self::M_SUBZONES)))
|
||||
{
|
||||
$overlay = $this->createAlphaImage(self::MAP_W, self::MAP_H);
|
||||
|
||||
foreach ($this->wmOverlays[$wmaId] as &$row)
|
||||
{
|
||||
$i = 1;
|
||||
$y = 0;
|
||||
while ($y < $row['h'])
|
||||
{
|
||||
$x = 0;
|
||||
while ($x < $row['w'])
|
||||
{
|
||||
$img = $this->loadImageFile($srcPath . '/' . $row['textureString'] . $i);
|
||||
if (!$img)
|
||||
{
|
||||
CLI::write(' - complexImg: tile '.$srcPath.'/'.$row['textureString'].$i.'.blp missing.', CLI::LOG_ERROR);
|
||||
break 2;
|
||||
}
|
||||
|
||||
imagecopy($overlay, $img, $row['x'] + $x, $row['y'] + $y, 0, 0, imagesx($img), imagesy($img));
|
||||
|
||||
// prepare subzone image
|
||||
if ($this->modeMask & self::M_SUBZONES)
|
||||
{
|
||||
if (!isset($row['maskimage']))
|
||||
{
|
||||
$row['maskimage'] = $this->createAlphaImage($row['w'], $row['h']);
|
||||
$row['maskcolor'] = imagecolorallocatealpha($row['maskimage'], ...self::COLOR_SUBZONE);
|
||||
}
|
||||
|
||||
for ($my = 0; $my < imagesy($img); $my++)
|
||||
for ($mx = 0; $mx < imagesx($img); $mx++)
|
||||
if ((imagecolorat($img, $mx, $my) >> 24) < self::A_THRESHOLD)
|
||||
imagesetpixel($row['maskimage'], $x + $mx, $y + $my, $row['maskcolor']);
|
||||
}
|
||||
|
||||
imagedestroy($img);
|
||||
|
||||
$x += 256;
|
||||
$i++;
|
||||
}
|
||||
$y += 256;
|
||||
}
|
||||
}
|
||||
$resOverlay = $this->generateOverlay($wmaId, $srcPath);
|
||||
|
||||
// create spawn-maps if wanted
|
||||
if ($this->modeMask & self::M_SPAWNS)
|
||||
{
|
||||
$outFile = $this->genSteps[self::M_SPAWNS][self::$GEN_IDX_DEST_INFO][0][0] . $zoneId . '.png';
|
||||
|
||||
if (CLISetup::getOpt('force') || !file_exists($outFile))
|
||||
{
|
||||
$tmp = imagecreate(self::SPAWNMAP_WH, self::SPAWNMAP_WH);
|
||||
$cbg = imagecolorallocate($tmp, ...self::COLOR_WHITE);
|
||||
$cfg = imagecolorallocate($tmp, ...self::COLOR_BLACK);
|
||||
|
||||
for ($y = 0; $y < self::SPAWNMAP_WH; $y++)
|
||||
{
|
||||
for ($x = 0; $x < self::SPAWNMAP_WH; $x++)
|
||||
{
|
||||
$a = imagecolorat($overlay, ($x * self::MAP_W) / self::SPAWNMAP_WH, ($y * self::MAP_H) / self::SPAWNMAP_WH) >> 24;
|
||||
imagesetpixel($tmp, $x, $y, $a < self::A_THRESHOLD ? $cfg : $cbg);
|
||||
}
|
||||
}
|
||||
|
||||
imagecolordeallocate($tmp, $cbg);
|
||||
imagecolordeallocate($tmp, $cfg);
|
||||
|
||||
if (!$this->writeImageFile($tmp, $outFile, self::SPAWNMAP_WH, self::SPAWNMAP_WH))
|
||||
$this->success = false;
|
||||
}
|
||||
else
|
||||
CLI::write($this->status.' - file '.$outFile.' was already processed', CLI::LOG_BLANK, true, true);
|
||||
}
|
||||
if ($resOverlay && ($this->modeMask & self::M_SPAWNS))
|
||||
$this->buildSpawnMap($resOverlay, $zoneId);
|
||||
}
|
||||
|
||||
// check if we can create base map anyway
|
||||
$png = $srcPath.'/'.$textureStr.'1.png';
|
||||
$blp = $srcPath.'/'.$textureStr.'1.blp';
|
||||
$png = $srcPath.$textureStr.'1.png';
|
||||
$blp = $srcPath.$textureStr.'1.blp';
|
||||
$hasBaseMap = CLISetup::fileExists($blp) || CLISetup::fileExists($png);
|
||||
|
||||
$map = null;
|
||||
foreach ($dmFloors as $srcFloorIdx => $outFloorIdx)
|
||||
{
|
||||
ini_set('max_execution_time', $this->maxExecTime);
|
||||
|
||||
$doSkip = 0x0;
|
||||
$outPaths = [];
|
||||
$srcFile = $srcPath.'/'.$textureStr;
|
||||
$srcFile = $srcPath.$textureStr;
|
||||
$outFile = $zoneId;
|
||||
|
||||
if (!$srcFloorIdx && !$hasBaseMap)
|
||||
{
|
||||
CLI::Write('[img-maps] zone has no base floor, but it is referenced with base floor in dmFloors? Smells like an error. areaId: '.$zoneId, CLI::LOG_WARN);
|
||||
CLI::write('[img-maps] - Zone has no base floor, but is referenced with base floor in dmFloors.', CLI::LOG_WARN);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -802,21 +625,22 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
}
|
||||
}
|
||||
|
||||
if ($doSkip == 0xF)
|
||||
// can't skip map creation if we are to generate subzones later. although they may already exist and get skipped anyway *shrug*
|
||||
if ($doSkip == 0xF && !($this->modeMask & self::M_SUBZONES))
|
||||
continue;
|
||||
|
||||
$map = $this->assembleImage($srcFile, self::TILEORDER, self::MAP_W, self::MAP_H);
|
||||
if (!$map)
|
||||
$resMap = $this->assembleImage($srcFile, self::TILEORDER, self::MAP_W, self::MAP_H);
|
||||
if (!$resMap)
|
||||
{
|
||||
CLI::write(' - could not create image resource for zone '.$zoneId.($nFloors ? ' floor '.$srcFloorIdx : ''));
|
||||
CLI::write('[img-maps] - Could not create image resource for '.($nFloors ? 'floor '.$srcFloorIdx : 'base level'), CLI::LOG_ERROR);
|
||||
$this->success = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($overlay && !$nFloors)
|
||||
if ($resOverlay && !$nFloors)
|
||||
{
|
||||
imagecopymerge($map, $overlay, 0, 0, 0, 0, imagesx($overlay), imagesy($overlay), 100);
|
||||
imagedestroy($overlay);
|
||||
imagecopymerge($resMap, $resOverlay, 0, 0, 0, 0, imagesx($resOverlay), imagesy($resOverlay), 100);
|
||||
imagedestroy($resOverlay);
|
||||
}
|
||||
|
||||
// create map
|
||||
@@ -827,52 +651,18 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
if ($doSkip & (1 << $sizeIdx))
|
||||
continue;
|
||||
|
||||
if (!$this->writeImageFile($map, $outPaths[$sizeIdx], $width ?: self::MAP_W, $height ?: self::MAP_H))
|
||||
if (!$this->writeImageFile($resMap, $outPaths[$sizeIdx], $width ?: self::MAP_W, $height ?: self::MAP_H))
|
||||
$this->success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// also create subzone-maps
|
||||
if ($map && isset($this->wmOverlays[$wmaId]) && $this->modeMask & self::M_SUBZONES)
|
||||
{
|
||||
foreach ($this->wmOverlays[$wmaId] as &$row)
|
||||
{
|
||||
$doSkip = 0x0;
|
||||
$outFiles = [];
|
||||
if ($resMap && isset($this->wmOverlays[$wmaId]) && $this->modeMask & self::M_SUBZONES)
|
||||
$this->buildSubZones($resMap, $wmaId, $l);
|
||||
|
||||
foreach (self::DEST_DIRS as $sizeIdx => [$path, , ])
|
||||
{
|
||||
$outFile[$sizeIdx] = sprintf($path, strtolower(Util::$localeStrings[$l]).'/') . $row['areaTableId'].'.jpg';
|
||||
if (!CLISetup::getOpt('force') && file_exists($outFiles[$sizeIdx]))
|
||||
{
|
||||
CLI::write($this->status.' - file '.$outFiles[$sizeIdx].' was already processed', CLI::LOG_BLANK, true, true);
|
||||
$doSkip |= (1 << $sizeIdx);
|
||||
}
|
||||
}
|
||||
|
||||
if ($doSkip == 0xF)
|
||||
continue;
|
||||
|
||||
$subZone = imagecreatetruecolor(self::MAP_W, self::MAP_H);
|
||||
imagecopy($subZone, $map, 0, 0, 0, 0, imagesx($map), imagesy($map));
|
||||
imagecopy($subZone, $row['maskimage'], $row['x'], $row['y'], 0, 0, imagesx($row['maskimage']), imagesy($row['maskimage']));
|
||||
|
||||
foreach (self::DEST_DIRS as $sizeIdx => [, $width, $height])
|
||||
{
|
||||
if ($doSkip & (1 << $sizeIdx))
|
||||
continue;
|
||||
|
||||
if (!$this->writeImageFile($subZone, $outFiles[$sizeIdx], $width ?: self::MAP_W, $height ?: self::MAP_H))
|
||||
$this->success = false;
|
||||
}
|
||||
|
||||
imagedestroy($subZone);
|
||||
}
|
||||
}
|
||||
|
||||
if ($map)
|
||||
imagedestroy($map);
|
||||
if ($resMap)
|
||||
imagedestroy($resMap);
|
||||
|
||||
// this takes a while; ping mysql just in case
|
||||
DB::Aowow()->selectCell('SELECT 1');
|
||||
@@ -880,7 +670,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
}
|
||||
}
|
||||
|
||||
private function buildZonesFile() : bool
|
||||
private function buildZonesFile() : void
|
||||
{
|
||||
$areaNames = array_combine(
|
||||
array_column($this->wmAreas, 'areaId'),
|
||||
@@ -910,14 +700,16 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
$zoneAreas[$lId][$zId][$floor] = $nameLOC;
|
||||
}
|
||||
else
|
||||
CLI::write('[img-maps] internal zone name from GlobalStrings.lua not found in WorldMapArea.dbc ['.$nameINT.']', CLI::LOG_WARN);
|
||||
CLI::write('[img-maps] ['.$nameINT.'] from GlobalStrings.lua not found in WorldMapArea.dbc', CLI::LOG_WARN);
|
||||
}
|
||||
|
||||
foreach (CLISetup::$locales as $lId => $loc)
|
||||
{
|
||||
Lang::load($lId);
|
||||
|
||||
// "custom" - show second level of Ahn'Kahet not shown but present in-game
|
||||
if (isset($zoneAreas[$lId][4494]))
|
||||
$zoneAreas[$lId][4494][2] = sprintf(self::LEVEL_N[$lId], 2);
|
||||
$zoneAreas[$lId][4494][2] = Lang::maps('floorN', [2]);
|
||||
|
||||
foreach ($zoneAreas[$lId] as $zoneId => $floorData)
|
||||
{
|
||||
@@ -927,7 +719,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
continue;
|
||||
|
||||
// todo: just note for now, try to compensate later?
|
||||
CLI::write('[img-maps] floor count mismatch for zone #'.$zoneId.' GlobalStrings: '.$nStrings.' image files: '.$nFloors, CLI::LOG_WARN);
|
||||
CLI::write('[img-maps] ['.$loc.'] '.str_pad('['.$zoneId.']', 7).'floor count mismatch between GlobalStrings: '.$nStrings.' and image files: '.$nFloors, CLI::LOG_WARN);
|
||||
}
|
||||
|
||||
ksort($zoneAreas[$lId]);
|
||||
@@ -942,75 +734,24 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
if (!CLISetup::writeFile($file, $toFile))
|
||||
$this->success = false;
|
||||
}
|
||||
|
||||
return $this->success;
|
||||
}
|
||||
|
||||
private function generateOverlay(int $wmaId, string $name, string $basePath) // : ?GdImage
|
||||
{
|
||||
if (!isset($this->wmOverlays[$wmaId]))
|
||||
return null;
|
||||
|
||||
$overlay = $this->createAlphaImage(self::MAP_W, self::MAP_H);
|
||||
|
||||
foreach ($this->wmOverlays[$wmaId] as &$this->wmOverlays)
|
||||
{
|
||||
$i = 1;
|
||||
$y = 0;
|
||||
while ($y < $this->wmOverlays['h'])
|
||||
{
|
||||
$x = 0;
|
||||
while ($x < $this->wmOverlays['w'])
|
||||
{
|
||||
$img = $this->loadImageFile($basePath . $name . $i);
|
||||
if (!$img)
|
||||
{
|
||||
CLI::write(' - complexImg: tile '.$basePath.$name.$i.'.blp missing.', CLI::LOG_ERROR);
|
||||
break 2;
|
||||
}
|
||||
|
||||
imagecopy($overlay, $img, $this->wmOverlays['x'] + $x, $this->wmOverlays['y'] + $y, 0, 0, imagesx($img), imagesy($img));
|
||||
|
||||
// prepare subzone image
|
||||
if ($this->modeMask & self::M_SUBZONES)
|
||||
{
|
||||
if (!isset($this->wmOverlays['maskimage']))
|
||||
{
|
||||
$this->wmOverlays['maskimage'] = $this->createAlphaImage($this->wmOverlays['w'], $this->wmOverlays['h']);
|
||||
$this->wmOverlays['maskcolor'] = imagecolorallocatealpha($this->wmOverlays['maskimage'], ...self::COLOR_SUBZONE);
|
||||
}
|
||||
|
||||
for ($my = 0; $my < imagesy($img); $my++)
|
||||
for ($mx = 0; $mx < imagesx($img); $mx++)
|
||||
if ((imagecolorat($img, $mx, $my) >> 24) < self::A_THRESHOLD)
|
||||
imagesetpixel($this->wmOverlays['maskimage'], $x + $mx, $y + $my, $this->wmOverlays['maskcolor']);
|
||||
}
|
||||
|
||||
imagedestroy($img);
|
||||
|
||||
$x += 256;
|
||||
$i++;
|
||||
}
|
||||
$y += 256;
|
||||
}
|
||||
}
|
||||
|
||||
return $overlay;
|
||||
}
|
||||
|
||||
private function generateSpawnMap(/*GdImage*/ $overlay, string $outFile) : bool
|
||||
private function buildSpawnMap(/*GdImage*/ $resOverlay, int $zoneId) : void
|
||||
{
|
||||
// GdImage: < 8.0 resource; >= 8.0 object
|
||||
if (gettype($overlay) != 'resource' && gettype($overlay) != 'object')
|
||||
if (gettype($resOverlay) != 'resource' && gettype($resOverlay) != 'object')
|
||||
{
|
||||
CLI::write('[img-maps] no GdImage passed to generateSpawnMap', CLI::LOG_ERROR);
|
||||
return false;
|
||||
CLI::write('[img-maps] - no GdImage passed to buildSpawnMap', CLI::LOG_ERROR);
|
||||
$this->success = false;
|
||||
return;
|
||||
}
|
||||
|
||||
$outFile = $this->genSteps[self::M_SPAWNS][self::$GEN_IDX_DEST_INFO][0][0] . $zoneId . '.png';
|
||||
|
||||
if (!CLISetup::getOpt('force') && file_exists($outFile))
|
||||
{
|
||||
CLI::write($this->status.' - file '.$outFile.' was already processed', CLI::LOG_BLANK, true, true);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
$tmp = imagecreate(self::SPAWNMAP_WH, self::SPAWNMAP_WH);
|
||||
@@ -1021,7 +762,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
{
|
||||
for ($x = 0; $x < self::SPAWNMAP_WH; $x++)
|
||||
{
|
||||
$a = imagecolorat($overlay, ($x * self::MAP_W) / self::SPAWNMAP_WH, ($y * self::MAP_H) / self::SPAWNMAP_WH) >> 24;
|
||||
$a = imagecolorat($resOverlay, ($x * self::MAP_W) / self::SPAWNMAP_WH, ($y * self::MAP_H) / self::SPAWNMAP_WH) >> 24;
|
||||
imagesetpixel($tmp, $x, $y, $a < self::A_THRESHOLD ? $cfg : $cbg);
|
||||
}
|
||||
}
|
||||
@@ -1029,16 +770,18 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
imagecolordeallocate($tmp, $cbg);
|
||||
imagecolordeallocate($tmp, $cfg);
|
||||
|
||||
return $this->writeImageFile($tmp, $outFile, self::SPAWNMAP_WH, self::SPAWNMAP_WH);
|
||||
if (!$this->writeImageFile($tmp, $outFile, self::SPAWNMAP_WH, self::SPAWNMAP_WH))
|
||||
$this->success = false;
|
||||
}
|
||||
|
||||
private function generateSubZones(/*GdImage*/ $map, int $wmaId, int $locId) : bool
|
||||
private function buildSubZones(/*GdImage*/ $resMap, int $wmaId, int $locId) : void
|
||||
{
|
||||
// GdImage: < 8.0 resource; >= 8.0 object
|
||||
if (gettype($map) != 'resource' && gettype($map) != 'object')
|
||||
if (gettype($resMap) != 'resource' && gettype($resMap) != 'object')
|
||||
{
|
||||
CLI::write('[img-maps] no GdImage passed to generateSubZones', CLI::LOG_ERROR);
|
||||
return false;
|
||||
CLI::write('[img-maps] - no GdImage passed to buildSubZones()', CLI::LOG_ERROR);
|
||||
$this->success = false;
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->wmOverlays[$wmaId] as &$row)
|
||||
@@ -1060,7 +803,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
continue;
|
||||
|
||||
$subZone = imagecreatetruecolor(self::MAP_W, self::MAP_H);
|
||||
imagecopy($subZone, $map, 0, 0, 0, 0, imagesx($map), imagesy($map));
|
||||
imagecopy($subZone, $resMap, 0, 0, 0, 0, imagesx($resMap), imagesy($resMap));
|
||||
imagecopy($subZone, $row['maskimage'], $row['x'], $row['y'], 0, 0, imagesx($row['maskimage']), imagesy($row['maskimage']));
|
||||
|
||||
foreach (self::DEST_DIRS as $sizeIdx => [, $width, $height])
|
||||
@@ -1074,8 +817,58 @@ CLISetup::registerSetup("build", new class extends SetupScript
|
||||
|
||||
imagedestroy($subZone);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
private function generateOverlay(int $wmaId, string $basePath) // : ?GdImage
|
||||
{
|
||||
if (!isset($this->wmOverlays[$wmaId]))
|
||||
return null;
|
||||
|
||||
$resOverlay = $this->createAlphaImage(self::MAP_W, self::MAP_H);
|
||||
|
||||
foreach ($this->wmOverlays[$wmaId] as &$row)
|
||||
{
|
||||
$i = 1;
|
||||
$y = 0;
|
||||
while ($y < $row['h'])
|
||||
{
|
||||
$x = 0;
|
||||
while ($x < $row['w'])
|
||||
{
|
||||
$img = $this->loadImageFile($basePath . $row['textureString'] . $i);
|
||||
if (!$img)
|
||||
{
|
||||
CLI::write('[img-maps] - overlay tile ' . $basePath . $row['textureString'] . $i . '.blp missing.', CLI::LOG_ERROR);
|
||||
break 2;
|
||||
}
|
||||
|
||||
imagecopy($resOverlay, $img, $row['x'] + $x, $row['y'] + $y, 0, 0, imagesx($img), imagesy($img));
|
||||
|
||||
// prepare subzone image
|
||||
if ($this->modeMask & self::M_SUBZONES)
|
||||
{
|
||||
if (!isset($row['maskimage']))
|
||||
{
|
||||
$row['maskimage'] = $this->createAlphaImage($row['w'], $row['h']);
|
||||
$row['maskcolor'] = imagecolorallocatealpha($row['maskimage'], ...self::COLOR_SUBZONE);
|
||||
}
|
||||
|
||||
for ($my = 0; $my < imagesy($img); $my++)
|
||||
for ($mx = 0; $mx < imagesx($img); $mx++)
|
||||
if ((imagecolorat($img, $mx, $my) >> 24) < self::A_THRESHOLD)
|
||||
imagesetpixel($row['maskimage'], $x + $mx, $y + $my, $row['maskcolor']);
|
||||
}
|
||||
|
||||
imagedestroy($img);
|
||||
|
||||
$x += 256;
|
||||
$i++;
|
||||
}
|
||||
$y += 256;
|
||||
}
|
||||
}
|
||||
|
||||
return $resOverlay;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user