diff --git a/Directory.Build.props b/Directory.Build.props
index 723456e..3e2f119 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -33,7 +33,7 @@
-
+
all
3.9.50
diff --git a/modules/ModdingToolBase b/modules/ModdingToolBase
index e12f6ce..da072f4 160000
--- a/modules/ModdingToolBase
+++ b/modules/ModdingToolBase
@@ -1 +1 @@
-Subproject commit e12f6ceedb83fe9e3372dd89c68d508f8479cf92
+Subproject commit da072f43e6b85aab35b43d11f6b36eab61bdcfa6
diff --git a/src/ModVerify.CliApp/App/VerifyAction.cs b/src/ModVerify.CliApp/App/VerifyAction.cs
index f30305c..e17d7bc 100644
--- a/src/ModVerify.CliApp/App/VerifyAction.cs
+++ b/src/ModVerify.CliApp/App/VerifyAction.cs
@@ -73,6 +73,7 @@ private IReadOnlyCollection CreateReporters()
reporters.Add(IVerificationReporter.CreateConsole(new ConsoleReporterSettings
{
+ Verbose = Settings.ReportSettings.Verbose,
MinimumReportSeverity = Settings.VerifierServiceSettings.FailFastSettings.IsFailFast
? VerificationSeverity.Information
: VerificationSeverity.Error
@@ -83,11 +84,13 @@ private IReadOnlyCollection CreateReporters()
{
OutputDirectory = outputDirectory,
MinimumReportSeverity = Settings.ReportSettings.MinimumReportSeverity,
- AggregateResults = true
+ AggregateResults = true,
+ Verbose = Settings.ReportSettings.Verbose
}, ServiceProvider));
reporters.Add(IVerificationReporter.CreateText(new TextFileReporterSettings
{
+ Verbose = Settings.ReportSettings.Verbose,
OutputDirectory = outputDirectory!,
MinimumReportSeverity = Settings.ReportSettings.MinimumReportSeverity
}, ServiceProvider));
diff --git a/src/ModVerify.CliApp/ModVerify.CliApp.csproj b/src/ModVerify.CliApp/ModVerify.CliApp.csproj
index 7dcf361..f7b7ff8 100644
--- a/src/ModVerify.CliApp/ModVerify.CliApp.csproj
+++ b/src/ModVerify.CliApp/ModVerify.CliApp.csproj
@@ -30,18 +30,18 @@
-
-
-
-
+
+
+
+
-
+
-
-
-
-
-
+
+
+
+
+
@@ -62,7 +62,7 @@
-
+
compile
runtime; build; native; contentfiles; analyzers; buildtransitive
@@ -70,7 +70,7 @@
compile
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/src/ModVerify.CliApp/Program.cs b/src/ModVerify.CliApp/Program.cs
index 68056a4..e5316f4 100644
--- a/src/ModVerify.CliApp/Program.cs
+++ b/src/ModVerify.CliApp/Program.cs
@@ -15,7 +15,6 @@
using Microsoft.Extensions.Logging;
using PG.Commons;
using PG.StarWarsGame.Engine;
-using PG.StarWarsGame.Engine.Xml.Parsers;
using PG.StarWarsGame.Files.ALO;
using PG.StarWarsGame.Files.MEG;
using PG.StarWarsGame.Files.MTD;
@@ -35,6 +34,7 @@
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using AET.ModVerify.App.Reporting;
+using PG.StarWarsGame.Engine.Xml;
using Testably.Abstractions;
using ILogger = Serilog.ILogger;
@@ -51,8 +51,8 @@ private static Task Main(string[] args)
internal class Program : SelfUpdateableAppLifecycle
{
- private static readonly string EngineParserNamespace = typeof(XmlObjectParser<>).Namespace!;
- private static readonly string ParserNamespace = typeof(PetroglyphXmlFileParser<>).Namespace!;
+ private static readonly string EngineParserNamespace = typeof(PetroglyphStarWarsGameXmlParser).Namespace!;
+ private static readonly string ParserNamespace = typeof(XmlFileParser<>).Namespace!;
private static readonly string ModVerifyRootNameSpace = typeof(Program).Namespace!;
private static readonly CompiledExpression PrintToConsoleExpression = SerilogExpression.Compile($"EventId.Id = {ModVerifyConstants.ConsoleEventIdValue}");
diff --git a/src/ModVerify.CliApp/Properties/launchSettings.json b/src/ModVerify.CliApp/Properties/launchSettings.json
index 299ce46..46fa0fc 100644
--- a/src/ModVerify.CliApp/Properties/launchSettings.json
+++ b/src/ModVerify.CliApp/Properties/launchSettings.json
@@ -2,15 +2,15 @@
"profiles": {
"Verify": {
"commandName": "Project",
- "commandLineArgs": ""
+ "commandLineArgs": "verify --offline"
},
"Verify (Interactive)": {
"commandName": "Project",
- "commandLineArgs": "verify -o verifyResults --offline --minFailSeverity Information"
+ "commandLineArgs": "verify -o verifyResults --offline --minFailSeverity Information --searchBaseline"
},
"Verify (Automatic Target Selection)": {
"commandName": "Project",
- "commandLineArgs": "verify -o verifyResults --path \"C:\\Program Files (x86)\\Steam\\steamapps\\common\\Star Wars Empire at War\\corruption\""
+ "commandLineArgs": "verify --offline -o verifyResults --path \"C:/Program Files (x86)/Steam/steamapps/common/Star Wars Empire at War/corruption/Mods/Test\""
},
"Create Baseline Interactive": {
"commandName": "Project",
diff --git a/src/ModVerify.CliApp/Resources/Baselines/baseline-foc.json b/src/ModVerify.CliApp/Resources/Baselines/baseline-foc.json
index ce70f8a..39b65f9 100644
--- a/src/ModVerify.CliApp/Resources/Baselines/baseline-foc.json
+++ b/src/ModVerify.CliApp/Resources/Baselines/baseline-foc.json
@@ -1,5 +1,5 @@
{
- "version": "2.1",
+ "version": "2.2",
"target": {
"name": "Forces of Corruption (SteamGold)",
"engine": "Foc",
@@ -10,3038 +10,2864 @@
"errors": [
{
"id": "XML04",
- "verifiers": [
- "XMLError"
- ],
- "message": "Expected double but got value \u002737\u0060\u0027. File=\u0027DATA\\XML\\COMMANDBARCOMPONENTS.XML #11571\u0027",
"severity": "Warning",
+ "asset": "Size",
+ "message": "Expected double but got value \u002737\u0060\u0027. File=\u0027DATA\\XML\\COMMANDBARCOMPONENTS.XML #11571\u0027",
"context": [
- "DATA\\XML\\COMMANDBARCOMPONENTS.XML",
+ "Parser: PG.StarWarsGame.Files.XML.Parsers.PetroglyphXmlFloatParser",
+ "File: DATA\\XML\\COMMANDBARCOMPONENTS.XML",
"Size",
"parentName=\u0027bm_text_steal\u0027"
- ],
- "asset": "Size"
+ ]
},
{
"id": "XML04",
- "verifiers": [
- "XMLError"
- ],
- "message": "Expected integer but got \u002780, 20\u0027. File=\u0027DATA\\XML\\SFXEVENTSWEAPONS.XML #90\u0027",
"severity": "Warning",
+ "asset": "Probability",
+ "message": "Expected integer but got \u002780, 20\u0027. File=\u0027DATA\\XML\\SFXEVENTSWEAPONS.XML #90\u0027",
"context": [
- "DATA\\XML\\SFXEVENTSWEAPONS.XML",
+ "Parser: PG.StarWarsGame.Files.XML.Parsers.PetroglyphXmlIntegerParser",
+ "File: DATA\\XML\\SFXEVENTSWEAPONS.XML",
"Probability",
"parentName=\u0027Unit_TIE_Fighter_Fire\u0027"
- ],
- "asset": "Probability"
+ ]
},
{
- "id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027CIN_Reb_CelebHall.alo\u0027",
- "severity": "Error",
- "context": [],
- "asset": "CIN_Reb_CelebHall.alo"
+ "id": "XML08",
+ "severity": "Information",
+ "asset": "DATA\\XML\\UNITS_HERO_REBEL_ROGUE_SQUADRON.XML",
+ "message": "XML header is not the first entry of the XML file. File=\u0027DATA\\XML\\UNITS_HERO_REBEL_ROGUE_SQUADRON.XML #0\u0027",
+ "context": [
+ "Parser: PG.StarWarsGame.Engine.Xml.Parsers.GameObjectFileParser",
+ "File: DATA\\XML\\UNITS_HERO_REBEL_ROGUE_SQUADRON.XML"
+ ]
},
{
- "id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_ssd_debris\u0027 not found for model \u0027DATA\\ART\\MODELS\\UV_ECLIPSE_UC_DC.ALO\u0027",
- "severity": "Error",
+ "id": "XML10",
+ "severity": "Information",
+ "asset": "Disabled_Darken",
+ "message": "The node \u0027Disabled_Darken\u0027 is not supported. File=\u0027DATA\\XML\\COMMANDBARCOMPONENTS.XML #8608\u0027",
"context": [
- "DATA\\ART\\MODELS\\UV_ECLIPSE_UC_DC.ALO"
- ],
- "asset": "p_ssd_debris"
+ "Parser: PG.StarWarsGame.Engine.Xml.Parsers.CommandBarComponentParser",
+ "File: DATA\\XML\\COMMANDBARCOMPONENTS.XML",
+ "Disabled_Darken",
+ "parentName=\u0027b_fast_forward_t\u0027"
+ ]
},
{
- "id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
- "AET.ModVerify.Verifiers.Commons.TextureVeifier"
- ],
- "message": "Could not find texture \u0027Cin_Reb_CelebHall_Wall.tga\u0027 for context: [W_SITH_LEFTHALL.ALO].",
- "severity": "Error",
+ "id": "XML10",
+ "severity": "Information",
+ "asset": "Mega_Texture_Name",
+ "message": "The node \u0027Mega_Texture_Name\u0027 is not supported. File=\u0027DATA\\XML\\COMMANDBARCOMPONENTS.XML #8\u0027",
"context": [
- "W_SITH_LEFTHALL.ALO"
- ],
- "asset": "Cin_Reb_CelebHall_Wall.tga"
+ "Parser: PG.StarWarsGame.Engine.Xml.Parsers.CommandBarComponentParser",
+ "File: DATA\\XML\\COMMANDBARCOMPONENTS.XML",
+ "Mega_Texture_Name",
+ "parentName=\u0027i_main_commandbar\u0027"
+ ]
},
{
- "id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027Cin_ImperialCraft.alo\u0027",
- "severity": "Error",
- "context": [],
- "asset": "Cin_ImperialCraft.alo"
+ "id": "XML08",
+ "severity": "Information",
+ "asset": "DATA\\XML\\UNITS_SPACE_UNDERWORLD_INTERCEPTOR4.XML",
+ "message": "XML header is not the first entry of the XML file. File=\u0027DATA\\XML\\UNITS_SPACE_UNDERWORLD_INTERCEPTOR4.XML #0\u0027",
+ "context": [
+ "Parser: PG.StarWarsGame.Engine.Xml.Parsers.GameObjectFileParser",
+ "File: DATA\\XML\\UNITS_SPACE_UNDERWORLD_INTERCEPTOR4.XML"
+ ]
},
{
- "id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027Cin_Officer.alo\u0027",
- "severity": "Error",
- "context": [],
- "asset": "Cin_Officer.alo"
+ "id": "XML08",
+ "severity": "Information",
+ "asset": "DATA\\XML\\UNITS_SPACE_EMPIRE_TIE_DEFENDER.XML",
+ "message": "XML header is not the first entry of the XML file. File=\u0027DATA\\XML\\UNITS_SPACE_EMPIRE_TIE_DEFENDER.XML #0\u0027",
+ "context": [
+ "Parser: PG.StarWarsGame.Engine.Xml.Parsers.GameObjectFileParser",
+ "File: DATA\\XML\\UNITS_SPACE_EMPIRE_TIE_DEFENDER.XML"
+ ]
},
{
- "id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027Cin_DStar_protons.alo\u0027",
- "severity": "Error",
- "context": [],
- "asset": "Cin_DStar_protons.alo"
+ "id": "XML10",
+ "severity": "Information",
+ "asset": "Disabled_Darken",
+ "message": "The node \u0027Disabled_Darken\u0027 is not supported. File=\u0027DATA\\XML\\COMMANDBARCOMPONENTS.XML #8569\u0027",
+ "context": [
+ "Parser: PG.StarWarsGame.Engine.Xml.Parsers.CommandBarComponentParser",
+ "File: DATA\\XML\\COMMANDBARCOMPONENTS.XML",
+ "Disabled_Darken",
+ "parentName=\u0027b_fast_forward\u0027"
+ ]
},
{
- "id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
- "AET.ModVerify.Verifiers.Commons.TextureVeifier"
- ],
- "message": "Could not find texture \u0027w_grenade.tga\u0027 for context: [W_GRENADE.ALO].",
- "severity": "Error",
+ "id": "XML08",
+ "severity": "Information",
+ "asset": "DATA\\XML\\GROUNDSTRUCTURES_UNDERWORLD.XML",
+ "message": "XML header is not the first entry of the XML file. File=\u0027DATA\\XML\\GROUNDSTRUCTURES_UNDERWORLD.XML #0\u0027",
"context": [
- "W_GRENADE.ALO"
- ],
- "asset": "w_grenade.tga"
+ "Parser: PG.StarWarsGame.Engine.Xml.Parsers.GameObjectFileParser",
+ "File: DATA\\XML\\GROUNDSTRUCTURES_UNDERWORLD.XML"
+ ]
},
{
- "id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_uwstation_death\u0027 not found for model \u0027DATA\\ART\\MODELS\\UB_03_STATION_D.ALO\u0027",
- "severity": "Error",
+ "id": "XML08",
+ "severity": "Information",
+ "asset": "DATA\\XML\\UNITS_LAND_REBEL_GALLOFREE_HTT.XML",
+ "message": "XML header is not the first entry of the XML file. File=\u0027DATA\\XML\\UNITS_LAND_REBEL_GALLOFREE_HTT.XML #0\u0027",
"context": [
- "DATA\\ART\\MODELS\\UB_03_STATION_D.ALO"
- ],
- "asset": "p_uwstation_death"
+ "Parser: PG.StarWarsGame.Engine.Xml.Parsers.GameObjectFileParser",
+ "File: DATA\\XML\\UNITS_LAND_REBEL_GALLOFREE_HTT.XML"
+ ]
},
{
- "id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027Cin_EI_Vader.alo\u0027",
- "severity": "Error",
- "context": [],
- "asset": "Cin_EI_Vader.alo"
+ "id": "XML10",
+ "severity": "Information",
+ "asset": "Disabled_Darken",
+ "message": "The node \u0027Disabled_Darken\u0027 is not supported. File=\u0027DATA\\XML\\COMMANDBARCOMPONENTS.XML #8589\u0027",
+ "context": [
+ "Parser: PG.StarWarsGame.Engine.Xml.Parsers.CommandBarComponentParser",
+ "File: DATA\\XML\\COMMANDBARCOMPONENTS.XML",
+ "Disabled_Darken",
+ "parentName=\u0027b_play_pause_t\u0027"
+ ]
},
{
- "id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027MODELS\u0027",
- "severity": "Error",
- "context": [],
- "asset": "MODELS"
+ "id": "XML10",
+ "severity": "Information",
+ "asset": "Disabled_Darken",
+ "message": "The node \u0027Disabled_Darken\u0027 is not supported. File=\u0027DATA\\XML\\COMMANDBARCOMPONENTS.XML #8550\u0027",
+ "context": [
+ "Parser: PG.StarWarsGame.Engine.Xml.Parsers.CommandBarComponentParser",
+ "File: DATA\\XML\\COMMANDBARCOMPONENTS.XML",
+ "Disabled_Darken",
+ "parentName=\u0027b_play_pause\u0027"
+ ]
},
{
- "id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027Cin_DeathStar_Wall.alo\u0027",
- "severity": "Error",
- "context": [],
- "asset": "Cin_DeathStar_Wall.alo"
+ "id": "XML08",
+ "severity": "Information",
+ "asset": "DATA\\XML\\SPACEPROPS_UNDERWORLD.XML",
+ "message": "XML header is not the first entry of the XML file. File=\u0027DATA\\XML\\SPACEPROPS_UNDERWORLD.XML #0\u0027",
+ "context": [
+ "Parser: PG.StarWarsGame.Engine.Xml.Parsers.GameObjectFileParser",
+ "File: DATA\\XML\\SPACEPROPS_UNDERWORLD.XML"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_smoke_small_thin2\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_PRISON.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0210_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0210_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\NB_PRISON.ALO"
- ],
- "asset": "p_smoke_small_thin2"
+ "Unit_Group_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_uwstation_death\u0027 not found for model \u0027DATA\\ART\\MODELS\\UB_01_STATION_D.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0207_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0207_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\UB_01_STATION_D.ALO"
- ],
- "asset": "p_uwstation_death"
+ "Unit_Group_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027CIN_Officer_Row.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_Officer_Row.alo"
+ "asset": "U000_LEI0205_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0205_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027Lensflare0\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_STARS_MEDIUM.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0207_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0207_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\W_STARS_MEDIUM.ALO"
- ],
- "asset": "Lensflare0"
+ "Unit_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027CIN_DeathStar_Hangar.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_DeathStar_Hangar.alo"
+ "asset": "U000_DEF3006_ENG.WAV",
+ "message": "Audio file \u0027U000_DEF3006_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Corrupt_Sabateur"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027Cin_EV_lambdaShuttle_150.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "Cin_EV_lambdaShuttle_150.alo"
+ "asset": "U000_ARC3104_ENG.WAV",
+ "message": "Audio file \u0027U000_ARC3104_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Produce_Troops_Arc_Hammer"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_smoke_small_thin4\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_PRISON.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0315_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0315_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\NB_PRISON.ALO"
- ],
- "asset": "p_smoke_small_thin4"
+ "Unit_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027Lensflare0\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_STARS_CINE.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0201_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0201_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\W_STARS_CINE.ALO"
- ],
- "asset": "Lensflare0"
+ "Unit_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Shader effect \u0027Default.fx\u0027 not found for model \u0027DATA\\ART\\MODELS\\UV_SKIPRAY.ALO\u0027.",
"severity": "Error",
+ "asset": "U000_LEI0211_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0211_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\UV_SKIPRAY.ALO"
- ],
- "asset": "Default.fx"
+ "Unit_Group_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_desert_ground_dust\u0027 not found for model \u0027DATA\\ART\\MODELS\\UI_IG88.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0303_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0303_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\UI_IG88.ALO"
- ],
- "asset": "p_desert_ground_dust"
+ "Unit_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027CIN_p_proton_torpedo.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_p_proton_torpedo.alo"
+ "asset": "U000_LEI0111_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0111_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Select_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027CIN_Fire_Huge.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_Fire_Huge.alo"
+ "asset": "AMB_URB_CLEAR_LOOP_1.WAV",
+ "message": "Audio file \u0027AMB_URB_CLEAR_LOOP_1.WAV\u0027 could not be found.",
+ "context": [
+ "Weather_Ambient_Clear_Urban_Loop"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_uwstation_death\u0027 not found for model \u0027DATA\\ART\\MODELS\\UB_04_STATION_D.ALO\u0027",
"severity": "Error",
+ "asset": "FS_BEETLE_3.WAV",
+ "message": "Audio file \u0027FS_BEETLE_3.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\UB_04_STATION_D.ALO"
- ],
- "asset": "p_uwstation_death"
+ "SFX_Anim_Beetle_Footsteps"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027RV_nebulonb_D_death_00.ALO\u0027",
"severity": "Error",
- "context": [],
- "asset": "RV_nebulonb_D_death_00.ALO"
+ "asset": "U000_LEI0205_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0205_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Group_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_uwstation_death\u0027 not found for model \u0027DATA\\ART\\MODELS\\UB_02_STATION_D.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0215_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0215_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\UB_02_STATION_D.ALO"
- ],
- "asset": "p_uwstation_death"
+ "Unit_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027W_Kamino_Reflect.ALO\u0027",
"severity": "Error",
- "context": [],
- "asset": "W_Kamino_Reflect.ALO"
+ "asset": "U000_LEI0504_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0504_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Remove_Corruption_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_smoke_small_thin2\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_MONCAL_BUILDING.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0104_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0104_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\NB_MONCAL_BUILDING.ALO"
- ],
- "asset": "p_smoke_small_thin2"
+ "Unit_Select_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_steam_small\u0027 not found for model \u0027DATA\\ART\\MODELS\\RB_HEAVYVEHICLEFACTORY.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0303_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0303_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\RB_HEAVYVEHICLEFACTORY.ALO"
- ],
- "asset": "p_steam_small"
+ "Unit_Group_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027Cin_EV_Stardestroyer_Warp.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "Cin_EV_Stardestroyer_Warp.alo"
+ "asset": "U000_LEI0202_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0202_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Fleet_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027Cin_DStar_TurretLasers.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "Cin_DStar_TurretLasers.alo"
+ "asset": "U000_LEI0212_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0212_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027CIN_Rbel_GreyGroup.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_Rbel_GreyGroup.alo"
+ "asset": "U000_LEI0105_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0105_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Select_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027Cin_Planet_Hoth_High.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "Cin_Planet_Hoth_High.alo"
+ "asset": "U000_LEI0311_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0311_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027CIN_Trooper_Row.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_Trooper_Row.alo"
+ "asset": "U000_LEI0110_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0110_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Select_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_desert_ground_dust\u0027 not found for model \u0027DATA\\ART\\MODELS\\UI_SABOTEUR.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0313_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0313_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\UI_SABOTEUR.ALO"
- ],
- "asset": "p_desert_ground_dust"
+ "Unit_Group_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027Lensflare0\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_STARS_CINE_LUA.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0103_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0103_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\W_STARS_CINE_LUA.ALO"
- ],
- "asset": "Lensflare0"
+ "Unit_Select_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027W_AllShaders.ALO\u0027",
"severity": "Error",
- "context": [],
- "asset": "W_AllShaders.ALO"
+ "asset": "U000_LEI0308_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0308_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Group_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Shader effect \u0027Default.fx\u0027 not found for model \u0027DATA\\ART\\MODELS\\EV_TIE_LANCET.ALO\u0027.",
"severity": "Error",
+ "asset": "U000_TMC0212_ENG.WAV",
+ "message": "Audio file \u0027U000_TMC0212_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\EV_TIE_LANCET.ALO"
- ],
- "asset": "Default.fx"
+ "Unit_Assist_Move_Tie_Mauler"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027CINE_EV_StarDestroyer.ALO\u0027",
"severity": "Error",
- "context": [],
- "asset": "CINE_EV_StarDestroyer.ALO"
+ "asset": "U000_LEI0304_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0304_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027Cin_EI_Palpatine.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "Cin_EI_Palpatine.alo"
+ "asset": "U000_LEI0101_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0101_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Select_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
- "AET.ModVerify.Verifiers.Commons.TextureVeifier"
- ],
- "message": "Could not find texture \u0027Cin_DeathStar.tga\u0027 for context: [ALTTEST.ALO].",
"severity": "Error",
+ "asset": "U000_LEI0211_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0211_ENG.WAV\u0027 could not be found.",
"context": [
- "ALTTEST.ALO"
- ],
- "asset": "Cin_DeathStar.tga"
+ "Unit_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
- "AET.ModVerify.Verifiers.Commons.TextureVeifier"
- ],
- "message": "Could not find texture \u0027UB_girder_B.tga\u0027 for context: [UV_MDU_CAGE.ALO].",
"severity": "Error",
+ "asset": "U000_LEI0305_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0305_ENG.WAV\u0027 could not be found.",
"context": [
- "UV_MDU_CAGE.ALO"
- ],
- "asset": "UB_girder_B.tga"
+ "Unit_Group_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027P_mptl-2a_Die\u0027 not found for model \u0027DATA\\ART\\MODELS\\RV_MPTL-2A.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0208_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0208_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\RV_MPTL-2A.ALO"
- ],
- "asset": "P_mptl-2a_Die"
+ "Unit_Fleet_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Shader effect \u0027Default.fx\u0027 not found for model \u0027DATA\\ART\\MODELS\\EV_MDU_SENSORNODE.ALO\u0027.",
"severity": "Error",
+ "asset": "U000_LEI0311_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0311_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\EV_MDU_SENSORNODE.ALO"
- ],
- "asset": "Default.fx"
+ "Unit_Group_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027Cin_Planet_Alderaan_High.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "Cin_Planet_Alderaan_High.alo"
+ "asset": "U000_LEI0314_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0314_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_hp_archammer-damage\u0027 not found for model \u0027DATA\\ART\\MODELS\\EV_ARCHAMMER.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0108_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0108_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\EV_ARCHAMMER.ALO"
- ],
- "asset": "p_hp_archammer-damage"
+ "Unit_Select_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_uwstation_death\u0027 not found for model \u0027DATA\\ART\\MODELS\\UB_05_STATION_D.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0213_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0213_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\UB_05_STATION_D.ALO"
- ],
- "asset": "p_uwstation_death"
+ "Unit_Group_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_explosion_smoke_small_thin5\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_NOGHRI_HUT.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0202_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0202_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\NB_NOGHRI_HUT.ALO"
- ],
- "asset": "p_explosion_smoke_small_thin5"
+ "Unit_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027CIN_Probe_Droid.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_Probe_Droid.alo"
+ "asset": "U000_LEI0113_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0113_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Select_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027Lensflare0\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_STARS_HIGH.ALO\u0027",
"severity": "Error",
+ "asset": "AMB_DES_CLEAR_LOOP_1.WAV",
+ "message": "Audio file \u0027AMB_DES_CLEAR_LOOP_1.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\W_STARS_HIGH.ALO"
- ],
- "asset": "Lensflare0"
+ "Weather_Ambient_Clear_Sandstorm_Loop"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027W_Volcano_Rock02.ALO\u0027",
"severity": "Error",
- "context": [],
- "asset": "W_Volcano_Rock02.ALO"
+ "asset": "U000_LEI0107_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0107_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Select_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027lookat\u0027 not found for model \u0027DATA\\ART\\MODELS\\UV_ECLIPSE.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0305_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0305_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\UV_ECLIPSE.ALO"
- ],
- "asset": "lookat"
+ "Unit_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027Cin_Shuttle_Tyderium.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "Cin_Shuttle_Tyderium.alo"
+ "asset": "U000_LEI0209_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0209_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Group_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027W_SwampGasEmit.ALO\u0027",
"severity": "Error",
- "context": [],
- "asset": "W_SwampGasEmit.ALO"
+ "asset": "U000_LEI0308_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0308_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027P_heat_small01\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_VCH.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0207_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0207_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\NB_VCH.ALO"
- ],
- "asset": "P_heat_small01"
+ "Unit_Fleet_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027CIN_Rbel_NavyRow.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_Rbel_NavyRow.alo"
+ "asset": "U000_MAL0503_ENG.WAV",
+ "message": "Audio file \u0027U000_MAL0503_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Assist_Move_Missile_Launcher"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027CIN_Fire_Medium.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_Fire_Medium.alo"
+ "asset": "U000_LEI0102_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0102_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Select_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_ewok_drag_dirt\u0027 not found for model \u0027DATA\\ART\\MODELS\\UI_EWOK_HANDLER.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0306_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0306_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\UI_EWOK_HANDLER.ALO"
- ],
- "asset": "p_ewok_drag_dirt"
+ "Unit_Group_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027W_Bush_Swmp00.ALO\u0027",
"severity": "Error",
- "context": [],
- "asset": "W_Bush_Swmp00.ALO"
+ "asset": "FS_BEETLE_2.WAV",
+ "message": "Audio file \u0027FS_BEETLE_2.WAV\u0027 could not be found.",
+ "context": [
+ "SFX_Anim_Beetle_Footsteps"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027W_droid_steam.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "W_droid_steam.alo"
+ "asset": "U000_LEI0312_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0312_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Group_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027CIN_Biker_Row.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_Biker_Row.alo"
+ "asset": "U000_LEI0402_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0402_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Guard_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027w_planet_volcanic.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "w_planet_volcanic.alo"
+ "asset": "U000_LEI0309_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0309_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Group_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_smoke_small_thin2\u0027 not found for model \u0027DATA\\ART\\MODELS\\RB_HYPERVELOCITYGUN.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0501_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0501_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\RB_HYPERVELOCITYGUN.ALO"
- ],
- "asset": "p_smoke_small_thin2"
+ "Unit_Remove_Corruption_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027lookat\u0027 not found for model \u0027DATA\\ART\\MODELS\\UV_ECLIPSE_UC.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0201_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0201_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\UV_ECLIPSE_UC.ALO"
- ],
- "asset": "lookat"
+ "Unit_Group_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027CIN_REb_CelebCharacters.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_REb_CelebCharacters.alo"
+ "asset": "U000_MCF1601_ENG.WAV",
+ "message": "Audio file \u0027U000_MCF1601_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_StarDest_MC30_Frigate"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027Cin_DeathStar_High.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "Cin_DeathStar_High.alo"
+ "asset": "TESTUNITMOVE_ENG.WAV",
+ "message": "Audio file \u0027TESTUNITMOVE_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Move_Gneneric_Test"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
- "AET.ModVerify.Verifiers.Commons.TextureVeifier"
- ],
- "message": "Could not find texture \u0027Cin_Reb_CelebHall_Wall_B.tga\u0027 for context: [W_SITH_LEFTHALL.ALO].",
"severity": "Error",
+ "asset": "U000_LEI0114_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0114_ENG.WAV\u0027 could not be found.",
"context": [
- "W_SITH_LEFTHALL.ALO"
- ],
- "asset": "Cin_Reb_CelebHall_Wall_B.tga"
+ "Unit_Select_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
- "AET.ModVerify.Verifiers.Commons.TextureVeifier"
- ],
- "message": "Could not find texture \u0027NB_YsalamiriTree_B.tga\u0027 for context: [UV_MDU_CAGE.ALO].",
"severity": "Error",
+ "asset": "U000_ARC3105_ENG.WAV",
+ "message": "Audio file \u0027U000_ARC3105_ENG.WAV\u0027 could not be found.",
"context": [
- "UV_MDU_CAGE.ALO"
- ],
- "asset": "NB_YsalamiriTree_B.tga"
- },
- {
- "id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027Cin_Coruscant.alo\u0027",
- "severity": "Error",
- "context": [],
- "asset": "Cin_Coruscant.alo"
+ "Unit_Complete_Troops_Arc_Hammer"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_prison_light\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_PRISON.ALO\u0027",
"severity": "Error",
+ "asset": "EGL_STAR_VIPER_SPINNING_1.WAV",
+ "message": "Audio file \u0027EGL_STAR_VIPER_SPINNING_1.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\NB_PRISON.ALO"
- ],
- "asset": "p_prison_light"
+ "Unit_Star_Viper_Spinning_By"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_cold_tiny01\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_SCH.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0401_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0401_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\NB_SCH.ALO"
- ],
- "asset": "p_cold_tiny01"
+ "Unit_Guard_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027CIN_NavyTrooper_Row.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_NavyTrooper_Row.alo"
+ "asset": "U000_LEI0213_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0213_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Shader effect \u0027Default.fx\u0027 not found for model \u0027DATA\\ART\\MODELS\\UV_CRUSADERCLASSCORVETTE.ALO\u0027.",
"severity": "Error",
+ "asset": "U000_LEI0212_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0212_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\UV_CRUSADERCLASSCORVETTE.ALO"
- ],
- "asset": "Default.fx"
+ "Unit_Group_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027CIN_Rbel_Soldier.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_Rbel_Soldier.alo"
+ "asset": "U000_LEI0115_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0115_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Select_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_desert_ground_dust\u0027 not found for model \u0027DATA\\ART\\MODELS\\RI_KYLEKATARN.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0306_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0306_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\RI_KYLEKATARN.ALO"
- ],
- "asset": "p_desert_ground_dust"
+ "Unit_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027CIN_Lambda_Mouth.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_Lambda_Mouth.alo"
+ "asset": "U000_LEI0601_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0601_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Increase_Production_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
- "AET.ModVerify.Verifiers.Commons.TextureVeifier"
- ],
- "message": "Could not find texture \u0027p_particle_master\u0027 for context: [P_DIRT_EMITTER_TEST1.ALO].",
"severity": "Error",
+ "asset": "U000_ARC3106_ENG.WAV",
+ "message": "Audio file \u0027U000_ARC3106_ENG.WAV\u0027 could not be found.",
"context": [
- "P_DIRT_EMITTER_TEST1.ALO"
- ],
- "asset": "p_particle_master"
+ "Unit_Complete_Troops_Arc_Hammer"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027Cin_bridge.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "Cin_bridge.alo"
+ "asset": "U000_LEI0602_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0602_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Increase_Production_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027W_Vol_Steam01.ALO\u0027",
"severity": "Error",
- "context": [],
- "asset": "W_Vol_Steam01.ALO"
+ "asset": "U000_DEF3106_ENG.WAV",
+ "message": "Audio file \u0027U000_DEF3106_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Weaken_Sabateur"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027CIN_Rbel_grey.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_Rbel_grey.alo"
+ "asset": "U000_LEI0403_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0403_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Guard_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027w_sith_arch.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "w_sith_arch.alo"
+ "asset": "U000_LEI0314_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0314_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Group_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027Cin_rv_XWingProp.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "Cin_rv_XWingProp.alo"
+ "asset": "U000_LEI0203_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0203_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Group_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027Cin_DStar_Dish_close.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "Cin_DStar_Dish_close.alo"
+ "asset": "U000_LEI0205_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0205_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Fleet_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
- "AET.ModVerify.Verifiers.Commons.TextureVeifier"
- ],
- "message": "Could not find texture \u0027W_TE_Rock_f_02_b.tga\u0027 for context: [EV_TIE_PHANTOM.ALO].",
"severity": "Error",
+ "asset": "U000_TMC0212_ENG.WAV",
+ "message": "Audio file \u0027U000_TMC0212_ENG.WAV\u0027 could not be found.",
"context": [
- "EV_TIE_PHANTOM.ALO"
- ],
- "asset": "W_TE_Rock_f_02_b.tga"
+ "Unit_Move_Tie_Mauler"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027pe_bwing_yellow\u0027 not found for model \u0027DATA\\ART\\MODELS\\RV_BWING.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0203_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0203_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\RV_BWING.ALO"
- ],
- "asset": "pe_bwing_yellow"
+ "Unit_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027CIN_Lambda_Head.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_Lambda_Head.alo"
+ "asset": "U000_LEI0307_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0307_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_explosion_small_delay00\u0027 not found for model \u0027DATA\\ART\\MODELS\\EB_COMMANDCENTER.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0203_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0203_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\EB_COMMANDCENTER.ALO"
- ],
- "asset": "p_explosion_small_delay00"
+ "Unit_Fleet_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027Cin_DStar_LeverPanel.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "Cin_DStar_LeverPanel.alo"
+ "asset": "U000_LEI0201_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0201_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Fleet_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027p_splash_wake_lava.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "p_splash_wake_lava.alo"
+ "asset": "FS_BEETLE_1.WAV",
+ "message": "Audio file \u0027FS_BEETLE_1.WAV\u0027 could not be found.",
+ "context": [
+ "SFX_Anim_Beetle_Footsteps"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027Lensflare0\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_STARS_LOW.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0204_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0204_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\W_STARS_LOW.ALO"
- ],
- "asset": "Lensflare0"
+ "Unit_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_desert_ground_dust\u0027 not found for model \u0027DATA\\ART\\MODELS\\EI_MARAJADE.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0206_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0206_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\EI_MARAJADE.ALO"
- ],
- "asset": "p_desert_ground_dust"
+ "Unit_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Proxy particle \u0027p_bomb_spin\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_THERMAL_DETONATOR_EMPIRE.ALO\u0027",
"severity": "Error",
+ "asset": "U000_LEI0603_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0603_ENG.WAV\u0027 could not be found.",
"context": [
- "DATA\\ART\\MODELS\\W_THERMAL_DETONATOR_EMPIRE.ALO"
- ],
- "asset": "p_bomb_spin"
+ "Unit_Increase_Production_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027Cin_EV_TieAdvanced.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "Cin_EV_TieAdvanced.alo"
+ "asset": "U000_LEI0313_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0313_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
- ],
- "message": "Unable to find .ALO file \u0027CIN_Rbel_Soldier_Group.alo\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_Rbel_Soldier_Group.alo"
+ "asset": "U000_LEI0301_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0301_ENG.WAV\u0027 could not be found.",
+ "context": [
+ "Unit_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0213_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0312_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0312_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_Move_Leia"
- ],
- "asset": "U000_LEI0213_ENG.WAV"
+ "Unit_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0113_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0404_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0404_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_Select_Leia"
- ],
- "asset": "U000_LEI0113_ENG.WAV"
+ "Unit_Guard_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0603_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0604_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0604_ENG.WAV\u0027 could not be found.",
"context": [
"Unit_Increase_Production_Leia"
- ],
- "asset": "U000_LEI0603_ENG.WAV"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0309_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0210_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0210_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_Attack_Leia"
- ],
- "asset": "U000_LEI0309_ENG.WAV"
+ "Unit_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0212_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0307_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0307_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_Move_Leia"
- ],
- "asset": "U000_LEI0212_ENG.WAV"
+ "Unit_Group_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_MAL0503_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "C000_DST0102_ENG.WAV",
+ "message": "Audio file \u0027C000_DST0102_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_Assist_Move_Missile_Launcher"
- ],
- "asset": "U000_MAL0503_ENG.WAV"
+ "EHD_Death_Star_Activate"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_MCF1601_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0215_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0215_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_StarDest_MC30_Frigate"
- ],
- "asset": "U000_MCF1601_ENG.WAV"
+ "Unit_Group_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0111_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0206_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0206_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_Select_Leia"
- ],
- "asset": "U000_LEI0111_ENG.WAV"
+ "Unit_Group_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_ARC3106_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0202_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0202_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_Complete_Troops_Arc_Hammer"
- ],
- "asset": "U000_ARC3106_ENG.WAV"
+ "Unit_Group_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0303_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0304_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0304_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_Attack_Leia"
- ],
- "asset": "U000_LEI0303_ENG.WAV"
+ "Unit_Group_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0404_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0315_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0315_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_Guard_Leia"
- ],
- "asset": "U000_LEI0404_ENG.WAV"
+ "Unit_Group_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027TESTUNITMOVE_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0112_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0112_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_Move_Gneneric_Test"
- ],
- "asset": "TESTUNITMOVE_ENG.WAV"
+ "Unit_Select_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0401_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "FS_BEETLE_4.WAV",
+ "message": "Audio file \u0027FS_BEETLE_4.WAV\u0027 could not be found.",
"context": [
- "Unit_Guard_Leia"
- ],
- "asset": "U000_LEI0401_ENG.WAV"
+ "SFX_Anim_Beetle_Footsteps"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027EGL_STAR_VIPER_SPINNING_1.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0109_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0109_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_Star_Viper_Spinning_By"
- ],
- "asset": "EGL_STAR_VIPER_SPINNING_1.WAV"
+ "Unit_Select_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_TMC0212_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0309_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0309_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_Move_Tie_Mauler"
- ],
- "asset": "U000_TMC0212_ENG.WAV"
+ "Unit_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0110_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0106_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0106_ENG.WAV\u0027 could not be found.",
"context": [
"Unit_Select_Leia"
- ],
- "asset": "U000_LEI0110_ENG.WAV"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0314_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0301_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0301_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_Attack_Leia"
- ],
- "asset": "U000_LEI0314_ENG.WAV"
+ "Unit_Group_Attack_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0305_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0209_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0209_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_Attack_Leia"
- ],
- "asset": "U000_LEI0305_ENG.WAV"
+ "Unit_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0112_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0208_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0208_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_Select_Leia"
- ],
- "asset": "U000_LEI0112_ENG.WAV"
+ "Unit_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0209_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0503_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0503_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_Move_Leia"
- ],
- "asset": "U000_LEI0209_ENG.WAV"
+ "Unit_Remove_Corruption_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0211_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0208_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0208_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_Move_Leia"
- ],
- "asset": "U000_LEI0211_ENG.WAV"
+ "Unit_Group_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0205_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0206_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0206_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_Move_Leia"
- ],
- "asset": "U000_LEI0205_ENG.WAV"
+ "Unit_Fleet_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0115_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0502_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0502_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_Select_Leia"
- ],
- "asset": "U000_LEI0115_ENG.WAV"
+ "Unit_Remove_Corruption_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0604_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "U000_LEI0204_ENG.WAV",
+ "message": "Audio file \u0027U000_LEI0204_ENG.WAV\u0027 could not be found.",
"context": [
- "Unit_Increase_Production_Leia"
- ],
- "asset": "U000_LEI0604_ENG.WAV"
+ "Unit_Group_Move_Leia"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0602_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "underworld_logo_off.tga",
+ "message": "Could not find GUI texture \u0027underworld_logo_off.tga\u0027 at location \u0027MegaTexture\u0027.",
"context": [
- "Unit_Increase_Production_Leia"
- ],
- "asset": "U000_LEI0602_ENG.WAV"
+ "IDC_PLAY_FACTION_A_BUTTON_BIG",
+ "MegaTexture"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0315_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "i_dialogue_button_large_middle_off.tga",
+ "message": "Could not find GUI texture \u0027i_dialogue_button_large_middle_off.tga\u0027 at location \u0027Repository\u0027.",
"context": [
- "Unit_Attack_Leia"
- ],
- "asset": "U000_LEI0315_ENG.WAV"
+ "IDC_PLAY_FACTION_B_BUTTON_BIG",
+ "Repository"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_DEF3006_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "underworld_logo_rollover.tga",
+ "message": "Could not find GUI texture \u0027underworld_logo_rollover.tga\u0027 at location \u0027MegaTexture\u0027.",
"context": [
- "Unit_Corrupt_Sabateur"
- ],
- "asset": "U000_DEF3006_ENG.WAV"
+ "IDC_PLAY_FACTION_A_BUTTON_BIG",
+ "MegaTexture"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0210_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "underworld_logo_selected.tga",
+ "message": "Could not find GUI texture \u0027underworld_logo_selected.tga\u0027 at location \u0027MegaTexture\u0027.",
"context": [
- "Unit_Move_Leia"
- ],
- "asset": "U000_LEI0210_ENG.WAV"
+ "IDC_PLAY_FACTION_A_BUTTON_BIG",
+ "MegaTexture"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0105_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "lookat",
+ "message": "Proxy particle \u0027lookat\u0027 not found for model \u0027DATA\\ART\\MODELS\\UV_ECLIPSE_UC.ALO\u0027",
"context": [
- "Unit_Select_Leia"
- ],
- "asset": "U000_LEI0105_ENG.WAV"
+ "Eclipse_Super_Star_Destroyer",
+ "DATA\\ART\\MODELS\\UV_ECLIPSE_UC.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0208_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "w_planet_volcanic.alo",
+ "message": "Unable to find .ALO file \u0027w_planet_volcanic.alo\u0027",
"context": [
- "Unit_Move_Leia"
- ],
- "asset": "U000_LEI0208_ENG.WAV"
+ "Volcanic_Backdrop_Large"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0106_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "Default.fx",
+ "message": "Shader effect \u0027Default.fx\u0027 not found for model \u0027DATA\\ART\\MODELS\\UV_SKIPRAY.ALO\u0027.",
"context": [
- "Unit_Select_Leia"
- ],
- "asset": "U000_LEI0106_ENG.WAV"
+ "Skipray_Bombing_Run",
+ "DATA\\ART\\MODELS\\UV_SKIPRAY.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0202_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "pe_bwing_yellow",
+ "message": "Proxy particle \u0027pe_bwing_yellow\u0027 not found for model \u0027DATA\\ART\\MODELS\\RV_BWING.ALO\u0027",
"context": [
- "Unit_Move_Leia"
- ],
- "asset": "U000_LEI0202_ENG.WAV"
+ "B-Wing",
+ "DATA\\ART\\MODELS\\RV_BWING.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0306_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "Cin_DeathStar_High.alo",
+ "message": "Unable to find .ALO file \u0027Cin_DeathStar_High.alo\u0027",
"context": [
- "Unit_Attack_Leia"
- ],
- "asset": "U000_LEI0306_ENG.WAV"
+ "Death_Star_Whole_small"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0101_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "CIN_Rbel_NavyRow.alo",
+ "message": "Unable to find .ALO file \u0027CIN_Rbel_NavyRow.alo\u0027",
"context": [
- "Unit_Select_Leia"
- ],
- "asset": "U000_LEI0101_ENG.WAV"
+ "Cin_Rebel_NavyRow"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027C000_DST0102_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "W_AllShaders.ALO",
+ "message": "Unable to find .ALO file \u0027W_AllShaders.ALO\u0027",
"context": [
- "EHD_Death_Star_Activate"
- ],
- "asset": "C000_DST0102_ENG.WAV"
+ "Prop_AllShaders"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0103_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "p_prison_light",
+ "message": "Proxy particle \u0027p_prison_light\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_PRISON.ALO\u0027",
"context": [
- "Unit_Select_Leia"
- ],
- "asset": "U000_LEI0103_ENG.WAV"
+ "Imperial_Prison_Facility",
+ "DATA\\ART\\MODELS\\NB_PRISON.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0403_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "Cin_DeathStar_High.alo",
+ "message": "Unable to find .ALO file \u0027Cin_DeathStar_High.alo\u0027",
"context": [
- "Unit_Guard_Leia"
- ],
- "asset": "U000_LEI0403_ENG.WAV"
+ "Death_Star_Whole_Vsmall"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027FS_BEETLE_2.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "W_Vol_Steam01.ALO",
+ "message": "Unable to find .ALO file \u0027W_Vol_Steam01.ALO\u0027",
"context": [
- "SFX_Anim_Beetle_Footsteps"
- ],
- "asset": "FS_BEETLE_2.WAV"
+ "Prop_Vol_Steam01"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0201_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "Cin_Coruscant.alo",
+ "message": "Unable to find .ALO file \u0027Cin_Coruscant.alo\u0027",
"context": [
- "Unit_Move_Leia"
- ],
- "asset": "U000_LEI0201_ENG.WAV"
+ "Corusant_Backdrop_Large 6x"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0203_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "Default.fx",
+ "message": "Shader effect \u0027Default.fx\u0027 not found for model \u0027DATA\\ART\\MODELS\\UV_CRUSADERCLASSCORVETTE.ALO\u0027.",
"context": [
- "Unit_Move_Leia"
- ],
- "asset": "U000_LEI0203_ENG.WAV"
+ "Crusader_Gunship",
+ "DATA\\ART\\MODELS\\UV_CRUSADERCLASSCORVETTE.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0114_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "Lensflare0",
+ "message": "Proxy particle \u0027Lensflare0\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_STARS_HIGH.ALO\u0027",
"context": [
- "Unit_Select_Leia"
- ],
- "asset": "U000_LEI0114_ENG.WAV"
+ "Stars_High",
+ "DATA\\ART\\MODELS\\W_STARS_HIGH.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027FS_BEETLE_1.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "lookat",
+ "message": "Proxy particle \u0027lookat\u0027 not found for model \u0027DATA\\ART\\MODELS\\UV_ECLIPSE.ALO\u0027",
"context": [
- "SFX_Anim_Beetle_Footsteps"
- ],
- "asset": "FS_BEETLE_1.WAV"
+ "Eclipse_Prop",
+ "DATA\\ART\\MODELS\\UV_ECLIPSE.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0304_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "p_uwstation_death",
+ "message": "Proxy particle \u0027p_uwstation_death\u0027 not found for model \u0027DATA\\ART\\MODELS\\UB_05_STATION_D.ALO\u0027",
"context": [
- "Unit_Attack_Leia"
- ],
- "asset": "U000_LEI0304_ENG.WAV"
+ "Underworld_Star_Base_5_Death_Clone",
+ "DATA\\ART\\MODELS\\UB_05_STATION_D.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Cin_DeathStar.tga",
+ "message": "Could not find texture \u0027Cin_DeathStar.tga\u0027 for context: [Test_Base_Hector--\u003EALTTEST.ALO].",
+ "context": [
+ "Test_Base_Hector",
+ "ALTTEST.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Lensflare0",
+ "message": "Proxy particle \u0027Lensflare0\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_STARS_CINE_LUA.ALO\u0027",
+ "context": [
+ "Stars_Lua_Cinematic",
+ "DATA\\ART\\MODELS\\W_STARS_CINE_LUA.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Cin_DStar_LeverPanel.alo",
+ "message": "Unable to find .ALO file \u0027Cin_DStar_LeverPanel.alo\u0027",
+ "context": [
+ "Death_Star_LeverPanel"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Lensflare0",
+ "message": "Proxy particle \u0027Lensflare0\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_STARS_LOW.ALO\u0027",
+ "context": [
+ "Stars_Low",
+ "DATA\\ART\\MODELS\\W_STARS_LOW.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "W_TE_Rock_f_02_b.tga",
+ "message": "Could not find texture \u0027W_TE_Rock_f_02_b.tga\u0027 for context: [Vengeance_Frigate--\u003EUV_VENGEANCE.ALO].",
+ "context": [
+ "Vengeance_Frigate",
+ "UV_VENGEANCE.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Cin_rv_XWingProp.alo",
+ "message": "Unable to find .ALO file \u0027Cin_rv_XWingProp.alo\u0027",
+ "context": [
+ "Cin_X-WingProp"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "CIN_Lambda_Mouth.alo",
+ "message": "Unable to find .ALO file \u0027CIN_Lambda_Mouth.alo\u0027",
+ "context": [
+ "Cin_Lambda_Mouth"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "p_uwstation_death",
+ "message": "Proxy particle \u0027p_uwstation_death\u0027 not found for model \u0027DATA\\ART\\MODELS\\UB_04_STATION_D.ALO\u0027",
+ "context": [
+ "Underworld_Star_Base_4_Death_Clone",
+ "DATA\\ART\\MODELS\\UB_04_STATION_D.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Cin_EV_lambdaShuttle_150.alo",
+ "message": "Unable to find .ALO file \u0027Cin_EV_lambdaShuttle_150.alo\u0027",
+ "context": [
+ "Lambda_Shuttle_150X6-9"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "CIN_Rbel_Soldier_Group.alo",
+ "message": "Unable to find .ALO file \u0027CIN_Rbel_Soldier_Group.alo\u0027",
+ "context": [
+ "Cin_Rebel_SoldierRow"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Cin_EI_Palpatine.alo",
+ "message": "Unable to find .ALO file \u0027Cin_EI_Palpatine.alo\u0027",
+ "context": [
+ "Cin_Emperor_Shot_5"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Cin_Reb_CelebHall_Wall_B.tga",
+ "message": "Could not find texture \u0027Cin_Reb_CelebHall_Wall_B.tga\u0027 for context: [Cin_sith_console--\u003EW_SITH_CONSOLE.ALO].",
+ "context": [
+ "Cin_sith_console",
+ "W_SITH_CONSOLE.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Cin_rv_XWingProp.alo",
+ "message": "Unable to find .ALO file \u0027Cin_rv_XWingProp.alo\u0027",
+ "context": [
+ "Grounded_Xwing"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Cin_EV_Stardestroyer_Warp.alo",
+ "message": "Unable to find .ALO file \u0027Cin_EV_Stardestroyer_Warp.alo\u0027",
+ "context": [
+ "Star_Destroyer_Warp"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "p_particle_master",
+ "message": "Could not find texture \u0027p_particle_master\u0027 for context: [Test_Particle--\u003EP_DIRT_EMITTER_TEST1.ALO].",
+ "context": [
+ "Test_Particle",
+ "P_DIRT_EMITTER_TEST1.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "W_Bush_Swmp00.ALO",
+ "message": "Unable to find .ALO file \u0027W_Bush_Swmp00.ALO\u0027",
+ "context": [
+ "Prop_Swamp_Bush00"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "W_TE_Rock_f_02_b.tga",
+ "message": "Could not find texture \u0027W_TE_Rock_f_02_b.tga\u0027 for context: [The_Peacebringer--\u003EUV_KRAYTCLASSDESTROYER_TYBER.ALO].",
+ "context": [
+ "The_Peacebringer",
+ "UV_KRAYTCLASSDESTROYER_TYBER.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Cin_Reb_CelebHall_Wall_B.tga",
+ "message": "Could not find texture \u0027Cin_Reb_CelebHall_Wall_B.tga\u0027 for context: [Cin_sith_lefthall--\u003EW_SITH_LEFTHALL.ALO].",
+ "context": [
+ "Cin_sith_lefthall",
+ "W_SITH_LEFTHALL.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Cin_Shuttle_Tyderium.alo",
+ "message": "Unable to find .ALO file \u0027Cin_Shuttle_Tyderium.alo\u0027",
+ "context": [
+ "Intro2_Shuttle_Tyderium"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "p_smoke_small_thin2",
+ "message": "Proxy particle \u0027p_smoke_small_thin2\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_PRISON.ALO\u0027",
+ "context": [
+ "Imperial_Prison_Facility",
+ "DATA\\ART\\MODELS\\NB_PRISON.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "P_mptl-2a_Die",
+ "message": "Proxy particle \u0027P_mptl-2a_Die\u0027 not found for model \u0027DATA\\ART\\MODELS\\RV_MPTL-2A.ALO\u0027",
+ "context": [
+ "MPTL",
+ "DATA\\ART\\MODELS\\RV_MPTL-2A.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Cin_DeathStar_High.alo",
+ "message": "Unable to find .ALO file \u0027Cin_DeathStar_High.alo\u0027",
+ "context": [
+ "UM05_PROP_DSTAR"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "CIN_Rbel_GreyGroup.alo",
+ "message": "Unable to find .ALO file \u0027CIN_Rbel_GreyGroup.alo\u0027",
+ "context": [
+ "Cin_Rebel_GreyGroup"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Cin_Officer.alo",
+ "message": "Unable to find .ALO file \u0027Cin_Officer.alo\u0027",
+ "context": [
+ "FIN_Officer"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "CIN_Reb_CelebHall.alo",
+ "message": "Unable to find .ALO file \u0027CIN_Reb_CelebHall.alo\u0027",
+ "context": [
+ "REb_CelebHall"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "p_ewok_drag_dirt",
+ "message": "Proxy particle \u0027p_ewok_drag_dirt\u0027 not found for model \u0027DATA\\ART\\MODELS\\UI_EWOK_HANDLER.ALO\u0027",
+ "context": [
+ "Ewok_Handler",
+ "DATA\\ART\\MODELS\\UI_EWOK_HANDLER.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "p_steam_small",
+ "message": "Proxy particle \u0027p_steam_small\u0027 not found for model \u0027DATA\\ART\\MODELS\\RB_HEAVYVEHICLEFACTORY.ALO\u0027",
+ "context": [
+ "R_Ground_Heavy_Vehicle_Factory",
+ "DATA\\ART\\MODELS\\RB_HEAVYVEHICLEFACTORY.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Cin_DeathStar_Wall.alo",
+ "message": "Unable to find .ALO file \u0027Cin_DeathStar_Wall.alo\u0027",
+ "context": [
+ "Death_Star_Hangar_Outside"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "W_Kamino_Reflect.ALO",
+ "message": "Unable to find .ALO file \u0027W_Kamino_Reflect.ALO\u0027",
+ "context": [
+ "Prop_Kamino_Reflection_00"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Warning",
+ "asset": "i_button_general_dodonna.tga",
+ "message": "Could not find icon \u0027i_button_general_dodonna.tga\u0027 for game object type \u0027General_Dodonna\u0027.",
+ "context": [
+ "General_Dodonna"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "p_cold_tiny01",
+ "message": "Proxy particle \u0027p_cold_tiny01\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_SCH.ALO\u0027",
+ "context": [
+ "Arctic_Civilian_Spawn_House",
+ "DATA\\ART\\MODELS\\NB_SCH.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "p_desert_ground_dust",
+ "message": "Proxy particle \u0027p_desert_ground_dust\u0027 not found for model \u0027DATA\\ART\\MODELS\\EI_MARAJADE.ALO\u0027",
+ "context": [
+ "Mara_Jade",
+ "DATA\\ART\\MODELS\\EI_MARAJADE.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "p_smoke_small_thin2",
+ "message": "Proxy particle \u0027p_smoke_small_thin2\u0027 not found for model \u0027DATA\\ART\\MODELS\\RB_HYPERVELOCITYGUN.ALO\u0027",
+ "context": [
+ "Ground_Empire_Hypervelocity_Gun",
+ "DATA\\ART\\MODELS\\RB_HYPERVELOCITYGUN.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "p_uwstation_death",
+ "message": "Proxy particle \u0027p_uwstation_death\u0027 not found for model \u0027DATA\\ART\\MODELS\\UB_02_STATION_D.ALO\u0027",
+ "context": [
+ "Underworld_Star_Base_2_Death_Clone",
+ "DATA\\ART\\MODELS\\UB_02_STATION_D.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "p_splash_wake_lava.alo",
+ "message": "Unable to find .ALO file \u0027p_splash_wake_lava.alo\u0027",
+ "context": [
+ "Splash_Wake_Lava"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Cin_Reb_CelebHall_Wall.tga",
+ "message": "Could not find texture \u0027Cin_Reb_CelebHall_Wall.tga\u0027 for context: [Cin_sith_console--\u003EW_SITH_CONSOLE.ALO].",
+ "context": [
+ "Cin_sith_console",
+ "W_SITH_CONSOLE.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Cin_EV_TieAdvanced.alo",
+ "message": "Unable to find .ALO file \u0027Cin_EV_TieAdvanced.alo\u0027",
+ "context": [
+ "Fin_Vader_TIE"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "p_uwstation_death",
+ "message": "Proxy particle \u0027p_uwstation_death\u0027 not found for model \u0027DATA\\ART\\MODELS\\UB_03_STATION_D.ALO\u0027",
+ "context": [
+ "Underworld_Star_Base_3_Death_Clone",
+ "DATA\\ART\\MODELS\\UB_03_STATION_D.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "CIN_Trooper_Row.alo",
+ "message": "Unable to find .ALO file \u0027CIN_Trooper_Row.alo\u0027",
+ "context": [
+ "Cin_Trooper_Row"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "CIN_Officer_Row.alo",
+ "message": "Unable to find .ALO file \u0027CIN_Officer_Row.alo\u0027",
+ "context": [
+ "Cin_Officer_Row"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "CINE_EV_StarDestroyer.ALO",
+ "message": "Unable to find .ALO file \u0027CINE_EV_StarDestroyer.ALO\u0027",
+ "context": [
+ "CIN_Star_Destroyer3X"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Cin_EV_lambdaShuttle_150.alo",
+ "message": "Unable to find .ALO file \u0027Cin_EV_lambdaShuttle_150.alo\u0027",
+ "context": [
+ "Lambda_Shuttle_150"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Lensflare0",
+ "message": "Proxy particle \u0027Lensflare0\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_STARS_MEDIUM.ALO\u0027",
+ "context": [
+ "Stars_Medium",
+ "DATA\\ART\\MODELS\\W_STARS_MEDIUM.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Cin_DStar_TurretLasers.alo",
+ "message": "Unable to find .ALO file \u0027Cin_DStar_TurretLasers.alo\u0027",
+ "context": [
+ "TurretLasers_DStar_Xplode"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "CIN_Rbel_Soldier.alo",
+ "message": "Unable to find .ALO file \u0027CIN_Rbel_Soldier.alo\u0027",
+ "context": [
+ "Cin_Rebel_soldier"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0301_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "p_smoke_small_thin4",
+ "message": "Proxy particle \u0027p_smoke_small_thin4\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_PRISON.ALO\u0027",
"context": [
- "Unit_Attack_Leia"
- ],
- "asset": "U000_LEI0301_ENG.WAV"
+ "Imperial_Prison_Facility",
+ "DATA\\ART\\MODELS\\NB_PRISON.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0503_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "Cin_ImperialCraft.alo",
+ "message": "Unable to find .ALO file \u0027Cin_ImperialCraft.alo\u0027",
"context": [
- "Unit_Remove_Corruption_Leia"
- ],
- "asset": "U000_LEI0503_ENG.WAV"
+ "Intro2_ImperialCraft"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0109_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "W_SwampGasEmit.ALO",
+ "message": "Unable to find .ALO file \u0027W_SwampGasEmit.ALO\u0027",
"context": [
- "Unit_Select_Leia"
- ],
- "asset": "U000_LEI0109_ENG.WAV"
+ "Prop_SwampGasEmitter"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0308_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "p_desert_ground_dust",
+ "message": "Proxy particle \u0027p_desert_ground_dust\u0027 not found for model \u0027DATA\\ART\\MODELS\\UI_IG88.ALO\u0027",
"context": [
- "Unit_Attack_Leia"
- ],
- "asset": "U000_LEI0308_ENG.WAV"
+ "IG-88",
+ "DATA\\ART\\MODELS\\UI_IG88.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0402_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "Cin_Planet_Hoth_High.alo",
+ "message": "Unable to find .ALO file \u0027Cin_Planet_Hoth_High.alo\u0027",
"context": [
- "Unit_Guard_Leia"
- ],
- "asset": "U000_LEI0402_ENG.WAV"
+ "Hoth_Backdrop_Large 6x"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0108_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "NB_YsalamiriTree_B.tga",
+ "message": "Could not find texture \u0027NB_YsalamiriTree_B.tga\u0027 for context: [Ysalamiri_Tree--\u003ENB_YSALAMIRI_TREE.ALO].",
"context": [
- "Unit_Select_Leia"
- ],
- "asset": "U000_LEI0108_ENG.WAV"
+ "Ysalamiri_Tree",
+ "NB_YSALAMIRI_TREE.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0307_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "CIN_DeathStar_Hangar.alo",
+ "message": "Unable to find .ALO file \u0027CIN_DeathStar_Hangar.alo\u0027",
"context": [
- "Unit_Attack_Leia"
- ],
- "asset": "U000_LEI0307_ENG.WAV"
+ "Cin_DeathStar_Hangar"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0311_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "Lensflare0",
+ "message": "Proxy particle \u0027Lensflare0\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_STARS_CINE.ALO\u0027",
"context": [
- "Unit_Attack_Leia"
- ],
- "asset": "U000_LEI0311_ENG.WAV"
+ "Stars_Cinematic",
+ "DATA\\ART\\MODELS\\W_STARS_CINE.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0102_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "w_sith_arch.alo",
+ "message": "Unable to find .ALO file \u0027w_sith_arch.alo\u0027",
"context": [
- "Unit_Select_Leia"
- ],
- "asset": "U000_LEI0102_ENG.WAV"
+ "Cin_sith_arch"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0104_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "W_TE_Rock_f_02_b.tga",
+ "message": "Could not find texture \u0027W_TE_Rock_f_02_b.tga\u0027 for context: [F9TZ_Cloaking_Transport--\u003EUV_F9TZTRANSPORT.ALO].",
"context": [
- "Unit_Select_Leia"
- ],
- "asset": "U000_LEI0104_ENG.WAV"
+ "F9TZ_Cloaking_Transport",
+ "UV_F9TZTRANSPORT.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027FS_BEETLE_3.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "Cin_Reb_CelebHall_Wall_B.tga",
+ "message": "Could not find texture \u0027Cin_Reb_CelebHall_Wall_B.tga\u0027 for context: [Cin_w_tile--\u003EW_TILE.ALO].",
"context": [
- "SFX_Anim_Beetle_Footsteps"
- ],
- "asset": "FS_BEETLE_3.WAV"
+ "Cin_w_tile",
+ "W_TILE.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0313_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "CIN_Probe_Droid.alo",
+ "message": "Unable to find .ALO file \u0027CIN_Probe_Droid.alo\u0027",
"context": [
- "Unit_Attack_Leia"
- ],
- "asset": "U000_LEI0313_ENG.WAV"
+ "Empire_Droid"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0206_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "CIN_Fire_Medium.alo",
+ "message": "Unable to find .ALO file \u0027CIN_Fire_Medium.alo\u0027",
"context": [
- "Unit_Move_Leia"
- ],
- "asset": "U000_LEI0206_ENG.WAV"
+ "Fin_Fire_Medium"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_ARC3104_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "Cin_Planet_Alderaan_High.alo",
+ "message": "Unable to find .ALO file \u0027Cin_Planet_Alderaan_High.alo\u0027",
"context": [
- "Unit_Produce_Troops_Arc_Hammer"
- ],
- "asset": "U000_ARC3104_ENG.WAV"
+ "Alderaan_Backdrop_Large 6x"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Warning",
+ "asset": "i_button_ni_nightsister_ranger.tga",
+ "message": "Could not find icon \u0027i_button_ni_nightsister_ranger.tga\u0027 for game object type \u0027Dathomir_Night_Sister\u0027.",
+ "context": [
+ "Dathomir_Night_Sister"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0312_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "Cin_Reb_CelebHall_Wall.tga",
+ "message": "Could not find texture \u0027Cin_Reb_CelebHall_Wall.tga\u0027 for context: [Cin_w_tile--\u003EW_TILE.ALO].",
"context": [
- "Unit_Attack_Leia"
- ],
- "asset": "U000_LEI0312_ENG.WAV"
+ "Cin_w_tile",
+ "W_TILE.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0215_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "W_Kamino_Reflect.ALO",
+ "message": "Unable to find .ALO file \u0027W_Kamino_Reflect.ALO\u0027",
"context": [
- "Unit_Move_Leia"
- ],
- "asset": "U000_LEI0215_ENG.WAV"
+ "Prop_Kamino_Reflection_01"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0107_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "CIN_Lambda_Head.alo",
+ "message": "Unable to find .ALO file \u0027CIN_Lambda_Head.alo\u0027",
"context": [
- "Unit_Select_Leia"
- ],
- "asset": "U000_LEI0107_ENG.WAV"
+ "Cin_Lambda_Head"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0501_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "p_explosion_small_delay00",
+ "message": "Proxy particle \u0027p_explosion_small_delay00\u0027 not found for model \u0027DATA\\ART\\MODELS\\EB_COMMANDCENTER.ALO\u0027",
"context": [
- "Unit_Remove_Corruption_Leia"
- ],
- "asset": "U000_LEI0501_ENG.WAV"
+ "Imperial_Command_Center",
+ "DATA\\ART\\MODELS\\EB_COMMANDCENTER.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027AMB_DES_CLEAR_LOOP_1.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "p_smoke_small_thin2",
+ "message": "Proxy particle \u0027p_smoke_small_thin2\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_MONCAL_BUILDING.ALO\u0027",
"context": [
- "Weather_Ambient_Clear_Sandstorm_Loop"
- ],
- "asset": "AMB_DES_CLEAR_LOOP_1.WAV"
+ "MonCalamari_Spawn_House",
+ "DATA\\ART\\MODELS\\NB_MONCAL_BUILDING.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0504_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "W_Volcano_Rock02.ALO",
+ "message": "Unable to find .ALO file \u0027W_Volcano_Rock02.ALO\u0027",
"context": [
- "Unit_Remove_Corruption_Leia"
- ],
- "asset": "U000_LEI0504_ENG.WAV"
+ "Prop_Volcano_RockForm03"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0502_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "Cin_EI_Vader.alo",
+ "message": "Unable to find .ALO file \u0027Cin_EI_Vader.alo\u0027",
"context": [
- "Unit_Remove_Corruption_Leia"
- ],
- "asset": "U000_LEI0502_ENG.WAV"
+ "Cin_Vader_Shot_6-9"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_DEF3106_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "p_uwstation_death",
+ "message": "Proxy particle \u0027p_uwstation_death\u0027 not found for model \u0027DATA\\ART\\MODELS\\UB_01_STATION_D.ALO\u0027",
"context": [
- "Unit_Weaken_Sabateur"
- ],
- "asset": "U000_DEF3106_ENG.WAV"
+ "Underworld_Star_Base_1_Death_Clone",
+ "DATA\\ART\\MODELS\\UB_01_STATION_D.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_ARC3105_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "Cin_Reb_CelebHall_Wall.tga",
+ "message": "Could not find texture \u0027Cin_Reb_CelebHall_Wall.tga\u0027 for context: [Cin_sith_lefthall--\u003EW_SITH_LEFTHALL.ALO].",
"context": [
- "Unit_Complete_Troops_Arc_Hammer"
- ],
- "asset": "U000_ARC3105_ENG.WAV"
+ "Cin_sith_lefthall",
+ "W_SITH_LEFTHALL.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0601_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "CIN_NavyTrooper_Row.alo",
+ "message": "Unable to find .ALO file \u0027CIN_NavyTrooper_Row.alo\u0027",
"context": [
- "Unit_Increase_Production_Leia"
- ],
- "asset": "U000_LEI0601_ENG.WAV"
+ "Cin_NavyTrooper_Row"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0204_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "p_ssd_debris",
+ "message": "Proxy particle \u0027p_ssd_debris\u0027 not found for model \u0027DATA\\ART\\MODELS\\UV_ECLIPSE_UC_DC.ALO\u0027",
"context": [
- "Unit_Move_Leia"
- ],
- "asset": "U000_LEI0204_ENG.WAV"
+ "Eclipse_Super_Star_Destroyer_Death_Clone",
+ "DATA\\ART\\MODELS\\UV_ECLIPSE_UC_DC.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027U000_LEI0207_ENG.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "Cin_EI_Vader.alo",
+ "message": "Unable to find .ALO file \u0027Cin_EI_Vader.alo\u0027",
"context": [
- "Unit_Move_Leia"
- ],
- "asset": "U000_LEI0207_ENG.WAV"
+ "Cin_Vader"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027FS_BEETLE_4.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "p_explosion_smoke_small_thin5",
+ "message": "Proxy particle \u0027p_explosion_smoke_small_thin5\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_NOGHRI_HUT.ALO\u0027",
"context": [
- "SFX_Anim_Beetle_Footsteps"
- ],
- "asset": "FS_BEETLE_4.WAV"
+ "Noghri_Spawn_House",
+ "DATA\\ART\\MODELS\\NB_NOGHRI_HUT.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
- ],
- "message": "Audio file \u0027AMB_URB_CLEAR_LOOP_1.WAV\u0027 could not be found.",
"severity": "Error",
+ "asset": "p_hp_archammer-damage",
+ "message": "Proxy particle \u0027p_hp_archammer-damage\u0027 not found for model \u0027DATA\\ART\\MODELS\\EV_ARCHAMMER.ALO\u0027",
"context": [
- "Weather_Ambient_Clear_Urban_Loop"
- ],
- "asset": "AMB_URB_CLEAR_LOOP_1.WAV"
+ "Arc_Hammer",
+ "DATA\\ART\\MODELS\\EV_ARCHAMMER.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.GuiDialogs.GuiDialogsVerifier"
- ],
- "message": "Could not find GUI texture \u0027i_dialogue_button_large_middle_off.tga\u0027 at location \u0027Repository\u0027.",
"severity": "Error",
+ "asset": "NB_YsalamiriTree_B.tga",
+ "message": "Could not find texture \u0027NB_YsalamiriTree_B.tga\u0027 for context: [Underworld_Ysalamiri_Cage--\u003EUV_MDU_CAGE.ALO].",
"context": [
- "IDC_PLAY_FACTION_B_BUTTON_BIG",
- "Repository"
- ],
- "asset": "i_dialogue_button_large_middle_off.tga"
+ "Underworld_Ysalamiri_Cage",
+ "UV_MDU_CAGE.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.GuiDialogs.GuiDialogsVerifier"
- ],
- "message": "Could not find GUI texture \u0027underworld_logo_selected.tga\u0027 at location \u0027MegaTexture\u0027.",
"severity": "Error",
+ "asset": "Cin_bridge.alo",
+ "message": "Unable to find .ALO file \u0027Cin_bridge.alo\u0027",
"context": [
- "IDC_PLAY_FACTION_A_BUTTON_BIG",
- "MegaTexture"
- ],
- "asset": "underworld_logo_selected.tga"
+ "UM05_PROP_BRIDGE"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.GuiDialogs.GuiDialogsVerifier"
- ],
- "message": "Could not find GUI texture \u0027underworld_logo_off.tga\u0027 at location \u0027MegaTexture\u0027.",
"severity": "Error",
+ "asset": "Cin_DStar_protons.alo",
+ "message": "Unable to find .ALO file \u0027Cin_DStar_protons.alo\u0027",
"context": [
- "IDC_PLAY_FACTION_A_BUTTON_BIG",
- "MegaTexture"
- ],
- "asset": "underworld_logo_off.tga"
+ "Protons_DStar_Xplode"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.GuiDialogs.GuiDialogsVerifier"
- ],
- "message": "Could not find GUI texture \u0027i_button_petro_sliver.tga\u0027 at location \u0027MegaTexture\u0027.",
"severity": "Error",
+ "asset": "Cin_DeathStar_High.alo",
+ "message": "Unable to find .ALO file \u0027Cin_DeathStar_High.alo\u0027",
"context": [
- "IDC_MENU_PETRO_LOGO",
- "MegaTexture"
- ],
- "asset": "i_button_petro_sliver.tga"
+ "Death_Star_Whole"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Default.fx",
+ "message": "Shader effect \u0027Default.fx\u0027 not found for model \u0027DATA\\ART\\MODELS\\EV_TIE_LANCET.ALO\u0027.",
+ "context": [
+ "Lancet_Air_Artillery",
+ "DATA\\ART\\MODELS\\EV_TIE_LANCET.ALO"
+ ]
},
{
"id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.GuiDialogs.GuiDialogsVerifier"
- ],
- "message": "Could not find GUI texture \u0027underworld_logo_rollover.tga\u0027 at location \u0027MegaTexture\u0027.",
"severity": "Error",
+ "asset": "UB_girder_B.tga",
+ "message": "Could not find texture \u0027UB_girder_B.tga\u0027 for context: [Underworld_Ysalamiri_Cage--\u003EUV_MDU_CAGE.ALO].",
"context": [
- "IDC_PLAY_FACTION_A_BUTTON_BIG",
- "MegaTexture"
- ],
- "asset": "underworld_logo_rollover.tga"
+ "Underworld_Ysalamiri_Cage",
+ "UV_MDU_CAGE.ALO"
+ ]
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_planet_land_forces\u0027 is not connected to a shell component.",
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Cin_bridge.alo",
+ "message": "Unable to find .ALO file \u0027Cin_bridge.alo\u0027",
+ "context": [
+ "Imperial_Bridge"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "p_desert_ground_dust",
+ "message": "Proxy particle \u0027p_desert_ground_dust\u0027 not found for model \u0027DATA\\ART\\MODELS\\UI_SABOTEUR.ALO\u0027",
+ "context": [
+ "Underworld_Saboteur",
+ "DATA\\ART\\MODELS\\UI_SABOTEUR.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "CIN_p_proton_torpedo.alo",
+ "message": "Unable to find .ALO file \u0027CIN_p_proton_torpedo.alo\u0027",
+ "context": [
+ "Cin_Proj_Ground_Proton_Torpedo"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "CIN_Rbel_grey.alo",
+ "message": "Unable to find .ALO file \u0027CIN_Rbel_grey.alo\u0027",
+ "context": [
+ "Cin_Rebel_Grey"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Default.fx",
+ "message": "Shader effect \u0027Default.fx\u0027 not found for model \u0027DATA\\ART\\MODELS\\EV_MDU_SENSORNODE.ALO\u0027.",
+ "context": [
+ "Empire_Offensive_Sensor_Node",
+ "DATA\\ART\\MODELS\\EV_MDU_SENSORNODE.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "w_grenade.tga",
+ "message": "Could not find texture \u0027w_grenade.tga\u0027 for context: [Proj_Merc_Concussion_Grenade--\u003EW_GRENADE.ALO].",
+ "context": [
+ "Proj_Merc_Concussion_Grenade",
+ "W_GRENADE.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "CIN_Fire_Huge.alo",
+ "message": "Unable to find .ALO file \u0027CIN_Fire_Huge.alo\u0027",
+ "context": [
+ "Fin_Fire_Huge"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Cin_EI_Palpatine.alo",
+ "message": "Unable to find .ALO file \u0027Cin_EI_Palpatine.alo\u0027",
+ "context": [
+ "Cin_Emperor_Shot_6-9"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "p_desert_ground_dust",
+ "message": "Proxy particle \u0027p_desert_ground_dust\u0027 not found for model \u0027DATA\\ART\\MODELS\\RI_KYLEKATARN.ALO\u0027",
+ "context": [
+ "Kyle_Katarn",
+ "DATA\\ART\\MODELS\\RI_KYLEKATARN.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "P_heat_small01",
+ "message": "Proxy particle \u0027P_heat_small01\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_VCH.ALO\u0027",
+ "context": [
+ "Volcanic_Civilian_Spawn_House_Independent_AI",
+ "DATA\\ART\\MODELS\\NB_VCH.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "CIN_REb_CelebCharacters.alo",
+ "message": "Unable to find .ALO file \u0027CIN_REb_CelebCharacters.alo\u0027",
+ "context": [
+ "REb_CelebCharacters"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "W_TE_Rock_f_02_b.tga",
+ "message": "Could not find texture \u0027W_TE_Rock_f_02_b.tga\u0027 for context: [TIE_Phantom--\u003EEV_TIE_PHANTOM.ALO].",
+ "context": [
+ "TIE_Phantom",
+ "EV_TIE_PHANTOM.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "CIN_Biker_Row.alo",
+ "message": "Unable to find .ALO file \u0027CIN_Biker_Row.alo\u0027",
+ "context": [
+ "Cin_Biker_Row"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "p_bomb_spin",
+ "message": "Proxy particle \u0027p_bomb_spin\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_THERMAL_DETONATOR_EMPIRE.ALO\u0027",
+ "context": [
+ "TIE_Bomber_Bombing_Run_Bomb",
+ "DATA\\ART\\MODELS\\W_THERMAL_DETONATOR_EMPIRE.ALO"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "Cin_DStar_Dish_close.alo",
+ "message": "Unable to find .ALO file \u0027Cin_DStar_Dish_close.alo\u0027",
+ "context": [
+ "Death_Star_Dish_Close"
+ ]
+ },
+ {
+ "id": "FILE00",
+ "severity": "Error",
+ "asset": "W_droid_steam.alo",
+ "message": "Unable to find .ALO file \u0027W_droid_steam.alo\u0027",
+ "context": [
+ "Prop_Droid_Steam"
+ ]
+ },
+ {
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_planet_land_forces"
+ "asset": "b_planet_left",
+ "message": "The CommandBar component \u0027b_planet_left\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_ground_sell\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_ground_sell"
+ "asset": "encyclopedia_header_text",
+ "message": "The CommandBar component \u0027encyclopedia_header_text\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027st_bracket_medium\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "st_bracket_medium"
+ "asset": "st_control_group",
+ "message": "The CommandBar component \u0027st_control_group\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027b_planet_right\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "b_planet_right"
+ "asset": "tutorial_text_back",
+ "message": "The CommandBar component \u0027tutorial_text_back\u0027 is not connected to a shell component.",
+ "context": []
},
{
"id": "CMDBAR04",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_credit_bar\u0027 is not supported by the game.",
- "severity": "Information",
- "context": [],
- "asset": "g_credit_bar"
+ "severity": "Warning",
+ "asset": "encyclopedia_back",
+ "message": "The CommandBar component \u0027encyclopedia_back\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027zoomed_header_text\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "zoomed_header_text"
+ "asset": "g_build",
+ "message": "The CommandBar component \u0027g_build\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_space_level_pips\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_space_level_pips"
+ "asset": "generic_collision",
+ "message": "The CommandBar component \u0027generic_collision\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027bribed_icon\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "bribed_icon"
+ "asset": "objective_back",
+ "message": "The CommandBar component \u0027objective_back\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027encyclopedia_header_text\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "encyclopedia_header_text"
+ "asset": "st_shields_large",
+ "message": "The CommandBar component \u0027st_shields_large\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027tutorial_text_back\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "tutorial_text_back"
+ "asset": "zoomed_cost_text",
+ "message": "The CommandBar component \u0027zoomed_cost_text\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027encyclopedia_back\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "encyclopedia_back"
+ "asset": "st_bracket_medium",
+ "message": "The CommandBar component \u0027st_bracket_medium\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027encyclopedia_text\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "encyclopedia_text"
+ "asset": "g_smuggled",
+ "message": "The CommandBar component \u0027g_smuggled\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027balance_pip\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "balance_pip"
+ "asset": "skirmish_upgrade",
+ "message": "The CommandBar component \u0027skirmish_upgrade\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027objective_text\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "objective_text"
+ "asset": "st_ability_icon",
+ "message": "The CommandBar component \u0027st_ability_icon\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027skirmish_upgrade\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "skirmish_upgrade"
+ "asset": "g_bounty_hunter",
+ "message": "The CommandBar component \u0027g_bounty_hunter\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027surface_mod_icon\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "surface_mod_icon"
+ "asset": "radar_blip",
+ "message": "The CommandBar component \u0027radar_blip\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027st_hero_health\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "st_hero_health"
+ "asset": "g_weather",
+ "message": "The CommandBar component \u0027g_weather\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027bribe_display\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "bribe_display"
+ "asset": "st_health_medium",
+ "message": "The CommandBar component \u0027st_health_medium\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_build\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_build"
+ "asset": "tutorial_text",
+ "message": "The CommandBar component \u0027tutorial_text\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027garrison_slot_icon\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "garrison_slot_icon"
+ "asset": "garrison_slot_icon",
+ "message": "The CommandBar component \u0027garrison_slot_icon\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_conflict\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_conflict"
+ "asset": "encyclopedia_right_text",
+ "message": "The CommandBar component \u0027encyclopedia_right_text\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027tooltip_name\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "tooltip_name"
+ "asset": "g_planet_ring",
+ "message": "The CommandBar component \u0027g_planet_ring\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027garrison_respawn_counter\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "garrison_respawn_counter"
+ "asset": "tooltip_price",
+ "message": "The CommandBar component \u0027tooltip_price\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027st_ability_icon\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "st_ability_icon"
+ "asset": "bribe_display",
+ "message": "The CommandBar component \u0027bribe_display\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027st_shields_medium\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "st_shields_medium"
+ "asset": "tooltip_icon_land",
+ "message": "The CommandBar component \u0027tooltip_icon_land\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027st_health\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "st_health"
+ "asset": "encyclopedia_center_text",
+ "message": "The CommandBar component \u0027encyclopedia_center_text\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_weather\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_weather"
+ "asset": "st_bracket_small",
+ "message": "The CommandBar component \u0027st_bracket_small\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027st_health_medium\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "st_health_medium"
+ "asset": "g_ground_sell",
+ "message": "The CommandBar component \u0027g_ground_sell\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027st_power\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "st_power"
+ "asset": "st_shields_medium",
+ "message": "The CommandBar component \u0027st_shields_medium\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_ground_level_pips\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_ground_level_pips"
+ "asset": "g_corruption_text",
+ "message": "The CommandBar component \u0027g_corruption_text\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027zoomed_cost_text\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "zoomed_cost_text"
+ "asset": "st_health_bar",
+ "message": "The CommandBar component \u0027st_health_bar\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027bm_title_4011\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "bm_title_4011"
+ "asset": "b_quick_ref",
+ "message": "The CommandBar component \u0027b_quick_ref\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_planet_name\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_planet_name"
+ "asset": "g_special_ability",
+ "message": "The CommandBar component \u0027g_special_ability\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027st_shields_large\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "st_shields_large"
+ "asset": "g_hero_icon",
+ "message": "The CommandBar component \u0027g_hero_icon\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_hero_icon\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_hero_icon"
+ "asset": "st_hero_health",
+ "message": "The CommandBar component \u0027st_hero_health\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027generic_flytext\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "generic_flytext"
+ "asset": "bribed_icon",
+ "message": "The CommandBar component \u0027bribed_icon\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027reinforcement_counter\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "reinforcement_counter"
+ "asset": "g_credit_bar",
+ "message": "The CommandBar component \u0027g_credit_bar\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_planet_value\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_planet_value"
+ "asset": "g_space_icon",
+ "message": "The CommandBar component \u0027g_space_icon\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027radar_blip\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "radar_blip"
+ "asset": "bm_title_4010",
+ "message": "The CommandBar component \u0027bm_title_4010\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_political_control\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_political_control"
+ "asset": "help_back",
+ "message": "The CommandBar component \u0027help_back\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_planet_ring\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_planet_ring"
+ "asset": "g_space_level",
+ "message": "The CommandBar component \u0027g_space_level\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027st_garrison_icon\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "st_garrison_icon"
+ "asset": "g_planet_ability",
+ "message": "The CommandBar component \u0027g_planet_ability\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027encyclopedia_right_text\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "encyclopedia_right_text"
+ "asset": "st_shields",
+ "message": "The CommandBar component \u0027st_shields\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027b_quick_ref\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "b_quick_ref"
+ "asset": "b_planet_right",
+ "message": "The CommandBar component \u0027b_planet_right\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027objective_back\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "objective_back"
+ "asset": "st_health_large",
+ "message": "The CommandBar component \u0027st_health_large\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027encyclopedia_center_text\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "encyclopedia_center_text"
+ "asset": "bm_title_4011",
+ "message": "The CommandBar component \u0027bm_title_4011\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027st_shields\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "st_shields"
+ "asset": "g_ground_level_pips",
+ "message": "The CommandBar component \u0027g_ground_level_pips\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027st_grab_bar\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "st_grab_bar"
+ "asset": "g_political_control",
+ "message": "The CommandBar component \u0027g_political_control\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_smuggler\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_smuggler"
+ "asset": "st_hero_icon",
+ "message": "The CommandBar component \u0027st_hero_icon\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_enemy_hero\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_enemy_hero"
+ "asset": "objective_text",
+ "message": "The CommandBar component \u0027objective_text\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027cs_ability_text\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "cs_ability_text"
+ "asset": "zoomed_text",
+ "message": "The CommandBar component \u0027zoomed_text\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027encyclopedia_cost_text\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "encyclopedia_cost_text"
+ "asset": "garrison_respawn_counter",
+ "message": "The CommandBar component \u0027garrison_respawn_counter\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_planet_ability\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_planet_ability"
+ "asset": "st_grab_bar",
+ "message": "The CommandBar component \u0027st_grab_bar\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027st_control_group\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "st_control_group"
+ "asset": "zoomed_center_text",
+ "message": "The CommandBar component \u0027zoomed_center_text\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027gui_dialog_tooltip\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "gui_dialog_tooltip"
+ "asset": "g_space_level_pips",
+ "message": "The CommandBar component \u0027g_space_level_pips\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027remote_bomb_icon\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "remote_bomb_icon"
+ "asset": "generic_flytext",
+ "message": "The CommandBar component \u0027generic_flytext\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027tutorial_text\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "tutorial_text"
+ "asset": "gui_dialog_tooltip",
+ "message": "The CommandBar component \u0027gui_dialog_tooltip\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_space_icon\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_space_icon"
+ "asset": "st_health",
+ "message": "The CommandBar component \u0027st_health\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027st_bracket_large\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "st_bracket_large"
+ "asset": "g_planet_name",
+ "message": "The CommandBar component \u0027g_planet_name\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027zoomed_back\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "zoomed_back"
+ "asset": "zoomed_header_text",
+ "message": "The CommandBar component \u0027zoomed_header_text\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027encyclopedia_icon\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "encyclopedia_icon"
+ "asset": "g_conflict",
+ "message": "The CommandBar component \u0027g_conflict\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027zoomed_right_text\u0027 is not connected to a shell component.",
- "severity": "Warning",
- "context": [],
- "asset": "zoomed_right_text"
+ "id": "CMDBAR03",
+ "severity": "Information",
+ "asset": "g_credit_bar",
+ "message": "The CommandBar component \u0027g_credit_bar\u0027 is not supported by the game.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027b_beacon_t\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "b_beacon_t"
+ "asset": "zoomed_back",
+ "message": "The CommandBar component \u0027zoomed_back\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_bounty_hunter\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_bounty_hunter"
+ "asset": "zoomed_right_text",
+ "message": "The CommandBar component \u0027zoomed_right_text\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_credit_bar\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_credit_bar"
+ "asset": "st_power",
+ "message": "The CommandBar component \u0027st_power\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_hero\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_hero"
+ "asset": "st_bracket_large",
+ "message": "The CommandBar component \u0027st_bracket_large\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027bm_title_4010\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "bm_title_4010"
+ "asset": "g_ground_icon",
+ "message": "The CommandBar component \u0027g_ground_icon\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_planet_fleet\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_planet_fleet"
+ "asset": "g_planet_land_forces",
+ "message": "The CommandBar component \u0027g_planet_land_forces\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_corruption_icon\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_corruption_icon"
+ "asset": "tooltip_back",
+ "message": "The CommandBar component \u0027tooltip_back\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_smuggled\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_smuggled"
+ "asset": "b_beacon_t",
+ "message": "The CommandBar component \u0027b_beacon_t\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027help_back\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "help_back"
+ "asset": "balance_pip",
+ "message": "The CommandBar component \u0027balance_pip\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027st_bracket_small\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "st_bracket_small"
+ "asset": "g_corruption_icon",
+ "message": "The CommandBar component \u0027g_corruption_icon\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027objective_header_text\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "objective_header_text"
+ "asset": "g_radar_blip",
+ "message": "The CommandBar component \u0027g_radar_blip\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_corruption_text\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_corruption_text"
+ "asset": "g_hero",
+ "message": "The CommandBar component \u0027g_hero\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_ground_level\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_ground_level"
+ "asset": "encyclopedia_cost_text",
+ "message": "The CommandBar component \u0027encyclopedia_cost_text\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027lt_weather_icon\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "lt_weather_icon"
+ "asset": "remote_bomb_icon",
+ "message": "The CommandBar component \u0027remote_bomb_icon\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027cs_ability_button\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "cs_ability_button"
+ "asset": "surface_mod_icon",
+ "message": "The CommandBar component \u0027surface_mod_icon\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_radar_view\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_radar_view"
+ "asset": "cs_ability_button",
+ "message": "The CommandBar component \u0027cs_ability_button\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027objective_icon\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "objective_icon"
+ "asset": "encyclopedia_text",
+ "message": "The CommandBar component \u0027encyclopedia_text\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027tooltip_back\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "tooltip_back"
+ "asset": "objective_icon",
+ "message": "The CommandBar component \u0027objective_icon\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027zoomed_center_text\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "zoomed_center_text"
+ "asset": "st_garrison_icon",
+ "message": "The CommandBar component \u0027st_garrison_icon\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027st_health_bar\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "st_health_bar"
+ "asset": "g_enemy_hero",
+ "message": "The CommandBar component \u0027g_enemy_hero\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027zoomed_text\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "zoomed_text"
+ "asset": "g_radar_view",
+ "message": "The CommandBar component \u0027g_radar_view\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027generic_collision\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "generic_collision"
+ "asset": "tactical_sell",
+ "message": "The CommandBar component \u0027tactical_sell\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027tooltip_icon\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "tooltip_icon"
+ "asset": "cs_ability_text",
+ "message": "The CommandBar component \u0027cs_ability_text\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_radar_blip\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_radar_blip"
+ "asset": "g_smuggler",
+ "message": "The CommandBar component \u0027g_smuggler\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027st_hero_icon\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "st_hero_icon"
+ "asset": "reinforcement_counter",
+ "message": "The CommandBar component \u0027reinforcement_counter\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_space_level\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_space_level"
+ "asset": "g_planet_fleet",
+ "message": "The CommandBar component \u0027g_planet_fleet\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027b_planet_left\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "b_planet_left"
+ "asset": "tooltip_left_text",
+ "message": "The CommandBar component \u0027tooltip_left_text\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027tooltip_icon_land\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "tooltip_icon_land"
+ "asset": "objective_header_text",
+ "message": "The CommandBar component \u0027objective_header_text\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_ground_icon\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_ground_icon"
+ "asset": "lt_weather_icon",
+ "message": "The CommandBar component \u0027lt_weather_icon\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027tooltip_price\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "tooltip_price"
+ "asset": "g_planet_value",
+ "message": "The CommandBar component \u0027g_planet_value\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027tooltip_left_text\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "tooltip_left_text"
+ "asset": "tooltip_icon",
+ "message": "The CommandBar component \u0027tooltip_icon\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027st_health_large\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "st_health_large"
+ "asset": "g_ground_level",
+ "message": "The CommandBar component \u0027g_ground_level\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027tactical_sell\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "tactical_sell"
+ "asset": "tooltip_name",
+ "message": "The CommandBar component \u0027tooltip_name\u0027 is not connected to a shell component.",
+ "context": []
},
{
- "id": "CMDBAR05",
- "verifiers": [
- "AET.ModVerify.Verifiers.CommandBarVerifier"
- ],
- "message": "The CommandBar component \u0027g_special_ability\u0027 is not connected to a shell component.",
+ "id": "CMDBAR04",
"severity": "Warning",
- "context": [],
- "asset": "g_special_ability"
+ "asset": "encyclopedia_icon",
+ "message": "The CommandBar component \u0027encyclopedia_icon\u0027 is not connected to a shell component.",
+ "context": []
}
]
}
\ No newline at end of file
diff --git a/src/ModVerify/DefaultGameVerifiersProvider.cs b/src/ModVerify/DefaultGameVerifiersProvider.cs
index c9982b7..d7ce226 100644
--- a/src/ModVerify/DefaultGameVerifiersProvider.cs
+++ b/src/ModVerify/DefaultGameVerifiersProvider.cs
@@ -1,23 +1,28 @@
-using System;
-using System.Collections.Generic;
-using AET.ModVerify.Settings;
+using AET.ModVerify.Settings;
using AET.ModVerify.Verifiers;
+using AET.ModVerify.Verifiers.CommandBar;
+using AET.ModVerify.Verifiers.Engine;
+using AET.ModVerify.Verifiers.GameObjects;
using AET.ModVerify.Verifiers.GuiDialogs;
+using AET.ModVerify.Verifiers.SfxEvents;
using PG.StarWarsGame.Engine;
+using System;
+using System.Collections.Generic;
namespace AET.ModVerify;
public sealed class DefaultGameVerifiersProvider : IGameVerifiersProvider
{
public IEnumerable GetVerifiers(
- IStarWarsGameEngine database,
+ IStarWarsGameEngine gameEngine,
GameVerifySettings settings,
IServiceProvider serviceProvider)
{
- yield return new ReferencedModelsVerifier(database, settings, serviceProvider);
- yield return new DuplicateNameFinder(database, settings, serviceProvider);
- yield return new AudioFilesVerifier(database, settings, serviceProvider);
- yield return new GuiDialogsVerifier(database, settings, serviceProvider);
- //yield return new CommandBarVerifier(database, settings, serviceProvider);
+ //yield break;
+ yield return new SfxEventVerifier(gameEngine, settings, serviceProvider);
+ yield return new HardcodedAssetsVerifier(gameEngine, settings, serviceProvider);
+ yield return new GuiDialogsVerifier(gameEngine, settings, serviceProvider);
+ yield return new GameObjectTypeVerifier(gameEngine, settings, serviceProvider);
+ yield return new CommandBarVerifier(gameEngine, settings, serviceProvider);
}
}
\ No newline at end of file
diff --git a/src/ModVerify/GameVerifyPipeline.cs b/src/ModVerify/GameVerifyPipeline.cs
index 4ed351e..4a7e0fb 100644
--- a/src/ModVerify/GameVerifyPipeline.cs
+++ b/src/ModVerify/GameVerifyPipeline.cs
@@ -11,6 +11,8 @@
using AET.ModVerify.Settings;
using AET.ModVerify.Utilities;
using AET.ModVerify.Verifiers;
+using AET.ModVerify.Verifiers.Engine;
+using AET.ModVerify.Verifiers.Utilities;
using AnakinRaW.CommonUtilities.SimplePipeline;
using AnakinRaW.CommonUtilities.SimplePipeline.Runners;
using Microsoft.Extensions.DependencyInjection;
diff --git a/src/ModVerify/IGameVerifiersProvider.cs b/src/ModVerify/IGameVerifiersProvider.cs
index 8cde9dc..c34c98d 100644
--- a/src/ModVerify/IGameVerifiersProvider.cs
+++ b/src/ModVerify/IGameVerifiersProvider.cs
@@ -9,7 +9,7 @@ namespace AET.ModVerify;
public interface IGameVerifiersProvider
{
IEnumerable GetVerifiers(
- IStarWarsGameEngine database,
+ IStarWarsGameEngine gameEngine,
GameVerifySettings settings,
IServiceProvider serviceProvider);
}
\ No newline at end of file
diff --git a/src/ModVerify/ModVerify.csproj b/src/ModVerify/ModVerify.csproj
index aecf306..96656cc 100644
--- a/src/ModVerify/ModVerify.csproj
+++ b/src/ModVerify/ModVerify.csproj
@@ -1,7 +1,7 @@
- netstandard2.0;netstandard2.1
+ netstandard2.0;netstandard2.1;net10.0
AlamoEngineTools.ModVerify
AET.ModVerify
AET.ModVerify
@@ -22,13 +22,13 @@
-
+
-
-
-
+
+
+
diff --git a/src/ModVerify/ModVerify.csproj.DotSettings b/src/ModVerify/ModVerify.csproj.DotSettings
index 3859842..d3b37e3 100644
--- a/src/ModVerify/ModVerify.csproj.DotSettings
+++ b/src/ModVerify/ModVerify.csproj.DotSettings
@@ -4,6 +4,9 @@
True
True
False
- True
+ False
+ True
+ True
True
- True
\ No newline at end of file
+ False
+ False
\ No newline at end of file
diff --git a/src/ModVerify/ModVerifyServiceExtensions.cs b/src/ModVerify/ModVerifyServiceExtensions.cs
index 41fbeaa..04567e7 100644
--- a/src/ModVerify/ModVerifyServiceExtensions.cs
+++ b/src/ModVerify/ModVerifyServiceExtensions.cs
@@ -1,4 +1,4 @@
-using AET.ModVerify.Verifiers;
+using AET.ModVerify.Verifiers.Caching;
using Microsoft.Extensions.DependencyInjection;
namespace AET.ModVerify;
@@ -14,7 +14,7 @@ public IServiceCollection AddModVerify()
public IServiceCollection RegisterVerifierCache()
{
- return serviceCollection.AddSingleton(sp => new AlreadyVerifiedCache(sp));
+ return serviceCollection.AddSingleton(new AlreadyVerifiedCache());
}
}
}
\ No newline at end of file
diff --git a/src/ModVerify/Reporting/Baseline/VerificationBaseline.cs b/src/ModVerify/Reporting/Baseline/VerificationBaseline.cs
index d734e6e..80f95b8 100644
--- a/src/ModVerify/Reporting/Baseline/VerificationBaseline.cs
+++ b/src/ModVerify/Reporting/Baseline/VerificationBaseline.cs
@@ -13,7 +13,7 @@ namespace AET.ModVerify.Reporting.Baseline;
public sealed class VerificationBaseline : IReadOnlyCollection
{
- public static readonly Version LatestVersion = new(2, 1);
+ public static readonly Version LatestVersion = new(2, 2);
public static readonly string LatestVersionString = LatestVersion.ToString(2);
public static readonly VerificationBaseline Empty = new(VerificationSeverity.Information, [], null);
@@ -61,7 +61,6 @@ public void ToJson(Stream stream)
{
JsonSerializer.Serialize(stream, new JsonVerificationBaseline(this), ModVerifyJsonSettings.JsonSettings);
}
-
public Task ToJsonAsync(Stream stream)
{
return JsonSerializer.SerializeAsync(stream, new JsonVerificationBaseline(this), ModVerifyJsonSettings.JsonSettings);
diff --git a/src/ModVerify/Reporting/Engine/EngineErrorReporterBase.cs b/src/ModVerify/Reporting/Engine/EngineErrorReporterBase.cs
index 7200f23..f8c7cd2 100644
--- a/src/ModVerify/Reporting/Engine/EngineErrorReporterBase.cs
+++ b/src/ModVerify/Reporting/Engine/EngineErrorReporterBase.cs
@@ -6,25 +6,33 @@
namespace AET.ModVerify.Reporting.Engine;
-internal abstract class EngineErrorReporterBase(IGameRepository gameRepository, IServiceProvider serviceProvider)
- : IGameVerifierInfo
+internal abstract class EngineErrorReporterBase : IGameVerifierInfo
{
- protected readonly IGameRepository GameRepository = gameRepository ?? throw new ArgumentNullException(nameof(gameRepository));
- protected readonly IServiceProvider ServiceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
+ protected readonly IGameRepository GameRepository;
+ protected readonly IServiceProvider ServiceProvider;
public IGameVerifierInfo? Parent => null;
+ public IReadOnlyList VerifierChain { get; }
+
public string Name => GetType().FullName;
public abstract string FriendlyName { get; }
+ protected EngineErrorReporterBase(IGameRepository gameRepository, IServiceProvider serviceProvider)
+ {
+ GameRepository = gameRepository ?? throw new ArgumentNullException(nameof(gameRepository));
+ ServiceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
+ VerifierChain = [this];
+ }
+
public IEnumerable GetErrors(IEnumerable errors)
{
foreach (var error in errors)
{
var errorData = CreateError(error);
yield return new VerificationError(
- errorData.Identifier, errorData.Message, [this], errorData.Context, errorData.Asset, errorData.Severity);
+ errorData.Identifier, errorData.Message, this, errorData.Context, errorData.Asset, errorData.Severity);
}
}
diff --git a/src/ModVerify/Reporting/Engine/GameAssertErrorReporter.cs b/src/ModVerify/Reporting/Engine/GameAssertErrorReporter.cs
index f75334c..0c8c633 100644
--- a/src/ModVerify/Reporting/Engine/GameAssertErrorReporter.cs
+++ b/src/ModVerify/Reporting/Engine/GameAssertErrorReporter.cs
@@ -17,7 +17,12 @@ protected override ErrorData CreateError(EngineAssert assert)
var context = new List();
context.AddRange(assert.Context);
context.Add($"location='{GetLocation(assert)}'");
- return new ErrorData(GetIdFromError(assert.Kind), assert.Message, context, assert.Value, VerificationSeverity.Warning);
+ return new ErrorData(
+ GetIdFromError(assert.Kind),
+ assert.Message,
+ context,
+ assert.Value,
+ VerificationSeverity.Warning);
}
private static string GetLocation(EngineAssert assert)
@@ -41,6 +46,7 @@ private static string GetIdFromError(EngineAssertKind assertKind)
EngineAssertKind.ValueOutOfRange => VerifierErrorCodes.AssertValueOutOfRange,
EngineAssertKind.InvalidValue => VerifierErrorCodes.AssertValueInvalid,
EngineAssertKind.FileNotFound => VerifierErrorCodes.FileNotFound,
+ EngineAssertKind.DuplicateEntry => VerifierErrorCodes.Duplicate,
_ => throw new ArgumentOutOfRangeException(nameof(assertKind), assertKind, null)
};
}
diff --git a/src/ModVerify/Reporting/Engine/GameEngineErrorCollection.cs b/src/ModVerify/Reporting/Engine/GameEngineErrorCollection.cs
index ba0abf5..8cb67c0 100644
--- a/src/ModVerify/Reporting/Engine/GameEngineErrorCollection.cs
+++ b/src/ModVerify/Reporting/Engine/GameEngineErrorCollection.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using PG.StarWarsGame.Engine.ErrorReporting;
+using PG.StarWarsGame.Files.XML.ErrorHandling;
namespace AET.ModVerify.Reporting.Engine;
@@ -17,7 +18,7 @@ public sealed class GameEngineErrorCollection : IGameEngineErrorCollection, IGam
public IEnumerable Asserts => _asserts.ToList();
- void IGameEngineErrorReporter.Report(XmlError error)
+ void IXmlParserErrorReporter.Report(XmlError error)
{
_xmlErrors.Add(error);
}
diff --git a/src/ModVerify/Reporting/Engine/IGameEngineErrorCollection.cs b/src/ModVerify/Reporting/Engine/IGameEngineErrorCollection.cs
index adf734d..286d047 100644
--- a/src/ModVerify/Reporting/Engine/IGameEngineErrorCollection.cs
+++ b/src/ModVerify/Reporting/Engine/IGameEngineErrorCollection.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using PG.StarWarsGame.Engine.ErrorReporting;
+using PG.StarWarsGame.Files.XML.ErrorHandling;
namespace AET.ModVerify.Reporting.Engine;
diff --git a/src/ModVerify/Reporting/Engine/XmlParseErrorReporter.cs b/src/ModVerify/Reporting/Engine/XmlParseErrorReporter.cs
index 2629f26..9548ad4 100644
--- a/src/ModVerify/Reporting/Engine/XmlParseErrorReporter.cs
+++ b/src/ModVerify/Reporting/Engine/XmlParseErrorReporter.cs
@@ -4,7 +4,6 @@
using AET.ModVerify.Utilities;
using AET.ModVerify.Verifiers;
using Microsoft.Extensions.DependencyInjection;
-using PG.StarWarsGame.Engine.ErrorReporting;
using PG.StarWarsGame.Engine.IO;
using PG.StarWarsGame.Files.XML.ErrorHandling;
@@ -29,7 +28,8 @@ protected override ErrorData CreateError(XmlError error)
var context = new List
{
- strippedFileName
+ $"Parser: {error.Parser.Name}",
+ $"File: {strippedFileName}"
};
var xmlElement = error.Element;
@@ -75,6 +75,8 @@ private static VerificationSeverity GetSeverityFromError(XmlParseErrorKind xmlEr
XmlParseErrorKind.DataBeforeHeader => VerificationSeverity.Information,
XmlParseErrorKind.MissingNode => VerificationSeverity.Critical,
XmlParseErrorKind.UnknownNode => VerificationSeverity.Information,
+ XmlParseErrorKind.TagHasElements => VerificationSeverity.Warning,
+ XmlParseErrorKind.UnexceptedElementName => VerificationSeverity.Information,
_ => VerificationSeverity.Warning
};
}
@@ -94,6 +96,8 @@ private static string GetIdFromError(XmlParseErrorKind xmlErrorErrorKind)
XmlParseErrorKind.DataBeforeHeader => VerifierErrorCodes.XmlDataBeforeHeader,
XmlParseErrorKind.MissingNode => VerifierErrorCodes.XmlMissingNode,
XmlParseErrorKind.UnknownNode => VerifierErrorCodes.XmlUnsupportedTag,
+ XmlParseErrorKind.TagHasElements => VerifierErrorCodes.XmlElementsInTag,
+ XmlParseErrorKind.UnexceptedElementName => VerifierErrorCodes.XmlUnexceptedElementName,
_ => throw new ArgumentOutOfRangeException(nameof(xmlErrorErrorKind), xmlErrorErrorKind, null)
};
}
diff --git a/src/ModVerify/Reporting/Json/JsonAggregatedVerificationError.cs b/src/ModVerify/Reporting/Json/JsonAggregatedVerificationError.cs
index 5a9cbb3..a60b3de 100644
--- a/src/ModVerify/Reporting/Json/JsonAggregatedVerificationError.cs
+++ b/src/ModVerify/Reporting/Json/JsonAggregatedVerificationError.cs
@@ -16,14 +16,16 @@ public JsonAggregatedVerificationError(
string message,
VerificationSeverity severity,
IEnumerable>? contexts,
- string? asset) : base(id, verifierChain, message, severity, asset)
+ string? asset) : base(id, severity, asset, message, verifierChain)
{
Contexts = contexts ?? [];
}
public JsonAggregatedVerificationError(
VerificationError error,
- IEnumerable> contexts) : base(error)
+ IEnumerable> contexts,
+ bool verbose = false)
+ : base(error, verbose)
{
Contexts = contexts;
}
diff --git a/src/ModVerify/Reporting/Json/JsonVerificationError.cs b/src/ModVerify/Reporting/Json/JsonVerificationError.cs
index 0e23283..8094058 100644
--- a/src/ModVerify/Reporting/Json/JsonVerificationError.cs
+++ b/src/ModVerify/Reporting/Json/JsonVerificationError.cs
@@ -8,22 +8,23 @@ internal class JsonVerificationError : JsonVerificationErrorBase
{
[JsonPropertyName("context")]
[JsonPropertyOrder(99)]
- public IEnumerable? ContextEntries { get; }
+ public IEnumerable ContextEntries { get; }
[JsonConstructor]
public JsonVerificationError(
- string id,
- IReadOnlyList? verifierChain,
+ string id,
+ VerificationSeverity severity,
+ string? asset,
string message,
- VerificationSeverity severity,
- IEnumerable? contextEntries,
- string? asset) : base(id, verifierChain, message, severity, asset)
+ IReadOnlyList? verifierChain,
+ IEnumerable contextEntries) : base(id, severity, asset, message, verifierChain)
{
ContextEntries = contextEntries;
}
- public JsonVerificationError(VerificationError error) : base(error)
+ public JsonVerificationError(VerificationError error, bool verbose = false)
+ : base(error, verbose)
{
- ContextEntries = error.ContextEntries.Any() ? error.ContextEntries : null;
+ ContextEntries = error.ContextEntries.Any() ? error.ContextEntries : [];
}
}
\ No newline at end of file
diff --git a/src/ModVerify/Reporting/Json/JsonVerificationErrorBase.cs b/src/ModVerify/Reporting/Json/JsonVerificationErrorBase.cs
index 06af012..b7aa298 100644
--- a/src/ModVerify/Reporting/Json/JsonVerificationErrorBase.cs
+++ b/src/ModVerify/Reporting/Json/JsonVerificationErrorBase.cs
@@ -11,12 +11,6 @@ internal abstract class JsonVerificationErrorBase
[JsonPropertyName("id")]
public string Id { get; }
- [JsonPropertyName("verifiers")]
- public IReadOnlyList VerifierChain { get; }
-
- [JsonPropertyName("message")]
- public string Message { get; }
-
[JsonPropertyName("severity")]
[JsonConverter(typeof(JsonStringEnumConverter))]
public VerificationSeverity Severity { get; }
@@ -24,24 +18,29 @@ internal abstract class JsonVerificationErrorBase
[JsonPropertyName("asset")]
public string Asset { get; }
- protected JsonVerificationErrorBase(
- string id,
- IReadOnlyList? verifierChain,
- string message,
+ [JsonPropertyName("message")]
+ public string Message { get; }
+
+ [JsonPropertyName("verifiers")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ public IReadOnlyList? VerifierChain { get; }
+
+ protected JsonVerificationErrorBase(string id,
VerificationSeverity severity,
- string? asset)
+ string? asset,
+ string message,
+ IReadOnlyList? verifierChain)
{
Id = id;
- VerifierChain = verifierChain ?? [];
+ VerifierChain = verifierChain;
Message = message;
Severity = severity;
Asset = asset ?? string.Empty;
}
-
- protected JsonVerificationErrorBase(VerificationError error)
+ protected JsonVerificationErrorBase(VerificationError error, bool verbose = false)
{
Id = error.Id;
- VerifierChain = error.VerifierChain.Select(x => x.Name).ToList();
+ VerifierChain = verbose ? error.VerifierChain.Select(x => x.Name).ToList() : null;
Message = error.Message;
Severity = error.Severity;
Asset = error.Asset;
diff --git a/src/ModVerify/Reporting/Reporters/JSON/JsonReporter.cs b/src/ModVerify/Reporting/Reporters/JSON/JsonReporter.cs
index 1feb655..ac11bb6 100644
--- a/src/ModVerify/Reporting/Reporters/JSON/JsonReporter.cs
+++ b/src/ModVerify/Reporting/Reporters/JSON/JsonReporter.cs
@@ -30,20 +30,24 @@ private JsonVerificationReport CreateJsonReport(VerificationResult result)
if (Settings.AggregateResults)
{
errors = result.Errors
+ .OrderByDescending(x => x.Severity)
+ .ThenBy(x => x.Id)
.GroupBy(x => new GroupKey(x.Asset, x.Id, x.VerifierChain))
.Select, JsonVerificationErrorBase>(g =>
{
var first = g.First();
var contexts = g.Select(x => x.ContextEntries).ToList();
-
if (contexts.Count == 1)
- return new JsonVerificationError(first);
- return new JsonAggregatedVerificationError(first, contexts);
+ return new JsonVerificationError(first, Settings.Verbose);
+ return new JsonAggregatedVerificationError(first, contexts, Settings.Verbose);
});
}
else
{
- errors = result.Errors.Select(x => new JsonVerificationError(x));
+ errors = result.Errors
+ .OrderByDescending(x => x.Severity)
+ .ThenBy(x => x.Id)
+ .Select(x => new JsonVerificationError(x, Settings.Verbose));
}
return new JsonVerificationReport
diff --git a/src/ModVerify/Reporting/Reporters/JSON/JsonReporterSettings.cs b/src/ModVerify/Reporting/Reporters/JSON/JsonReporterSettings.cs
index 7ccbba9..a2503ed 100644
--- a/src/ModVerify/Reporting/Reporters/JSON/JsonReporterSettings.cs
+++ b/src/ModVerify/Reporting/Reporters/JSON/JsonReporterSettings.cs
@@ -1,5 +1,4 @@
namespace AET.ModVerify.Reporting.Reporters;
-
public record JsonReporterSettings : FileBasedReporterSettings
{
public bool AggregateResults { get; init; }
diff --git a/src/ModVerify/Reporting/Reporters/ReporterSettings.cs b/src/ModVerify/Reporting/Reporters/ReporterSettings.cs
index 73332eb..6cd56d3 100644
--- a/src/ModVerify/Reporting/Reporters/ReporterSettings.cs
+++ b/src/ModVerify/Reporting/Reporters/ReporterSettings.cs
@@ -3,4 +3,5 @@
public record ReporterSettings
{
public VerificationSeverity MinimumReportSeverity { get; init; } = VerificationSeverity.Information;
+ public bool Verbose { get; init; }
}
\ No newline at end of file
diff --git a/src/ModVerify/Reporting/RestoredVerifierInfo.cs b/src/ModVerify/Reporting/RestoredVerifierInfo.cs
index 0c29488..0f0a87b 100644
--- a/src/ModVerify/Reporting/RestoredVerifierInfo.cs
+++ b/src/ModVerify/Reporting/RestoredVerifierInfo.cs
@@ -1,10 +1,15 @@
using AET.ModVerify.Verifiers;
+using AET.ModVerify.Verifiers.Utilities;
+using System.Collections.Generic;
namespace AET.ModVerify.Reporting;
internal sealed class RestoredVerifierInfo : IGameVerifierInfo
{
public IGameVerifierInfo? Parent { get; init; }
+
+ public IReadOnlyList VerifierChain => field ??= this.GetVerifierChain();
+
public required string Name { get; init; }
public string FriendlyName => Name;
}
\ No newline at end of file
diff --git a/src/ModVerify/Reporting/VerificationError.cs b/src/ModVerify/Reporting/VerificationError.cs
index d55f71b..2e95327 100644
--- a/src/ModVerify/Reporting/VerificationError.cs
+++ b/src/ModVerify/Reporting/VerificationError.cs
@@ -28,11 +28,13 @@ public sealed class VerificationError : IEquatable
public VerificationError(
string id,
string message,
- IReadOnlyList verifiers,
+ IGameVerifierInfo verifier,
IEnumerable contextEntries,
string asset,
VerificationSeverity severity)
{
+ if (verifier == null)
+ throw new ArgumentNullException(nameof(verifier));
if (contextEntries == null)
throw new ArgumentNullException(nameof(contextEntries));
if (asset is null)
@@ -41,7 +43,7 @@ public VerificationError(
Id = id;
Message = message ?? throw new ArgumentNullException(nameof(message));
- VerifierChain = [.. verifiers];
+ VerifierChain = verifier.VerifierChain;
Severity = severity;
ContextEntries = _contextEntries = [.. contextEntries];
Asset = asset;
@@ -58,18 +60,18 @@ internal VerificationError(JsonVerificationError error)
}
public static VerificationError Create(
- IReadOnlyList verifiers,
+ IGameVerifierInfo verifier,
string id,
string message,
VerificationSeverity severity,
IEnumerable context,
string asset)
{
- return new VerificationError(id, message, verifiers, context, asset, severity);
+ return new VerificationError(id, message, verifier, context, asset, severity);
}
public static VerificationError Create(
- IReadOnlyList verifiers,
+ IGameVerifierInfo verifier,
string id,
string message,
VerificationSeverity severity,
@@ -78,7 +80,7 @@ public static VerificationError Create(
return new VerificationError(
id,
message,
- verifiers,
+ verifier,
[],
asset,
severity);
@@ -120,8 +122,11 @@ public override string ToString()
$"{Id}: Message={Message}; Asset='{Asset}'; Context=[{string.Join(",", ContextEntries)}];";
}
- private static IReadOnlyList RestoreVerifierChain(IReadOnlyList errorVerifierChain)
+ private static IReadOnlyList RestoreVerifierChain(IReadOnlyList? errorVerifierChain)
{
+ if (errorVerifierChain is null)
+ return [];
+
var verifierChain = new List();
IGameVerifierInfo? previousVerifier = null;
diff --git a/src/ModVerify/Reporting/VerifierChainEqualityComparer.cs b/src/ModVerify/Reporting/VerifierChainEqualityComparer.cs
index abb01ef..27897cb 100644
--- a/src/ModVerify/Reporting/VerifierChainEqualityComparer.cs
+++ b/src/ModVerify/Reporting/VerifierChainEqualityComparer.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using AET.ModVerify.Verifiers;
+using AET.ModVerify.Verifiers.Utilities;
namespace AET.ModVerify.Reporting;
diff --git a/src/ModVerify/Resources/Schemas/2.1/baseline.json b/src/ModVerify/Resources/Schemas/2.2/baseline.json
similarity index 92%
rename from src/ModVerify/Resources/Schemas/2.1/baseline.json
rename to src/ModVerify/Resources/Schemas/2.2/baseline.json
index da37c4d..d893b4d 100644
--- a/src/ModVerify/Resources/Schemas/2.1/baseline.json
+++ b/src/ModVerify/Resources/Schemas/2.2/baseline.json
@@ -1,5 +1,5 @@
{
- "$id": "https://AlamoEngine-Tools.github.io/schemas/mod-verify/2.1/baseline",
+ "$id": "https://AlamoEngine-Tools.github.io/schemas/mod-verify/2.2/baseline",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "Represents a baseline for AET ModVerify",
"type": "object",
@@ -73,12 +73,6 @@
"severity": {
"$ref": "#/$defs/severity"
},
- "verifiers": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
"context": {
"type": "array",
"items": {
@@ -91,7 +85,6 @@
"message",
"asset",
"severity",
- "verifiers",
"context"
],
"additionalProperties": false
@@ -99,7 +92,7 @@
},
"properties": {
"version": {
- "const": "2.1"
+ "const": "2.2"
},
"minSeverity": {
"$ref": "#/$defs/severity"
diff --git a/src/ModVerify/Verifiers/AlreadyVerifiedCache.cs b/src/ModVerify/Verifiers/AlreadyVerifiedCache.cs
deleted file mode 100644
index 530ca4e..0000000
--- a/src/ModVerify/Verifiers/AlreadyVerifiedCache.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-using System.Collections.Concurrent;
-using Microsoft.Extensions.DependencyInjection;
-using PG.Commons.Hashing;
-using PG.StarWarsGame.Engine;
-
-namespace AET.ModVerify.Verifiers;
-
-internal sealed class AlreadyVerifiedCache(IServiceProvider serviceProvider) : IAlreadyVerifiedCache
-{
- private readonly ICrc32HashingService _crc32Hashing = serviceProvider.GetRequiredService();
- private readonly ConcurrentDictionary _cachedChecksums = new();
-
- public bool TryAddEntry(string entry)
- {
- return TryAddEntry(entry.AsSpan());
- }
-
- public bool TryAddEntry(ReadOnlySpan entry)
- {
- return TryAddEntry(_crc32Hashing.GetCrc32Upper(entry, PGConstants.DefaultPGEncoding));
- }
-
- public bool TryAddEntry(Crc32 checksum)
- {
- return _cachedChecksums.TryAdd(checksum, 0);
- }
-}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/AudioFilesVerifier.cs b/src/ModVerify/Verifiers/AudioFilesVerifier.cs
deleted file mode 100644
index ddd9252..0000000
--- a/src/ModVerify/Verifiers/AudioFilesVerifier.cs
+++ /dev/null
@@ -1,249 +0,0 @@
-using System;
-using System.Buffers;
-using System.Collections.Generic;
-using System.IO;
-using System.IO.Abstractions;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using AET.ModVerify.Reporting;
-using AET.ModVerify.Settings;
-using AnakinRaW.CommonUtilities.FileSystem.Normalization;
-using Microsoft.Extensions.DependencyInjection;
-using PG.Commons.Hashing;
-using PG.StarWarsGame.Engine;
-using PG.StarWarsGame.Engine.Audio.Sfx;
-using PG.StarWarsGame.Engine.Localization;
-#if NETSTANDARD2_0
-using AnakinRaW.CommonUtilities.FileSystem;
-#endif
-
-namespace AET.ModVerify.Verifiers;
-
-public class AudioFilesVerifier : GameVerifier
-{
- private static readonly PathNormalizeOptions SampleNormalizerOptions = new()
- {
- UnifyCase = UnifyCasingKind.UpperCaseForce,
- UnifySeparatorKind = DirectorySeparatorKind.Windows,
- UnifyDirectorySeparators = true
- };
-
- private readonly ICrc32HashingService _hashingService;
- private readonly IFileSystem _fileSystem;
- private readonly IGameLanguageManager _languageManager;
-
- public AudioFilesVerifier(IStarWarsGameEngine gameEngine, GameVerifySettings settings, IServiceProvider serviceProvider)
- : base(null, gameEngine, settings, serviceProvider)
- {
- _hashingService = serviceProvider.GetRequiredService();
- _fileSystem = serviceProvider.GetRequiredService();
- _languageManager = serviceProvider.GetRequiredService()
- .GetLanguageManager(Repository.EngineType);
- }
-
- public override string FriendlyName => "Audio Files";
-
- public override void Verify(CancellationToken token)
- {
- var visitedSamples = new HashSet();
- var languagesToVerify = GetLanguagesToVerify().ToList();
-
-
- var numSamples = GameEngine.SfxGameManager.Entries.Sum(x => x.AllSamples.Count());
- double counter = 0;
-
- foreach (var sfxEvent in GameEngine.SfxGameManager.Entries)
- {
- foreach (var codedSample in sfxEvent.AllSamples)
- {
- OnProgress(++counter / numSamples, $"Audio File - '{codedSample}'");
- VerifySample(codedSample.AsSpan(), sfxEvent, languagesToVerify, visitedSamples);
- }
- }
- }
-
- private void VerifySample(ReadOnlySpan sample, SfxEvent sfxEvent, IEnumerable languagesToVerify, HashSet visitedSamples)
- {
- char[]? pooledBuffer = null;
-
- var buffer = sample.Length < PGConstants.MaxMegEntryPathLength
- ? stackalloc char[PGConstants.MaxMegEntryPathLength]
- : pooledBuffer = ArrayPool.Shared.Rent(sample.Length);
-
- try
- {
- var length = PathNormalizer.Normalize(sample, buffer, SampleNormalizerOptions);
- var sampleNameBuffer = buffer.Slice(0, length);
-
- var crc = _hashingService.GetCrc32(sampleNameBuffer, Encoding.ASCII);
- if (!visitedSamples.Add(crc))
- return;
-
- if (sfxEvent.IsLocalized)
- {
- foreach (var language in languagesToVerify)
- {
- VerifySampleLocalized(sfxEvent, sampleNameBuffer, language, out var localized);
- if (!localized)
- return;
- }
- }
- else
- {
- VerifySample(sampleNameBuffer, sfxEvent);
- }
- }
- finally
- {
- if (pooledBuffer is not null)
- ArrayPool.Shared.Return(pooledBuffer);
- }
-
- }
-
- private void VerifySampleLocalized(SfxEvent sfxEvent, ReadOnlySpan sample, LanguageType language, out bool localized)
- {
- char[]? pooledBuffer = null;
-
- var buffer = sample.Length < PGConstants.MaxMegEntryPathLength
- ? stackalloc char[PGConstants.MaxMegEntryPathLength]
- : pooledBuffer = ArrayPool.Shared.Rent(sample.Length);
- try
- {
- var l = _languageManager.LocalizeFileName(sample, language, buffer, out localized);
- var localizedName = buffer.Slice(0, l);
- VerifySample(localizedName, sfxEvent);
- }
- finally
- {
- if (pooledBuffer is not null)
- ArrayPool.Shared.Return(pooledBuffer);
- }
- }
-
- private void VerifySample(ReadOnlySpan sample, SfxEvent sfxEvent)
- {
- using var sampleStream = Repository.TryOpenFile(sample);
- if (sampleStream is null)
- {
- var sampleString = sample.ToString();
- AddError(VerificationError.Create(
- VerifierChain,
- VerifierErrorCodes.FileNotFound,
- $"Audio file '{sampleString}' could not be found.",
- VerificationSeverity.Error,
- [sfxEvent.Name],
- sampleString));
- return;
- }
- using var binaryReader = new BinaryReader(sampleStream);
-
- // Skip Header + "fmt "
- binaryReader.BaseStream.Seek(16, SeekOrigin.Begin);
-
- var fmtSize = binaryReader.ReadInt32();
- var format = (WaveFormats)binaryReader.ReadInt16();
- var channels = binaryReader.ReadInt16();
-
- var sampleRate = binaryReader.ReadInt32();
- var bytesPerSecond = binaryReader.ReadInt32();
-
- var frameSize = binaryReader.ReadInt16();
- var bitPerSecondPerChannel = binaryReader.ReadInt16();
-
- if (format != WaveFormats.PCM)
- {
- var sampleString = sample.ToString();
- AddError(VerificationError.Create(
- VerifierChain,
- VerifierErrorCodes.SampleNotPCM,
- $"Audio file '{sampleString}' has an invalid format '{format}'. Supported is {WaveFormats.PCM}",
- VerificationSeverity.Error,
- [sfxEvent.Name],
- sampleString));
- }
-
- if (channels > 1 && !IsAmbient2D(sfxEvent))
- {
- var sampleString = sample.ToString();
- AddError(VerificationError.Create(
- VerifierChain,
- VerifierErrorCodes.SampleNotMono,
- $"Audio file '{sampleString}' is not mono audio.",
- VerificationSeverity.Information,
- sampleString));
- }
-
- if (sampleRate > 48_000)
- {
- var sampleString = sample.ToString();
- AddError(VerificationError.Create(
- VerifierChain,
- VerifierErrorCodes. InvalidSampleRate,
- $"Audio file '{sampleString}' has a too high sample rate of {sampleRate}. Maximum is 48.000Hz.",
- VerificationSeverity.Error,
- [sfxEvent.Name],
- sampleString));
- }
-
- if (bitPerSecondPerChannel > 16)
- {
- var sampleString = sample.ToString();
- AddError(VerificationError.Create(
- VerifierChain,
- VerifierErrorCodes.InvalidBitsPerSeconds,
- $"Audio file '{sampleString}' has an invalid bit size of {bitPerSecondPerChannel}. Supported are 16bit.",
- VerificationSeverity.Error,
- [sfxEvent.Name],
- sampleString));
- }
- }
-
- // Some heuristics whether a SFXEvent is most likely to be an ambient sound.
- private bool IsAmbient2D(SfxEvent sfxEvent)
- {
- if (!sfxEvent.Is2D)
- return false;
-
- if (sfxEvent.IsPreset)
- return false;
-
- // If the event is located in SFXEventsAmbient.xml we simply assume it's an ambient sound.
- var fileName = _fileSystem.Path.GetFileName(sfxEvent.Location.XmlFile.AsSpan());
- if (fileName.Equals("SFXEventsAmbient.xml".AsSpan(), StringComparison.OrdinalIgnoreCase))
- return true;
-
- if (string.IsNullOrEmpty(sfxEvent.UsePresetName))
- return false;
-
- if (sfxEvent.UsePresetName!.StartsWith("Preset_AMB_2D"))
- return true;
-
- return true;
- }
-
- private IEnumerable GetLanguagesToVerify()
- {
- switch (Settings.LocalizationOption)
- {
- case VerifyLocalizationOption.English:
- return new List { LanguageType.English };
- case VerifyLocalizationOption.CurrentSystem:
- return new List { _languageManager.GetLanguagesFromUser() };
- case VerifyLocalizationOption.AllInstalled:
- return GameEngine.InstalledLanguages;
- case VerifyLocalizationOption.All:
- return _languageManager.SupportedLanguages;
- default:
- throw new NotSupportedException($"{Settings.LocalizationOption} is not supported");
- }
- }
-
- private enum WaveFormats
- {
- PCM = 1,
- MSADPCM = 2,
- IEEE_Float = 3,
- }
-}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/Caching/AlreadyVerifiedCache.cs b/src/ModVerify/Verifiers/Caching/AlreadyVerifiedCache.cs
new file mode 100644
index 0000000..c6dda7c
--- /dev/null
+++ b/src/ModVerify/Verifiers/Caching/AlreadyVerifiedCache.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+
+namespace AET.ModVerify.Verifiers.Caching;
+
+internal sealed class AlreadyVerifiedCache : IAlreadyVerifiedCache
+{
+ private readonly Dictionary _cachedEntries = new();
+
+ public bool TryAddEntry(string entry, bool assetExists)
+ {
+ var upper = entry.ToUpperInvariant();
+
+#if NETSTANDARD2_1 || NET
+ return _cachedEntries.TryAdd(upper, assetExists);
+#else
+ var alreadyVerified = _cachedEntries.ContainsKey(upper);
+ if (alreadyVerified)
+ return false;
+
+ _cachedEntries[upper] = assetExists;
+ return true;
+#endif
+ }
+
+ public VerifiedCacheEntry GetEntry(string entry)
+ {
+ var upper = entry.ToUpperInvariant();
+ var alreadyVerified = _cachedEntries.TryGetValue(upper, out var exists);
+ return alreadyVerified ? new VerifiedCacheEntry(true, exists) : default;
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/Caching/IAlreadyVerifiedCache.cs b/src/ModVerify/Verifiers/Caching/IAlreadyVerifiedCache.cs
new file mode 100644
index 0000000..68f39b4
--- /dev/null
+++ b/src/ModVerify/Verifiers/Caching/IAlreadyVerifiedCache.cs
@@ -0,0 +1,8 @@
+namespace AET.ModVerify.Verifiers.Caching;
+
+public interface IAlreadyVerifiedCache
+{
+ bool TryAddEntry(string entry, bool assetExists);
+
+ VerifiedCacheEntry GetEntry(string entry);
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/Caching/VerifiedCacheEntry.cs b/src/ModVerify/Verifiers/Caching/VerifiedCacheEntry.cs
new file mode 100644
index 0000000..252a7c0
--- /dev/null
+++ b/src/ModVerify/Verifiers/Caching/VerifiedCacheEntry.cs
@@ -0,0 +1,14 @@
+namespace AET.ModVerify.Verifiers.Caching;
+
+public readonly struct VerifiedCacheEntry
+{
+ public bool AlreadyVerified { get; }
+
+ public bool AssetExists { get; }
+
+ public VerifiedCacheEntry(bool alreadyVerified, bool assetExists)
+ {
+ AlreadyVerified = alreadyVerified;
+ AssetExists = assetExists;
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/CommandBar/CommandBarVerifier.Base.cs b/src/ModVerify/Verifiers/CommandBar/CommandBarVerifier.Base.cs
deleted file mode 100644
index 3373f8e..0000000
--- a/src/ModVerify/Verifiers/CommandBar/CommandBarVerifier.Base.cs
+++ /dev/null
@@ -1,161 +0,0 @@
-using System;
-using System.Linq;
-using System.Threading;
-using AET.ModVerify.Reporting;
-using AET.ModVerify.Settings;
-using AnakinRaW.CommonUtilities.Collections;
-using PG.StarWarsGame.Engine;
-using PG.StarWarsGame.Engine.CommandBar;
-using PG.StarWarsGame.Engine.CommandBar.Components;
-
-namespace AET.ModVerify.Verifiers;
-
-public partial class CommandBarVerifier(IStarWarsGameEngine gameEngine, GameVerifySettings settings, IServiceProvider serviceProvider)
- : GameVerifier(null, gameEngine, settings, serviceProvider)
-{
- public const string CommandBarNoShellsGroup = "CMDBAR00";
- public const string CommandBarManyShellsGroup = "CMDBAR01";
- public const string CommandBarNoShellsComponentInShellGroup = "CMDBAR02";
- public const string CommandBarDuplicateComponent = "CMDBAR03";
- public const string CommandBarUnsupportedComponent = "CMDBAR04";
- public const string CommandBarShellNoModel = "CMDBAR05";
-
- public override string FriendlyName => "CommandBar";
-
- public override void Verify(CancellationToken token)
- {
- VerifyCommandBarShellsGroups();
- VerifyCommandBarComponents();
- }
-
- private void VerifySingleComponent(CommandBarBaseComponent component)
- {
- VerifyCommandBarModel(component);
- VerifyComponentBone(component);
- }
-}
-
-partial class CommandBarVerifier
-{
- private void VerifyCommandBarModel(CommandBarBaseComponent component)
- {
- if (component is not CommandBarShellComponent shellComponent)
- return;
-
- if (shellComponent.ModelPath is null)
- {
- AddError(VerificationError.Create(VerifierChain,
- CommandBarShellNoModel, $"The CommandBarShellComponent '{component.Name}' has no model specified.",
- VerificationSeverity.Error, shellComponent.Name));
- return;
- }
-
- var model = GameEngine.PGRender.LoadModelAndAnimations(shellComponent.ModelPath.AsSpan(), null);
- if (model is null)
- {
- AddError(VerificationError.Create(VerifierChain,
- CommandBarShellNoModel, $"Could not find model '{shellComponent.ModelPath}' for CommandBarShellComponent '{component.Name}'.",
- VerificationSeverity.Error, [shellComponent.Name], shellComponent.ModelPath));
- return;
- }
- }
-
- private void VerifyComponentBone(CommandBarBaseComponent component)
- {
- if (component is CommandBarShellComponent)
- return;
-
- if (component.Bone == -1)
- {
- AddError(VerificationError.Create(VerifierChain,
- CommandBarShellNoModel, $"The CommandBar component '{component.Name}' is not connected to a shell component.",
- VerificationSeverity.Warning, component.Name));
- }
- }
-}
-
-partial class CommandBarVerifier
-{
- private void VerifyCommandBarComponents()
- {
- var occupiedComponentIds = SupportedCommandBarComponentData.GetComponentIdsForEngine(Repository.EngineType).Keys
- .ToDictionary(value => value, _ => false);
-
- foreach (var component in GameEngine.CommandBar.Components)
- {
- if (!occupiedComponentIds.TryGetValue(component.Id, out var alreadyOccupied))
- {
- AddError(VerificationError.Create(
- VerifierChain,
- CommandBarUnsupportedComponent,
- $"The CommandBar component '{component.Name}' is not supported by the game.",
- VerificationSeverity.Information,
- component.Name));
- }
- else
- {
- occupiedComponentIds[component.Id] = true;
- }
-
- if (alreadyOccupied)
- {
- AddError(VerificationError.Create(VerifierChain,
- CommandBarDuplicateComponent,
- $"The CommandBar component '{component.Name}' with ID '{component.Id}' already exists.",
- VerificationSeverity.Warning,
- component.Name));
- }
-
- VerifySingleComponent(component);
- }
- }
-}
-
-partial class CommandBarVerifier
-{
- private void VerifyCommandBarShellsGroups()
- {
- var shellGroups = new FrugalList();
- foreach (var groupPair in GameEngine.CommandBar.Groups)
- {
- if (groupPair.Key == CommandBarConstants.ShellGroupName)
- {
- shellGroups.Add(groupPair.Key);
- VerifyShellGroup(groupPair.Value);
- }
- else if (groupPair.Key.Equals(CommandBarConstants.ShellGroupName, StringComparison.OrdinalIgnoreCase))
- {
- shellGroups.Add(groupPair.Key);
- }
- }
-
- if (shellGroups.Count == 0)
- AddError(VerificationError.Create(VerifierChain,
- CommandBarNoShellsGroup,
- $"No CommandBarGroup '{CommandBarConstants.ShellGroupName}' found.",
- VerificationSeverity.Error,
- "GameCommandBar"));
-
- if (shellGroups.Count > 1)
- AddError(VerificationError.Create(VerifierChain,
- CommandBarManyShellsGroup,
- $"Found more than one Shells CommandBarGroup. Mind that group names are case-sensitive. Correct name is '{CommandBarConstants.ShellGroupName}'",
- VerificationSeverity.Warning,
- shellGroups, "GameCommandBar"));
- }
-
- private void VerifyShellGroup(CommandBarComponentGroup shellGroup)
- {
- foreach (var component in shellGroup.Components)
- {
- var shellComponent = component as CommandBarShellComponent;
- if (shellComponent?.Type is not CommandBarComponentType.Shell)
- {
- AddError(VerificationError.Create(VerifierChain,
- CommandBarNoShellsComponentInShellGroup,
- $"The CommandBar component '{component.Name}' is not a shell component, but part of the '{CommandBarConstants.ShellGroupName}' group.",
- VerificationSeverity.Warning, component.Name));
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/CommandBar/CommandBarVerifier.Components.cs b/src/ModVerify/Verifiers/CommandBar/CommandBarVerifier.Components.cs
new file mode 100644
index 0000000..3b43093
--- /dev/null
+++ b/src/ModVerify/Verifiers/CommandBar/CommandBarVerifier.Components.cs
@@ -0,0 +1,51 @@
+using AET.ModVerify.Reporting;
+using PG.StarWarsGame.Engine.CommandBar;
+using System.Linq;
+using System.Threading;
+
+namespace AET.ModVerify.Verifiers.CommandBar;
+
+partial class CommandBarVerifier
+{
+ private void VerifyCommandBarComponents(CancellationToken token, double startProgress)
+ {
+ var occupiedComponentIds = SupportedCommandBarComponentData
+ .GetComponentIdsForEngine(Repository.EngineType).Keys
+ .ToDictionary(value => value, _ => false);
+
+ var counter = 0;
+ var numEntities = GameEngine.CommandBar.Components.Count;
+ var num = 1 - startProgress;
+
+ foreach (var component in GameEngine.CommandBar.Components)
+ {
+ var progress = num + (++counter / (double)numEntities) * startProgress;
+ OnProgress(progress, $"CommandBarComponent - '{component.Name}'");
+
+ if (!occupiedComponentIds.TryGetValue(component.Id, out var alreadyOccupied))
+ {
+ AddError(VerificationError.Create(
+ this,
+ CommandBarUnsupportedComponent,
+ $"The CommandBar component '{component.Name}' is not supported by the game.",
+ VerificationSeverity.Information,
+ component.Name));
+ }
+ else
+ {
+ occupiedComponentIds[component.Id] = true;
+ }
+
+ if (alreadyOccupied)
+ {
+ AddError(VerificationError.Create(this,
+ VerifierErrorCodes.Duplicate,
+ $"The CommandBar component '{component.Name}' with ID '{component.Id}' already exists.",
+ VerificationSeverity.Warning,
+ component.Name));
+ }
+
+ VerifySingleComponent(component, token);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/CommandBar/CommandBarVerifier.Groups.cs b/src/ModVerify/Verifiers/CommandBar/CommandBarVerifier.Groups.cs
new file mode 100644
index 0000000..e3ed107
--- /dev/null
+++ b/src/ModVerify/Verifiers/CommandBar/CommandBarVerifier.Groups.cs
@@ -0,0 +1,56 @@
+using System;
+using AET.ModVerify.Reporting;
+using AnakinRaW.CommonUtilities.Collections;
+using PG.StarWarsGame.Engine.CommandBar;
+using PG.StarWarsGame.Engine.CommandBar.Components;
+
+namespace AET.ModVerify.Verifiers.CommandBar;
+
+partial class CommandBarVerifier
+{
+ private void VerifyCommandBarShellsGroups()
+ {
+ var shellGroups = new FrugalList();
+ foreach (var groupPair in GameEngine.CommandBar.Groups)
+ {
+ if (groupPair.Key == CommandBarConstants.ShellGroupName)
+ {
+ shellGroups.Add(groupPair.Key);
+ VerifyShellGroup(groupPair.Value);
+ }
+ else if (groupPair.Key.Equals(CommandBarConstants.ShellGroupName, StringComparison.OrdinalIgnoreCase))
+ {
+ shellGroups.Add(groupPair.Key);
+ }
+ }
+
+ if (shellGroups.Count == 0)
+ AddError(VerificationError.Create(this,
+ CommandBarNoShellsGroup,
+ $"No CommandBarGroup '{CommandBarConstants.ShellGroupName}' found.",
+ VerificationSeverity.Error,
+ "GameCommandBar"));
+
+ if (shellGroups.Count > 1)
+ AddError(VerificationError.Create(this,
+ CommandBarManyShellsGroup,
+ $"Found more than one Shells CommandBarGroup. Mind that group names are case-sensitive. Correct name is '{CommandBarConstants.ShellGroupName}'",
+ VerificationSeverity.Warning,
+ shellGroups, "GameCommandBar"));
+ }
+
+ private void VerifyShellGroup(CommandBarComponentGroup shellGroup)
+ {
+ foreach (var component in shellGroup.Components)
+ {
+ var shellComponent = component as CommandBarShellComponent;
+ if (shellComponent?.Type is not CommandBarComponentType.Shell)
+ {
+ AddError(VerificationError.Create(this,
+ CommandBarNoShellsComponentInShellGroup,
+ $"The CommandBar component '{component.Name}' is not a shell component, but part of the '{CommandBarConstants.ShellGroupName}' group.",
+ VerificationSeverity.Warning, component.Name));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/CommandBar/CommandBarVerifier.MegaTexture.cs b/src/ModVerify/Verifiers/CommandBar/CommandBarVerifier.MegaTexture.cs
new file mode 100644
index 0000000..8d86bad
--- /dev/null
+++ b/src/ModVerify/Verifiers/CommandBar/CommandBarVerifier.MegaTexture.cs
@@ -0,0 +1,41 @@
+using System.Threading;
+using AET.ModVerify.Reporting;
+using AET.ModVerify.Verifiers.Commons;
+using AET.ModVerify.Verifiers.Utilities;
+using PG.StarWarsGame.Engine.CommandBar;
+
+namespace AET.ModVerify.Verifiers.CommandBar;
+
+partial class CommandBarVerifier
+{
+ private void VerifyMegaTexture(CancellationToken token)
+ {
+ if (CommandBar.MtdFile is null)
+ {
+ AddError(VerificationError.Create(this, VerifierErrorCodes.FileNotFound,
+ $"Cannot find CommandBar MegaTextureDirectory '{CommandBarConstants.MegaTextureBaseName}.mtd'",
+ VerificationSeverity.Critical, $"{CommandBarConstants.MegaTextureBaseName}.mtd"));
+ }
+ else
+ {
+ var dupVerifier = new DuplicateVerifier(this);
+ dupVerifier.Verify(IDuplicateVerificationContext.CreateForMtd(CommandBar.MtdFile), [], token);
+
+ foreach (var duplicateError in dupVerifier.VerifyErrors)
+ AddError(duplicateError);
+ }
+
+ if (CommandBar.MegaTextureFileName is null)
+ {
+ AddError(VerificationError.Create(this, VerifierErrorCodes.FileNotFound,
+ $"Cannot find CommandBar MegaTexture '{CommandBarConstants.MegaTextureBaseName}.tga'",
+ VerificationSeverity.Critical, $"{CommandBarConstants.MegaTextureBaseName}.tga"));
+ }
+ else if (!GameEngine.GameRepository.TextureRepository.FileExists(CommandBar.MegaTextureFileName))
+ {
+ AddError(VerificationError.Create(this, VerifierErrorCodes.FileNotFound,
+ $"Cannot find CommandBar MegaTexture '{CommandBarConstants.MegaTextureBaseName}.tga'",
+ VerificationSeverity.Critical, $"{CommandBarConstants.MegaTextureBaseName}.tga"));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/CommandBar/CommandBarVerifier.SingleComponent.cs b/src/ModVerify/Verifiers/CommandBar/CommandBarVerifier.SingleComponent.cs
new file mode 100644
index 0000000..4a0d951
--- /dev/null
+++ b/src/ModVerify/Verifiers/CommandBar/CommandBarVerifier.SingleComponent.cs
@@ -0,0 +1,74 @@
+using AET.ModVerify.Reporting;
+using PG.StarWarsGame.Engine;
+using PG.StarWarsGame.Engine.CommandBar.Components;
+using System;
+using System.Threading;
+
+namespace AET.ModVerify.Verifiers.CommandBar;
+
+partial class CommandBarVerifier
+{
+ private void VerifySingleComponent(CommandBarBaseComponent component, CancellationToken token)
+ {
+ VerifyName(component);
+ VerifyCommandBarModel(component, token);
+ VerifyComponentBone(component);
+
+ // TODO: Textures
+ }
+
+ private void VerifyName(CommandBarBaseComponent component)
+ {
+ if (component.Name.Length > PGConstants.MaxCommandBarComponentNameBuffer)
+ {
+ AddError(VerificationError.Create(this, VerifierErrorCodes.NameTooLong,
+ // Deliberately not reporting the buffer length as max, as it's considered to be internal data
+ $"The CommandBarShellComponent name '{component.Name}' is too long. Maximum length is {PGConstants.MaxCommandBarComponentName}.",
+ VerificationSeverity.Critical, [], component.Name));
+ }
+ }
+
+ private void VerifyCommandBarModel(CommandBarBaseComponent component, CancellationToken token)
+ {
+ if (component is not CommandBarShellComponent shellComponent)
+ return;
+
+ if (shellComponent.ModelPath is null)
+ {
+ AddError(VerificationError.Create(this,
+ CommandBarShellNoModel, $"The CommandBarShellComponent '{component.Name}' has no model specified.",
+ VerificationSeverity.Error, [shellComponent.Name], shellComponent.Name));
+ return;
+ }
+
+ using var model = GameEngine.PGRender.LoadModelAndAnimations(shellComponent.ModelPath.AsSpan(), null);
+ if (model is null)
+ {
+ AddError(VerificationError.Create(this,
+ CommandBarShellNoModel, $"Could not find model '{shellComponent.ModelPath}' for CommandBarShellComponent '{component.Name}'.",
+ VerificationSeverity.Error, [shellComponent.Name], shellComponent.ModelPath));
+ return;
+ }
+
+ _modelVerifier.VerifyModelOrParticle(model.File, [shellComponent.Name], token);
+
+ if (model.Animations.Cout == 0)
+ return;
+
+ // TODO: Verify Animations
+
+ }
+
+ private void VerifyComponentBone(CommandBarBaseComponent component)
+ {
+ if (component is CommandBarShellComponent)
+ return;
+
+ if (component.Bone == -1)
+ {
+ AddError(VerificationError.Create(this,
+ CommandBarShellNoModel, $"The CommandBar component '{component.Name}' is not connected to a shell component.",
+ VerificationSeverity.Warning, component.Name));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/CommandBar/CommandBarVerifier.cs b/src/ModVerify/Verifiers/CommandBar/CommandBarVerifier.cs
new file mode 100644
index 0000000..4894673
--- /dev/null
+++ b/src/ModVerify/Verifiers/CommandBar/CommandBarVerifier.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Linq;
+using System.Threading;
+using AET.ModVerify.Settings;
+using AET.ModVerify.Verifiers.Commons;
+using PG.StarWarsGame.Engine;
+using PG.StarWarsGame.Engine.CommandBar;
+
+namespace AET.ModVerify.Verifiers.CommandBar;
+
+public partial class CommandBarVerifier : GameVerifier
+{
+ public const string CommandBarNoShellsGroup = "CMDBAR00";
+ public const string CommandBarManyShellsGroup = "CMDBAR01";
+ public const string CommandBarNoShellsComponentInShellGroup = "CMDBAR02";
+ public const string CommandBarUnsupportedComponent = "CMDBAR03";
+ public const string CommandBarShellNoModel = "CMDBAR04";
+
+ private readonly SingleModelVerifier _modelVerifier;
+ private readonly TextureVerifier _textureVerifier;
+
+ public override string FriendlyName => "CommandBar";
+
+ public ICommandBarGameManager CommandBar { get; }
+
+ public CommandBarVerifier(IStarWarsGameEngine gameEngine, GameVerifySettings settings, IServiceProvider serviceProvider)
+ : base(gameEngine, settings, serviceProvider)
+ {
+ CommandBar = gameEngine.CommandBar;
+ _modelVerifier = new SingleModelVerifier(this);
+ _textureVerifier = new TextureVerifier(this);
+ }
+
+ public override void Verify(CancellationToken token)
+ {
+ var progress = 0.0d;
+ OnProgress(progress, "Verifying MegaTexture");
+ VerifyMegaTexture(token);
+ progress = 1 / 3.0;
+ OnProgress(progress, "Verifying CommandBar Shell");
+ VerifyCommandBarShellsGroups();
+ progress = 2 / 3.0;
+ OnProgress(progress, "Verifying CommandBar components");
+ VerifyCommandBarComponents(token, progress);
+
+ foreach (var subError in _modelVerifier.VerifyErrors.Concat(_textureVerifier.VerifyErrors))
+ AddError(subError);
+
+ progress = 1.0;
+ OnProgress(progress, null);
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/Commons/Audio/AudioFileInfo.cs b/src/ModVerify/Verifiers/Commons/Audio/AudioFileInfo.cs
new file mode 100644
index 0000000..ee428cb
--- /dev/null
+++ b/src/ModVerify/Verifiers/Commons/Audio/AudioFileInfo.cs
@@ -0,0 +1,15 @@
+namespace AET.ModVerify.Verifiers.Commons;
+
+public class AudioFileInfo
+{
+ public string SampleName { get; }
+ public AudioFileType ExpectedType { get; }
+ public bool IsAmbient { get; }
+
+ public AudioFileInfo(string sampleName, AudioFileType expectedType, bool isAmbient)
+ {
+ SampleName = sampleName;
+ ExpectedType = expectedType;
+ IsAmbient = isAmbient;
+ }
+}
diff --git a/src/ModVerify/Verifiers/Commons/Audio/AudioFileType.cs b/src/ModVerify/Verifiers/Commons/Audio/AudioFileType.cs
new file mode 100644
index 0000000..05ea0bc
--- /dev/null
+++ b/src/ModVerify/Verifiers/Commons/Audio/AudioFileType.cs
@@ -0,0 +1,7 @@
+namespace AET.ModVerify.Verifiers.Commons;
+
+public enum AudioFileType
+{
+ Wav,
+ Mp3
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/Commons/AudioFileVerifier.cs b/src/ModVerify/Verifiers/Commons/AudioFileVerifier.cs
new file mode 100644
index 0000000..4537a64
--- /dev/null
+++ b/src/ModVerify/Verifiers/Commons/AudioFileVerifier.cs
@@ -0,0 +1,141 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using AET.ModVerify.Reporting;
+using AET.ModVerify.Settings;
+using PG.StarWarsGame.Engine;
+using System.Threading;
+using Microsoft.Extensions.DependencyInjection;
+using AET.ModVerify.Verifiers.Caching;
+
+namespace AET.ModVerify.Verifiers.Commons;
+
+public class AudioFileVerifier : GameVerifier
+{
+ private readonly IAlreadyVerifiedCache? _alreadyVerifiedCache;
+
+ public AudioFileVerifier(GameVerifierBase parent) : base(parent)
+ {
+ _alreadyVerifiedCache = Services.GetService();
+ }
+
+ public AudioFileVerifier(IGameVerifierInfo? parent,
+ IStarWarsGameEngine gameEngine,
+ GameVerifySettings settings,
+ IServiceProvider serviceProvider) : base(parent, gameEngine, settings, serviceProvider)
+ {
+ _alreadyVerifiedCache = serviceProvider.GetService();
+ }
+
+ public override string FriendlyName => "Audio File format";
+
+ public override void Verify(AudioFileInfo sampleInfo, IReadOnlyCollection contextInfo, CancellationToken token)
+ {
+ var cached = _alreadyVerifiedCache?.GetEntry(sampleInfo.SampleName);
+
+ if (cached?.AlreadyVerified is true)
+ {
+ if (!cached.Value.AssetExists)
+ {
+ AddError(VerificationError.Create(
+ this,
+ VerifierErrorCodes.FileNotFound,
+ $"Audio file '{sampleInfo.SampleName}' could not be found.",
+ VerificationSeverity.Error,
+ [.. contextInfo],
+ sampleInfo.SampleName));
+ }
+ return;
+ }
+
+
+ var sampleString = sampleInfo.SampleName;
+
+ using var sampleStream = Repository.TryOpenFile(sampleString.AsSpan());
+
+ _alreadyVerifiedCache?.TryAddEntry(sampleInfo.SampleName, sampleStream is not null);
+
+ if (sampleStream is null)
+ {
+ AddError(VerificationError.Create(
+ this,
+ VerifierErrorCodes.FileNotFound,
+ $"Audio file '{sampleString}' could not be found.",
+ VerificationSeverity.Error,
+ [..contextInfo],
+ sampleString));
+ return;
+ }
+
+ if (sampleInfo.ExpectedType == AudioFileType.Mp3)
+ {
+ // TODO: MP3 support to be implemented
+ return;
+ }
+
+ using var binaryReader = new BinaryReader(sampleStream);
+
+ // Skip Header + "fmt "
+ binaryReader.BaseStream.Seek(16, SeekOrigin.Begin);
+
+ var fmtSize = binaryReader.ReadInt32();
+ var format = (WaveFormats)binaryReader.ReadInt16();
+ var channels = binaryReader.ReadInt16();
+
+ var sampleRate = binaryReader.ReadInt32();
+ var bytesPerSecond = binaryReader.ReadInt32();
+
+ var frameSize = binaryReader.ReadInt16();
+ var bitPerSecondPerChannel = binaryReader.ReadInt16();
+
+ if (format != WaveFormats.PCM)
+ {
+ AddError(VerificationError.Create(
+ this,
+ VerifierErrorCodes.SampleNotPCM,
+ $"Audio file '{sampleString}' has an invalid format '{format}'. Supported is {WaveFormats.PCM}",
+ VerificationSeverity.Error,
+ [..contextInfo],
+ sampleString));
+ }
+
+ if (channels > 1 && !sampleInfo.IsAmbient)
+ {
+ AddError(VerificationError.Create(
+ this,
+ VerifierErrorCodes.SampleNotMono,
+ $"Audio file '{sampleString}' is not mono audio.",
+ VerificationSeverity.Information,
+ sampleString));
+ }
+
+ if (sampleRate > 48_000)
+ {
+ AddError(VerificationError.Create(
+ this,
+ VerifierErrorCodes.InvalidSampleRate,
+ $"Audio file '{sampleString}' has a too high sample rate of {sampleRate}. Maximum is 48.000Hz.",
+ VerificationSeverity.Error,
+ [..contextInfo],
+ sampleString));
+ }
+
+ if (bitPerSecondPerChannel > 16)
+ {
+ AddError(VerificationError.Create(
+ this,
+ VerifierErrorCodes.InvalidBitsPerSeconds,
+ $"Audio file '{sampleString}' has an invalid bit size of {bitPerSecondPerChannel}. Supported are 16bit.",
+ VerificationSeverity.Error,
+ [..contextInfo],
+ sampleString));
+ }
+ }
+
+ private enum WaveFormats
+ {
+ PCM = 1,
+ MSADPCM = 2,
+ IEEE_Float = 3,
+ }
+}
diff --git a/src/ModVerify/Verifiers/Commons/DuplicateVerifier.cs b/src/ModVerify/Verifiers/Commons/DuplicateVerifier.cs
new file mode 100644
index 0000000..7aa19e6
--- /dev/null
+++ b/src/ModVerify/Verifiers/Commons/DuplicateVerifier.cs
@@ -0,0 +1,43 @@
+using AET.ModVerify.Reporting;
+using AET.ModVerify.Settings;
+using PG.StarWarsGame.Engine;
+using System;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace AET.ModVerify.Verifiers.Commons;
+
+public sealed class DuplicateVerifier : GameVerifier
+{
+ public override string FriendlyName => "Duplicate Verifier";
+
+ public DuplicateVerifier(GameVerifierBase parent) : base(parent)
+ {
+ }
+
+ public DuplicateVerifier(
+ IGameVerifierInfo? parent,
+ IStarWarsGameEngine gameEngine,
+ GameVerifySettings settings,
+ IServiceProvider serviceProvider)
+ : base(parent, gameEngine, settings, serviceProvider)
+ {
+ }
+
+ public override void Verify(IDuplicateVerificationContext toVerify, IReadOnlyCollection contextInfo, CancellationToken token)
+ {
+ foreach (var crc32 in toVerify.GetCrcs())
+ {
+ if (toVerify.HasDuplicates(crc32, out var entryNames, out var context, out var errorMessage))
+ {
+ AddError(VerificationError.Create(
+ this,
+ VerifierErrorCodes.Duplicate,
+ errorMessage,
+ VerificationSeverity.Error,
+ context,
+ entryNames));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/Commons/Duplicates/IDuplicateVerificationContext.cs b/src/ModVerify/Verifiers/Commons/Duplicates/IDuplicateVerificationContext.cs
new file mode 100644
index 0000000..4301e54
--- /dev/null
+++ b/src/ModVerify/Verifiers/Commons/Duplicates/IDuplicateVerificationContext.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+using PG.Commons.Hashing;
+
+namespace AET.ModVerify.Verifiers.Commons;
+
+public interface IDuplicateVerificationContext
+{
+ string SourceName { get; }
+ IEnumerable GetCrcs();
+ bool HasDuplicates(Crc32 crc, out string entryNames, out IEnumerable duplicateContext, out string errorMessage);
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/Commons/Duplicates/MtdDuplicateVerificationContext.cs b/src/ModVerify/Verifiers/Commons/Duplicates/MtdDuplicateVerificationContext.cs
new file mode 100644
index 0000000..624a0a6
--- /dev/null
+++ b/src/ModVerify/Verifiers/Commons/Duplicates/MtdDuplicateVerificationContext.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+using System.Linq;
+using PG.Commons.Hashing;
+using PG.StarWarsGame.Files.MTD.Files;
+
+namespace AET.ModVerify.Verifiers.Commons;
+
+internal sealed class MtdDuplicateVerificationContext(IMtdFile mtdFile) : IDuplicateVerificationContext
+{
+ public string SourceName => mtdFile.FileName;
+
+ public IEnumerable GetCrcs() => mtdFile.Content.Select(x => x.Crc32);
+
+ public bool HasDuplicates(Crc32 crc, out string entryNames, out IEnumerable duplicateContext, out string errorMessage)
+ {
+ var entries = mtdFile.Content.EntriesWithCrc(crc);
+ if (entries.Count > 1)
+ {
+ var firstEntry = entries.First();
+ entryNames = firstEntry.FileName;
+ duplicateContext = entries.Select(x => $"'{x.FileName}' (CRC: {x.Crc32})");
+ errorMessage = $"MTD File '{SourceName}' has duplicate definitions for CRC ({firstEntry}): " +
+ $"{string.Join(",", entries.Select(x => x.FileName))}";
+ return true;
+ }
+
+ entryNames = string.Empty;
+ duplicateContext = [];
+ errorMessage = string.Empty;
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/Commons/Duplicates/NamedXmlObjectDuplicateVerificationContext.cs b/src/ModVerify/Verifiers/Commons/Duplicates/NamedXmlObjectDuplicateVerificationContext.cs
new file mode 100644
index 0000000..d50057d
--- /dev/null
+++ b/src/ModVerify/Verifiers/Commons/Duplicates/NamedXmlObjectDuplicateVerificationContext.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using PG.Commons.Hashing;
+using PG.StarWarsGame.Engine;
+using PG.StarWarsGame.Files.XML.Data;
+
+namespace AET.ModVerify.Verifiers.Commons;
+
+internal sealed class NamedXmlObjectDuplicateVerificationContext(string databaseName, IGameManager gameManager)
+ : IDuplicateVerificationContext
+ where T : NamedXmlObject
+{
+ public string SourceName => databaseName;
+
+ public IEnumerable GetCrcs() => gameManager.EntryKeys;
+
+ public bool HasDuplicates(Crc32 crc, out string entryNames, out IEnumerable duplicateContext, out string errorMessage)
+ {
+ var entries = gameManager.GetEntries(crc);
+ if (entries.Count > 1)
+ {
+ var firstEntry = entries.First();
+ entryNames = firstEntry.Name;
+ duplicateContext = entries.Select(x => $"'{x.Name}' - {x.Location}");
+ var message = $"{SourceName} '{firstEntry.Name}' ({firstEntry.Crc32}) has duplicate definitions: ";
+ message = entries.Aggregate(message, (current, entry) => current + $"['{entry.Name}' in {entry.Location.XmlFile}:{entry.Location.Line}] ");
+ errorMessage = message.TrimEnd();
+ return true;
+ }
+
+ entryNames = string.Empty;
+ duplicateContext = Array.Empty();
+ errorMessage = string.Empty;
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/Commons/ModelVerifier.cs b/src/ModVerify/Verifiers/Commons/SingleModelVerifier.cs
similarity index 80%
rename from src/ModVerify/Verifiers/Commons/ModelVerifier.cs
rename to src/ModVerify/Verifiers/Commons/SingleModelVerifier.cs
index 25704d1..fa621e1 100644
--- a/src/ModVerify/Verifiers/Commons/ModelVerifier.cs
+++ b/src/ModVerify/Verifiers/Commons/SingleModelVerifier.cs
@@ -4,6 +4,7 @@
using AET.ModVerify.Reporting;
using AET.ModVerify.Settings;
using AET.ModVerify.Utilities;
+using AET.ModVerify.Verifiers.Caching;
using Microsoft.Extensions.DependencyInjection;
using PG.StarWarsGame.Engine;
using PG.StarWarsGame.Files;
@@ -22,47 +23,93 @@ public sealed class SingleModelVerifier : GameVerifier
{
private const string ProxyAltIdentifier = "_ALT";
- private readonly TextureVeifier _textureVerifier;
+ private readonly TextureVerifier _textureVerifier;
private readonly IAlreadyVerifiedCache? _cache;
- public SingleModelVerifier(IGameVerifierInfo? parent,
+ public SingleModelVerifier(GameVerifierBase parent) : base(parent)
+ {
+ _textureVerifier = new TextureVerifier(this);
+ _cache = Services.GetService();
+ }
+
+ public SingleModelVerifier(
+ IGameVerifierInfo? parent,
IStarWarsGameEngine engine,
GameVerifySettings settings,
IServiceProvider serviceProvider) : base(parent, engine, settings, serviceProvider)
{
- _textureVerifier = new TextureVeifier(this, engine, settings, serviceProvider);
+ _textureVerifier = new TextureVerifier(this);
_cache = serviceProvider.GetService();
}
public override void Verify(string modelName, IReadOnlyCollection contextInfo, CancellationToken token)
{
- try
+ var cacheEntry = _cache?.GetEntry(modelName);
+ if (cacheEntry?.AlreadyVerified is true)
{
- _textureVerifier.Error += OnTextureError;
-
- var modelPath = BuildModelPath(modelName);
- VerifyAlamoFile(modelPath, contextInfo, token);
+ if (!cacheEntry.Value.AssetExists)
+ {
+ var error = VerificationError.Create(
+ this,
+ VerifierErrorCodes.FileNotFound,
+ $"Unable to find .ALO file '{modelName}'",
+ VerificationSeverity.Error,
+ contextInfo,
+ modelName);
+ AddError(error);
+ }
+ return;
}
- finally
+
+ var modelPath = BuildModelPath(modelName);
+ VerifyAlamoFile(modelPath, contextInfo, token, out var modelExists);
+
+ if (!modelExists)
{
- _textureVerifier.Error -= OnTextureError;
+ var error = VerificationError.Create(
+ this,
+ VerifierErrorCodes.FileNotFound,
+ $"Unable to find .ALO file '{modelName}'",
+ VerificationSeverity.Error,
+ contextInfo,
+ modelName);
+ AddError(error);
}
+
+ _cache?.TryAddEntry(modelName, modelExists);
+
+ foreach (var textureError in _textureVerifier.VerifyErrors)
+ AddError(textureError);
}
- private void OnTextureError(object sender, VerificationErrorEventArgs e)
+ public void VerifyModelOrParticle(
+ IAloFile aloFile,
+ IReadOnlyCollection contextInfo,
+ CancellationToken token)
{
- AddError(e.Error);
+ switch (aloFile)
+ {
+ case IAloModelFile model:
+ VerifyModel(model, contextInfo, token);
+ break;
+ case IAloParticleFile particle:
+ VerifyParticle(particle, contextInfo);
+ break;
+ default:
+ throw new InvalidOperationException("The data stream is neither a model nor particle.");
+ }
}
- private void VerifyAlamoFile(string modelPath, IReadOnlyCollection contextInfo, CancellationToken token)
+ private void VerifyAlamoFile(
+ string modelPath,
+ IReadOnlyCollection contextInfo,
+ CancellationToken token,
+ out bool modelExists)
{
token.ThrowIfCancellationRequested();
- var modelName = FileSystem.Path.GetFileName(modelPath.AsSpan());
+ modelExists = true;
- if (_cache?.TryAddEntry(modelName) == false)
- return;
-
IAloFile? aloFile = null;
try
{
@@ -74,22 +121,16 @@ private void VerifyAlamoFile(string modelPath, IReadOnlyCollection conte
{
var aloFilePath = FileSystem.Path.GetGameStrippedPath(Repository.Path.AsSpan(), modelPath.AsSpan()).ToString();
var message = $"'{aloFilePath}' is corrupted: {e.Message}";
- AddError(VerificationError.Create(VerifierChain, VerifierErrorCodes.FileCorrupt, message,
+ AddError(VerificationError.Create(this, VerifierErrorCodes.BinaryFileCorrupt, message,
VerificationSeverity.Critical, contextInfo, aloFilePath));
return;
}
+ // Because throwsException is true, we know that if aloFile is null,
+ // the file does not exist
if (aloFile is null)
{
- var modelNameString = modelName.ToString();
- var error = VerificationError.Create(
- VerifierChain,
- VerifierErrorCodes.FileNotFound,
- $"Unable to find .ALO file '{modelNameString}'",
- VerificationSeverity.Error,
- contextInfo,
- modelNameString);
- AddError(error);
+ modelExists = false;
return;
}
@@ -101,24 +142,6 @@ private void VerifyAlamoFile(string modelPath, IReadOnlyCollection conte
}
}
- private void VerifyModelOrParticle(
- IAloFile aloFile,
- IReadOnlyCollection contextInfo,
- CancellationToken token)
- {
- switch (aloFile)
- {
- case IAloModelFile model:
- VerifyModel(model, contextInfo, token);
- break;
- case IAloParticleFile particle:
- VerifyParticle(particle, contextInfo);
- break;
- default:
- throw new InvalidOperationException("The data stream is neither a model nor particle.");
- }
- }
-
private void VerifyParticle(IAloParticleFile file, IReadOnlyCollection contextInfo)
{
foreach (var texture in file.Content.Textures)
@@ -129,7 +152,7 @@ private void VerifyParticle(IAloParticleFile file, IReadOnlyCollection c
{
var particlePath = FileSystem.Path.GetGameStrippedPath(Repository.Path.AsSpan(), file.FilePath.AsSpan()).ToString();
AddError(VerificationError.Create(
- VerifierChain,
+ this,
VerifierErrorCodes.InvalidFilePath,
$"Invalid texture file name '{texture}' in particle '{particlePath}'",
VerificationSeverity.Error,
@@ -144,7 +167,7 @@ private void VerifyParticle(IAloParticleFile file, IReadOnlyCollection c
{
var particlePath = FileSystem.Path.GetGameStrippedPath(Repository.Path.AsSpan(), file.FilePath.AsSpan()).ToString();
AddError(VerificationError.Create(
- VerifierChain,
+ this,
VerifierErrorCodes.InvalidParticleName,
$"The particle name '{file.Content.Name}' does not match file name '{particlePath}'",
VerificationSeverity.Error,
@@ -163,7 +186,7 @@ private void VerifyModel(IAloModelFile file, IReadOnlyCollection context
{
var modelFilePath = FileSystem.Path.GetGameStrippedPath(Repository.Path.AsSpan(), file.FilePath.AsSpan()).ToString();
AddError(VerificationError.Create(
- VerifierChain,
+ this,
VerifierErrorCodes.InvalidFilePath,
$"Invalid texture file name '{texture}' in model '{modelFilePath}'",
VerificationSeverity.Error,
@@ -181,7 +204,7 @@ private void VerifyModel(IAloModelFile file, IReadOnlyCollection context
var modelFilePath =
FileSystem.Path.GetGameStrippedPath(Repository.Path.AsSpan(), file.FilePath.AsSpan()).ToString();
AddError(VerificationError.Create(
- VerifierChain,
+ this,
VerifierErrorCodes.InvalidFilePath,
$"Invalid shader file name '{shader}' in model '{modelFilePath}'",
VerificationSeverity.Error,
@@ -200,7 +223,7 @@ private void VerifyModel(IAloModelFile file, IReadOnlyCollection context
var modelFilePath = FileSystem.Path
.GetGameStrippedPath(Repository.Path.AsSpan(), file.FilePath.AsSpan()).ToString();
AddError(VerificationError.Create(
- VerifierChain,
+ this,
VerifierErrorCodes.InvalidFilePath,
$"Invalid proxy file name '{proxy}' for model '{modelFilePath}'",
VerificationSeverity.Error,
@@ -223,22 +246,21 @@ private void VerifyProxyExists(IPetroglyphFileHolder model, string proxy, IReadO
var proxyPath = BuildModelPath(proxyName);
var modelFilePath = FileSystem.Path.GetGameStrippedPath(Repository.Path.AsSpan(), model.FilePath.AsSpan()).ToString();
+
+ VerifyAlamoFile(proxyPath, [..contextInfo, modelFilePath], token, out var proxyExists);
- if (!Repository.ModelRepository.FileExists(proxyPath))
+ if (!proxyExists)
{
var message = $"Proxy particle '{proxyName}' not found for model '{modelFilePath}'";
var error = VerificationError.Create(
- VerifierChain,
+ this,
VerifierErrorCodes.FileNotFound,
- message,
- VerificationSeverity.Error,
- [..contextInfo, modelFilePath],
+ message,
+ VerificationSeverity.Error,
+ [.. contextInfo, modelFilePath],
proxyName);
AddError(error);
- return;
}
-
- VerifyAlamoFile(proxyPath, [..contextInfo, modelFilePath], token);
}
private void VerifyShaderExists(IPetroglyphFileHolder model, string shader, IReadOnlyCollection contextInfo)
@@ -251,7 +273,7 @@ private void VerifyShaderExists(IPetroglyphFileHolder model, string shader, IRea
var modelFilePath = FileSystem.Path.GetGameStrippedPath(Repository.Path.AsSpan(), model.FilePath.AsSpan()).ToString();
var message = $"Shader effect '{shader}' not found for model '{modelFilePath}'.";
var error = VerificationError.Create(
- VerifierChain,
+ this,
VerifierErrorCodes.FileNotFound,
message,
VerificationSeverity.Error,
diff --git a/src/ModVerify/Verifiers/Commons/TextureVeifier.cs b/src/ModVerify/Verifiers/Commons/TextureVerifier.cs
similarity index 68%
rename from src/ModVerify/Verifiers/Commons/TextureVeifier.cs
rename to src/ModVerify/Verifiers/Commons/TextureVerifier.cs
index 1bd3a08..e7709e3 100644
--- a/src/ModVerify/Verifiers/Commons/TextureVeifier.cs
+++ b/src/ModVerify/Verifiers/Commons/TextureVerifier.cs
@@ -4,19 +4,24 @@
using System.Threading;
using AET.ModVerify.Reporting;
using AET.ModVerify.Settings;
-using Microsoft.Extensions.DependencyInjection;
using PG.StarWarsGame.Engine;
namespace AET.ModVerify.Verifiers.Commons;
-public sealed class TextureVeifier(
- IGameVerifierInfo? parent,
- IStarWarsGameEngine gameEngine,
- GameVerifySettings settings,
- IServiceProvider serviceProvider)
- : GameVerifier(parent, gameEngine, settings, serviceProvider)
+public sealed class TextureVerifier : GameVerifier
{
- private readonly IAlreadyVerifiedCache? _cache = serviceProvider.GetService();
+ public TextureVerifier(GameVerifierBase parent) : base(parent)
+ {
+ }
+
+ public TextureVerifier(
+ IGameVerifierInfo? parent,
+ IStarWarsGameEngine gameEngine,
+ GameVerifySettings settings,
+ IServiceProvider serviceProvider) :
+ base(parent, gameEngine, settings, serviceProvider)
+ {
+ }
public override void Verify(string texturePath, IReadOnlyCollection contextInfo, CancellationToken token)
{
@@ -27,10 +32,6 @@ public void Verify(ReadOnlySpan textureName, IReadOnlyCollection c
{
token.ThrowIfCancellationRequested();
-
- if (_cache?.TryAddEntry(textureName) == false)
- return;
-
if (Repository.TextureRepository.FileExists(textureName, false, out var tooLongPath))
return;
@@ -38,7 +39,7 @@ public void Verify(ReadOnlySpan textureName, IReadOnlyCollection c
if (tooLongPath)
{
- AddError(VerificationError.Create(VerifierChain, VerifierErrorCodes.FilePathTooLong,
+ AddError(VerificationError.Create(this, VerifierErrorCodes.FilePathTooLong,
$"Could not find texture '{pathString}' because the engine resolved a path that is too long.",
VerificationSeverity.Error, contextInfo, pathString));
return;
@@ -55,7 +56,7 @@ public void Verify(ReadOnlySpan textureName, IReadOnlyCollection c
messageBuilder.Append('.');
- AddError(VerificationError.Create(VerifierChain, VerifierErrorCodes.FileNotFound,
+ AddError(VerificationError.Create(this, VerifierErrorCodes.FileNotFound,
messageBuilder.ToString(),
VerificationSeverity.Error, contextInfo, pathString));
}
diff --git a/src/ModVerify/Verifiers/DuplicateNameFinder.cs b/src/ModVerify/Verifiers/DuplicateNameFinder.cs
deleted file mode 100644
index 0b3b585..0000000
--- a/src/ModVerify/Verifiers/DuplicateNameFinder.cs
+++ /dev/null
@@ -1,104 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using AET.ModVerify.Reporting;
-using AET.ModVerify.Settings;
-using AnakinRaW.CommonUtilities.Collections;
-using PG.Commons.Hashing;
-using PG.StarWarsGame.Engine;
-using PG.StarWarsGame.Engine.Xml;
-using PG.StarWarsGame.Files.MTD.Data;
-using PG.StarWarsGame.Files.MTD.Files;
-
-namespace AET.ModVerify.Verifiers;
-
-public sealed class DuplicateNameFinder(
- IStarWarsGameEngine gameEngine,
- GameVerifySettings settings,
- IServiceProvider serviceProvider)
- : GameVerifier(null, gameEngine, settings, serviceProvider)
-{
- public override string FriendlyName => "Duplicates";
-
- public override void Verify(CancellationToken token)
- {
- CheckXmlObjectsForDuplicates("GameObject", GameEngine.GameObjectTypeManager);
- CheckXmlObjectsForDuplicates("SFXEvent", GameEngine.SfxGameManager);
-
- if (GameEngine.GuiDialogManager.MtdFile is not null)
- CheckMtdForDuplicates(GameEngine.GuiDialogManager.MtdFile);
-
- if (GameEngine.CommandBar.MegaTextureFile is not null)
- {
- if (!GameEngine.CommandBar.MegaTextureFile.FilePath.Equals(GameEngine.GuiDialogManager.MtdFile?.FileName))
- CheckMtdForDuplicates(GameEngine.CommandBar.MegaTextureFile);
- }
- }
-
- private void CheckForDuplicateCrcEntries(
- string sourceName,
- TSource source,
- Func> crcSelector,
- Func> entrySelector,
- Func entryToStringSelector,
- Func, IEnumerable> contextSelector,
- Func, string, string> errorMessageCreator)
- {
- foreach (var crc32 in crcSelector(source))
- {
- var entries = entrySelector(source, crc32);
- if (entries.Count > 1)
- {
- var entryNames = entryToStringSelector(entries.First());
- var context = contextSelector(entries);
- AddError(VerificationError.Create(
- VerifierChain,
- VerifierErrorCodes.DuplicateFound,
- errorMessageCreator(entries, sourceName),
- VerificationSeverity.Error,
- context,
- entryNames));
- }
- }
- }
-
- private void CheckMtdForDuplicates(IMtdFile mtdFile)
- {
- CheckForDuplicateCrcEntries(
- mtdFile.FileName,
- mtdFile,
- mtd => mtd.Content.Select(x => x.Crc32),
- (mtd, crc32) => mtd.Content.EntriesWithCrc(crc32),
- entry => entry.FileName,
- entries => entries.Select(x => $"'{x.FileName}' (CRC: {x.Crc32})"),
- CreateDuplicateMtdErrorMessage);
- }
-
- private void CheckXmlObjectsForDuplicates(string databaseName, IGameManager gameManager) where T : NamedXmlObject
- {
- CheckForDuplicateCrcEntries(
- databaseName,
- gameManager,
- manager => manager.EntryKeys,
- (manager, crc32) => manager.GetEntries(crc32),
- entry => entry.Name,
- entries => entries.Select(x => $"'{x.Name}' - {x.Location}"),
- CreateDuplicateXmlErrorMessage);
- }
-
- private static string CreateDuplicateMtdErrorMessage(ImmutableFrugalList entries, string fileName)
- {
- var firstEntry = entries.First();
- return $"MTD File '{fileName}' has duplicate definitions for CRC ({firstEntry}): {string.Join(",", entries.Select(x => x.FileName))}";
- }
-
- private static string CreateDuplicateXmlErrorMessage(ImmutableFrugalList entries, string databaseName) where T : NamedXmlObject
- {
- var firstEntry = entries.First();
- var message = $"{databaseName} '{firstEntry.Name}' ({firstEntry.Crc32}) has duplicate definitions: ";
- foreach (var entry in entries)
- message += $"['{entry.Name}' in {entry.Location.XmlFile}:{entry.Location.Line}] ";
- return message.TrimEnd();
- }
-}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/GameEngineErrorCollector.cs b/src/ModVerify/Verifiers/Engine/GameEngineErrorCollector.cs
similarity index 91%
rename from src/ModVerify/Verifiers/GameEngineErrorCollector.cs
rename to src/ModVerify/Verifiers/Engine/GameEngineErrorCollector.cs
index 975e360..70c1cb3 100644
--- a/src/ModVerify/Verifiers/GameEngineErrorCollector.cs
+++ b/src/ModVerify/Verifiers/Engine/GameEngineErrorCollector.cs
@@ -6,14 +6,14 @@
using AET.ModVerify.Settings;
using PG.StarWarsGame.Engine;
-namespace AET.ModVerify.Verifiers;
+namespace AET.ModVerify.Verifiers.Engine;
public sealed class GameEngineErrorCollector(
IGameEngineErrorCollection errorCollection,
IStarWarsGameEngine gameEngine,
GameVerifySettings settings,
IServiceProvider serviceProvider)
- : GameVerifier(null, gameEngine, settings, serviceProvider)
+ : GameVerifier(gameEngine, settings, serviceProvider)
{
public override string FriendlyName => "Game Engine Initialization";
diff --git a/src/ModVerify/Verifiers/Engine/HardcodedAssetsVerifier.cs b/src/ModVerify/Verifiers/Engine/HardcodedAssetsVerifier.cs
new file mode 100644
index 0000000..69a6800
--- /dev/null
+++ b/src/ModVerify/Verifiers/Engine/HardcodedAssetsVerifier.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Threading;
+using AET.ModVerify.Settings;
+using AET.ModVerify.Verifiers.Commons;
+using PG.StarWarsGame.Engine;
+
+namespace AET.ModVerify.Verifiers.Engine;
+
+public sealed class HardcodedAssetsVerifier : GameVerifier
+{
+ private readonly SingleModelVerifier _modelVerifier;
+
+ public HardcodedAssetsVerifier(IStarWarsGameEngine gameEngine, GameVerifySettings settings, IServiceProvider serviceProvider)
+ : base(gameEngine, settings, serviceProvider)
+ {
+ _modelVerifier = new SingleModelVerifier(this);
+ }
+
+ public override void Verify(CancellationToken token)
+ {
+ OnProgress(0.0d, "Verifying Hardcoded Models");
+ VerifyModels(token);
+ OnProgress(1.0, null);
+ }
+
+ private void VerifyModels(CancellationToken token)
+ {
+ var models = HardcodedEngineAssets.GetHardcodedModels(GameEngine.EngineType);
+
+ foreach (var model in models)
+ _modelVerifier.Verify(model, [], token);
+
+ foreach (var error in _modelVerifier.VerifyErrors)
+ AddError(error);
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/GameObjects/GameObjectTypeVerifier.Icons.cs b/src/ModVerify/Verifiers/GameObjects/GameObjectTypeVerifier.Icons.cs
new file mode 100644
index 0000000..36541bb
--- /dev/null
+++ b/src/ModVerify/Verifiers/GameObjects/GameObjectTypeVerifier.Icons.cs
@@ -0,0 +1,41 @@
+using AET.ModVerify.Reporting;
+using PG.StarWarsGame.Engine.GameObjects;
+
+namespace AET.ModVerify.Verifiers.GameObjects;
+
+public sealed partial class GameObjectTypeVerifier
+{
+ private void VerifyIcons(GameObject gameObject, string[] context)
+ {
+ VerifyObjectIcon(gameObject, context);
+ }
+
+ private void VerifyObjectIcon(GameObject gameObject, string[] context)
+ {
+ if (string.IsNullOrEmpty(gameObject.IconName))
+ return;
+
+ /*
+ * The engine loads game object icons with different strategies, depending on where the icon is displayed:
+ * 1. the game loads the texture from MTD and supports the faction prefixes e.g, r_ or e_
+ * Faction prefixes have higher priority than the non-prefix versions. The player's faction (not the object owner) is used.
+ * This applies to all command bar components (such as build buttons)
+ * 2. the game loads the texture form MTD and does NOT support faction prefix.
+ * If the texture is not found, the game searches the texture with forced .dds name in the Textures folder.
+ * This applies to the GUI dialogs (such as battle summary)
+ * 3. the game only loads the texture from MTD NOT supporting faction prefix nor textures folder fallback.
+ * This applies (only) to the neutralize hero dialog
+ *
+ * We only verify whether the icon exists in the MTD data, as this is the primary case to all strategies
+ * (and it's what really should only be used for mods)
+ * Faction-specific icons are not verified as they are statically not decidable.
+ */
+
+ if (!GameEngine.CommandBar.IconExists(gameObject))
+ {
+ AddError(VerificationError.Create(this, VerifierErrorCodes.FileNotFound,
+ $"Could not find icon '{gameObject.IconName}' for game object type '{gameObject.Name}'.",
+ VerificationSeverity.Warning, context, gameObject.IconName!));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/GameObjects/GameObjectTypeVerifier.Models.cs b/src/ModVerify/Verifiers/GameObjects/GameObjectTypeVerifier.Models.cs
new file mode 100644
index 0000000..39699a7
--- /dev/null
+++ b/src/ModVerify/Verifiers/GameObjects/GameObjectTypeVerifier.Models.cs
@@ -0,0 +1,13 @@
+using PG.StarWarsGame.Engine.GameObjects;
+using System.Threading;
+
+namespace AET.ModVerify.Verifiers.GameObjects;
+
+public sealed partial class GameObjectTypeVerifier
+{
+ private void VerifyModels(GameObject gameObject, string[] context, CancellationToken token)
+ {
+ foreach (var model in GameEngine.GameObjectTypeManager.GetModels(gameObject))
+ _singleModelVerifier.Verify(model, context, token);
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/GameObjects/GameObjectTypeVerifier.XRef.cs b/src/ModVerify/Verifiers/GameObjects/GameObjectTypeVerifier.XRef.cs
new file mode 100644
index 0000000..1bca0e9
--- /dev/null
+++ b/src/ModVerify/Verifiers/GameObjects/GameObjectTypeVerifier.XRef.cs
@@ -0,0 +1,44 @@
+using System.Linq;
+using AET.ModVerify.Reporting;
+using PG.StarWarsGame.Engine.GameObjects;
+
+namespace AET.ModVerify.Verifiers.GameObjects;
+
+public sealed partial class GameObjectTypeVerifier
+{
+ private void VerifyXRefs(GameObject gameObject, string[] context)
+ {
+ if (!string.IsNullOrEmpty(gameObject.VariantOfExistingTypeName) && gameObject.VariantOfExistingType is null)
+ {
+ AddError(VerificationError.Create(
+ this,
+ VerifierErrorCodes.MissingXRef,
+ $"Missing base type '{gameObject.VariantOfExistingTypeName}' for GameObject '{gameObject.Name}'",
+ VerificationSeverity.Critical,
+ [..context, "VariantOfExistingType"],
+ gameObject.VariantOfExistingTypeName));
+ }
+
+ VerifyCompanyUnits(gameObject, context);
+ }
+
+ private void VerifyCompanyUnits(GameObject gameObject, string[] context)
+ {
+ if (gameObject.GroundCompanyUnits.Count == 0)
+ return;
+
+ var uniqueCompanyUnits = gameObject.GroundCompanyUnits
+ .Select(x => x.ToUpperInvariant())
+ .Distinct();
+
+ foreach (var companyUnit in uniqueCompanyUnits)
+ {
+ if (GameEngine.GameObjectTypeManager.FindObjectType(companyUnit) is null)
+ {
+ AddError(VerificationError.Create(this, VerifierErrorCodes.MissingXRef,
+ $"Missing company unit '{companyUnit}' for GameObject '{gameObject.Name}'",
+ VerificationSeverity.Critical, [..context, "CompanyUnits"], companyUnit));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/GameObjects/GameObjectTypeVerifier.cs b/src/ModVerify/Verifiers/GameObjects/GameObjectTypeVerifier.cs
new file mode 100644
index 0000000..66d4672
--- /dev/null
+++ b/src/ModVerify/Verifiers/GameObjects/GameObjectTypeVerifier.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Threading;
+using AET.ModVerify.Reporting;
+using AET.ModVerify.Settings;
+using AET.ModVerify.Verifiers.Commons;
+using PG.StarWarsGame.Engine;
+using PG.StarWarsGame.Engine.GameObjects;
+
+namespace AET.ModVerify.Verifiers.GameObjects;
+
+// TODO: Add GameObjectTypeVerifier and check that LandModelTerrainOverride is correct (all keys correct, no dups)
+public sealed partial class GameObjectTypeVerifier : NamedGameEntityVerifier
+{
+ private readonly SingleModelVerifier _singleModelVerifier;
+
+ public override string FriendlyName => "GameObjectType Verifier";
+
+ public override IGameManager GameManager => GameEngine.GameObjectTypeManager;
+
+ public override string EntityTypeName => "GameObjectType";
+
+ public GameObjectTypeVerifier(
+ IStarWarsGameEngine gameEngine,
+ GameVerifySettings settings,
+ IServiceProvider serviceProvider)
+ : base(gameEngine, settings, serviceProvider)
+ {
+ _singleModelVerifier = new SingleModelVerifier(this);
+ }
+
+ protected override void VerifyEntity(GameObject entity, string[] context, double progress, CancellationToken token)
+ {
+ if (entity.Name.Length >= PGConstants.MaxGameObjectTypeName)
+ {
+ AddError(VerificationError.Create(this, VerifierErrorCodes.NameTooLong,
+ $"The GameObjectType name '{entity.Name}' is too long. Maximum length is {PGConstants.MaxGameObjectTypeName}.",
+ VerificationSeverity.Critical, entity.Name));
+ }
+ VerifyXRefs(entity, context);
+ VerifyModels(entity, context, token);
+ VerifyIcons(entity, context);
+ }
+
+ protected override void PostEntityVerify(CancellationToken token)
+ {
+ foreach (var modelError in _singleModelVerifier.VerifyErrors)
+ AddError(modelError);
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/GameVerifier.cs b/src/ModVerify/Verifiers/GameVerifier.cs
index aebfe94..83871d9 100644
--- a/src/ModVerify/Verifiers/GameVerifier.cs
+++ b/src/ModVerify/Verifiers/GameVerifier.cs
@@ -6,22 +6,50 @@
namespace AET.ModVerify.Verifiers;
-public abstract class GameVerifier(
- IGameVerifierInfo? parent,
- IStarWarsGameEngine gameEngine,
- GameVerifySettings settings,
- IServiceProvider serviceProvider)
- : GameVerifierBase(parent, gameEngine, settings, serviceProvider) where T : notnull
+public abstract class GameVerifier : GameVerifierBase where T : notnull
{
+ protected GameVerifier(
+ IGameVerifierInfo? parent,
+ IStarWarsGameEngine gameEngine,
+ GameVerifySettings settings,
+ IServiceProvider serviceProvider) : base(parent, gameEngine, settings, serviceProvider)
+ {
+ }
+ protected GameVerifier(GameVerifierBase parent) : base(parent)
+ {
+ }
+
+ protected GameVerifier(
+ IStarWarsGameEngine gameEngine,
+ GameVerifySettings settings,
+ IServiceProvider serviceProvider) : base(gameEngine, settings, serviceProvider)
+ {
+ }
+
public abstract void Verify(T toVerify, IReadOnlyCollection contextInfo, CancellationToken token);
}
-public abstract class GameVerifier(
- IGameVerifierInfo? parent,
- IStarWarsGameEngine gameEngine,
- GameVerifySettings settings,
- IServiceProvider serviceProvider)
- : GameVerifierBase(parent, gameEngine, settings, serviceProvider)
+public abstract class GameVerifier : GameVerifierBase
{
+ protected GameVerifier(
+ IGameVerifierInfo? parent,
+ IStarWarsGameEngine gameEngine,
+ GameVerifySettings settings,
+ IServiceProvider serviceProvider)
+ : base(parent, gameEngine, settings, serviceProvider)
+ {
+ }
+ protected GameVerifier(GameVerifierBase parent) : base(parent)
+ {
+ }
+
+ protected GameVerifier(
+ IStarWarsGameEngine gameEngine,
+ GameVerifySettings settings,
+ IServiceProvider serviceProvider)
+ : base(gameEngine, settings, serviceProvider)
+ {
+ }
+
public abstract void Verify(CancellationToken token);
}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/GameVerifierBase.cs b/src/ModVerify/Verifiers/GameVerifierBase.cs
index 22b2789..2da47bc 100644
--- a/src/ModVerify/Verifiers/GameVerifierBase.cs
+++ b/src/ModVerify/Verifiers/GameVerifierBase.cs
@@ -8,7 +8,10 @@
using System.Collections.Generic;
using System.IO.Abstractions;
using AET.ModVerify.Progress;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
using PG.StarWarsGame.Engine;
+using AET.ModVerify.Verifiers.Utilities;
namespace AET.ModVerify.Verifiers;
@@ -22,6 +25,7 @@ public abstract class GameVerifierBase : IGameVerifierInfo
protected readonly IFileSystem FileSystem;
protected readonly IServiceProvider Services;
protected readonly GameVerifySettings Settings;
+ protected readonly ILogger Logger;
public IReadOnlyCollection VerifyErrors => [.. _verifyErrors.Keys];
@@ -35,7 +39,23 @@ public abstract class GameVerifierBase : IGameVerifierInfo
protected IGameRepository Repository => GameEngine.GameRepository;
- protected IReadOnlyList VerifierChain { get; }
+ public IReadOnlyList VerifierChain { get; }
+
+
+ protected GameVerifierBase(GameVerifierBase parent)
+ : this(parent, parent.GameEngine, parent.Settings, parent.Services)
+ {
+ if (parent == null)
+ throw new ArgumentNullException(nameof(parent));
+ }
+
+ protected GameVerifierBase(
+ IStarWarsGameEngine gameEngine,
+ GameVerifySettings settings,
+ IServiceProvider serviceProvider)
+ : this (null, gameEngine, settings, serviceProvider)
+ {
+ }
protected GameVerifierBase(
IGameVerifierInfo? parent,
@@ -45,12 +65,13 @@ protected GameVerifierBase(
{
if (serviceProvider == null)
throw new ArgumentNullException(nameof(serviceProvider));
+ Logger = serviceProvider.GetService()?.CreateLogger(GetType()) ?? NullLogger.Instance;
FileSystem = serviceProvider.GetRequiredService();
Services = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
Parent = parent;
Settings = settings ?? throw new ArgumentNullException(nameof(settings));
GameEngine = gameEngine ?? throw new ArgumentNullException(nameof(gameEngine));
- VerifierChain = CreateVerifierChain();
+ VerifierChain = this.GetVerifierChain();
}
protected void AddError(VerificationError error)
@@ -80,18 +101,4 @@ protected void OnProgress(double progress, string? message)
{
Progress?.Invoke(this, new(progress, message));
}
-
- private IReadOnlyList CreateVerifierChain()
- {
- var verifierChain = new List { this };
-
- var parent = Parent;
- while (parent != null)
- {
- verifierChain.Insert(0, parent);
- parent = parent.Parent;
- }
-
- return verifierChain;
- }
}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/GuiDialogs/GuiDialogsVerifier.cs b/src/ModVerify/Verifiers/GuiDialogs/GuiDialogsVerifier.cs
index 435c5de..a33f900 100644
--- a/src/ModVerify/Verifiers/GuiDialogs/GuiDialogsVerifier.cs
+++ b/src/ModVerify/Verifiers/GuiDialogs/GuiDialogsVerifier.cs
@@ -1,5 +1,6 @@
using AET.ModVerify.Reporting;
using AET.ModVerify.Settings;
+using AET.ModVerify.Verifiers.Caching;
using AET.ModVerify.Verifiers.Commons;
using Microsoft.Extensions.DependencyInjection;
using PG.StarWarsGame.Engine;
@@ -8,6 +9,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Text;
using System.Threading;
namespace AET.ModVerify.Verifiers.GuiDialogs;
@@ -16,32 +18,29 @@ sealed class GuiDialogsVerifier : GameVerifier
{
internal const string DefaultComponentIdentifier = "<>";
- private static readonly GuiComponentType[] GuiComponentTypes =
+ private static readonly IReadOnlyList GuiComponentTypes =
Enum.GetValues(typeof(GuiComponentType)).OfType().ToArray();
private readonly IAlreadyVerifiedCache? _cache;
- private readonly TextureVeifier _textureVerifier;
+ private readonly TextureVerifier _textureVerifier;
- public GuiDialogsVerifier(IStarWarsGameEngine gameEngine,
+ public GuiDialogsVerifier(
+ IStarWarsGameEngine gameEngine,
GameVerifySettings settings,
- IServiceProvider serviceProvider) : base(null, gameEngine, settings, serviceProvider)
+ IServiceProvider serviceProvider)
+ : base(gameEngine, settings, serviceProvider)
{
_cache = serviceProvider.GetService();
- _textureVerifier = new TextureVeifier(this, gameEngine, settings, serviceProvider);
+ _textureVerifier = new TextureVerifier(this);
}
public override void Verify(CancellationToken token)
{
- try
- {
- _textureVerifier.Error += OnTextureError;
- VerifyMegaTexturesExist(token);
- VerifyGuiTextures();
- }
- finally
- {
- _textureVerifier.Error -= OnTextureError;
- }
+ VerifyMegaTexturesExist(token);
+ VerifyGuiTextures();
+
+ foreach (var textureError in _textureVerifier.VerifyErrors)
+ AddError(textureError);
}
private void VerifyGuiTextures()
@@ -52,6 +51,8 @@ private void VerifyGuiTextures()
};
components.AddRange(GameEngine.GuiDialogManager.Components);
+ // TODO: Verify no double definitions for textures and components exit
+
foreach (var component in components)
VerifyGuiComponentTexturesExist(component);
@@ -63,8 +64,8 @@ private void VerifyMegaTexturesExist(CancellationToken token)
if (GameEngine.GuiDialogManager.MtdFile is null)
{
var mtdFileName = megaTextureName ?? "<>";
- VerificationError.Create(VerifierChain, VerifierErrorCodes.FileNotFound, $"MtdFile '{mtdFileName}.mtd' could not be found",
- VerificationSeverity.Critical, mtdFileName);
+ AddError(VerificationError.Create(this, VerifierErrorCodes.FileNotFound, $"MtdFile '{mtdFileName}.mtd' could not be found",
+ VerificationSeverity.Critical, mtdFileName));
}
if (megaTextureName is not null)
@@ -84,13 +85,19 @@ private void VerifyMegaTexturesExist(CancellationToken token)
private void VerifyGuiComponentTexturesExist(string component)
{
- var middleButtonInRepoMode = false;
-
-
+ var buttonSpecialMode = false;
+
var entriesForComponent = GetTextureEntriesForComponents(component, out var defined);
if (!defined)
return;
+ if (entriesForComponent.TryGetValue(GuiComponentType.ButtonMiddle, out var middleTexture))
+ {
+ GameEngine.GuiDialogManager.TextureExists(middleTexture, out var origin, out _);
+ if (origin == GuiTextureOrigin.Repository)
+ buttonSpecialMode = true;
+ }
+
foreach (var componentType in GuiComponentTypes)
{
try
@@ -98,55 +105,68 @@ private void VerifyGuiComponentTexturesExist(string component)
if (!entriesForComponent.TryGetValue(componentType, out var texture))
continue;
- if (_cache?.TryAddEntry(texture.Texture) == false)
+ if (buttonSpecialMode && componentType.IsButton() && !componentType.SupportsSpecialTextureMode())
+ {
+ // If we are in special button mode, non-supported button textures won't be loaded anyway.
+ continue;
+ }
+
+ var cached = _cache?.GetEntry(texture.Texture);
+ if (cached?.AlreadyVerified is true)
{
// If we are in a special case we don't want to skip
- if (!middleButtonInRepoMode &&
+ if (!buttonSpecialMode &&
componentType is not GuiComponentType.ButtonMiddle &&
componentType is not GuiComponentType.Scanlines &&
componentType is not GuiComponentType.FrameBackground)
continue;
}
- if (!GameEngine.GuiDialogManager.TextureExists(
- texture,
- out var origin,
- out var isNone,
- middleButtonInRepoMode)
- && !isNone)
+ var exists = GameEngine.GuiDialogManager.TextureExists(
+ texture,
+ out var origin,
+ out var isNone,
+ buttonSpecialMode);
+
+ if (!exists && !isNone)
{
-
if (origin == GuiTextureOrigin.MegaTexture && texture.Texture.Length > MtdFileConstants.MaxFileNameSize)
{
- AddError(VerificationError.Create(VerifierChain, VerifierErrorCodes.FilePathTooLong,
+ AddError(VerificationError.Create(this, VerifierErrorCodes.FilePathTooLong,
$"The filename is too long. Max length is {MtdFileConstants.MaxFileNameSize} characters.",
VerificationSeverity.Error, texture.Texture));
}
else
{
- var message = $"Could not find GUI texture '{texture.Texture}' at location '{origin}'.";
-
- if (texture.Texture.Length > PGConstants.MaxMegEntryPathLength)
- message += " The file name is too long.";
-
- AddError(VerificationError.Create(VerifierChain, VerifierErrorCodes.FileNotFound,
- message, VerificationSeverity.Error,
- [component, origin.ToString()], texture.Texture));
+ AddNotFoundError(texture, component, origin);
}
}
-
- if (componentType is GuiComponentType.ButtonMiddle && origin is GuiTextureOrigin.Repository)
- middleButtonInRepoMode = true;
+
+ _cache?.TryAddEntry(texture.Texture, exists);
}
finally
{
-
- if (componentType >= GuiComponentType.ButtonRightDisabled)
- middleButtonInRepoMode = false;
+ if (!componentType.IsButton())
+ buttonSpecialMode = false;
}
}
}
+ private void AddNotFoundError(ComponentTextureEntry texture, string component, GuiTextureOrigin? origin)
+ {
+ var sb = new StringBuilder($"Could not find GUI texture '{texture.Texture}'");
+ if (origin is not null)
+ sb.Append($" at location '{origin}'");
+ sb.Append('.');
+
+ if (texture.Texture.Length > PGConstants.MaxMegEntryPathLength)
+ sb.Append(" The file name is too long.");
+
+ AddError(VerificationError.Create(this, VerifierErrorCodes.FileNotFound,
+ sb.ToString(), VerificationSeverity.Error,
+ [component, origin.ToString()], texture.Texture));
+ }
+
private IReadOnlyDictionary GetTextureEntriesForComponents(string component, out bool defined)
{
if (component == DefaultComponentIdentifier)
diff --git a/src/ModVerify/Verifiers/IAlreadyVerifiedCache.cs b/src/ModVerify/Verifiers/IAlreadyVerifiedCache.cs
deleted file mode 100644
index 1fe8ad5..0000000
--- a/src/ModVerify/Verifiers/IAlreadyVerifiedCache.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System;
-using PG.Commons.Hashing;
-
-namespace AET.ModVerify.Verifiers;
-
-public interface IAlreadyVerifiedCache
-{
- public bool TryAddEntry(string entry);
- public bool TryAddEntry(ReadOnlySpan entry);
- public bool TryAddEntry(Crc32 checksum);
-}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/IGameVerifierInfo.cs b/src/ModVerify/Verifiers/IGameVerifierInfo.cs
index cba43d1..731d605 100644
--- a/src/ModVerify/Verifiers/IGameVerifierInfo.cs
+++ b/src/ModVerify/Verifiers/IGameVerifierInfo.cs
@@ -1,9 +1,13 @@
-namespace AET.ModVerify.Verifiers;
+using System.Collections.Generic;
+
+namespace AET.ModVerify.Verifiers;
public interface IGameVerifierInfo
{
IGameVerifierInfo? Parent { get; }
+ IReadOnlyList VerifierChain { get; }
+
string Name { get; }
string FriendlyName { get; }
diff --git a/src/ModVerify/Verifiers/NamedGameEntityVerifier.cs b/src/ModVerify/Verifiers/NamedGameEntityVerifier.cs
new file mode 100644
index 0000000..18ec9c3
--- /dev/null
+++ b/src/ModVerify/Verifiers/NamedGameEntityVerifier.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Threading;
+using AET.ModVerify.Settings;
+using AET.ModVerify.Verifiers.Commons;
+using AET.ModVerify.Verifiers.Utilities;
+using Microsoft.Extensions.Logging;
+using PG.StarWarsGame.Engine;
+using PG.StarWarsGame.Files.XML.Data;
+
+namespace AET.ModVerify.Verifiers;
+
+public abstract partial class NamedGameEntityVerifier(
+ IStarWarsGameEngine gameEngine,
+ GameVerifySettings settings,
+ IServiceProvider serviceProvider)
+ : GameVerifier(null, gameEngine, settings, serviceProvider)
+ where T : NamedXmlObject
+{
+ public abstract IGameManager GameManager { get; }
+
+ public abstract string EntityTypeName { get; }
+
+ public sealed override void Verify(CancellationToken token)
+ {
+ OnProgress(0.0, $"Verifying GameManager for '{EntityTypeName}'");
+ PreEntityVerify(token);
+ OnProgress(0.5, null);
+
+ var numEntities = GameEngine.GameObjectTypeManager.Entries.Count;
+ double counter = 0;
+ var context = new string[1];
+ foreach (var gameEntity in GameManager.Entries)
+ {
+ LogVerifyingEntityTypeName(Logger, EntityTypeName, gameEntity.Name);
+ var progress = 0.5 + ++counter / numEntities * 0.5;
+ OnProgress(progress, $"{EntityTypeName} - '{gameEntity.Name}'");
+ context[0] = gameEntity.Name;
+ VerifyEntity(gameEntity, context, progress, token);
+ }
+
+ PostEntityVerify(token);
+ }
+
+ protected virtual void PostEntityVerify(CancellationToken token)
+ {
+ }
+
+ protected abstract void VerifyEntity(T entity, string[] context, double progress, CancellationToken token);
+
+ protected virtual void PreEntityVerify(CancellationToken token)
+ {
+ VerifyDuplicates(token);
+ }
+
+ private void VerifyDuplicates(CancellationToken token)
+ {
+ LogCheckingEntityTypeForDuplicateEntries(Logger, EntityTypeName);
+ var context = IDuplicateVerificationContext.CreateForNamedXmlObjects(GameManager, EntityTypeName);
+ var verifier = new DuplicateVerifier(this, GameEngine, Settings, Services);
+ verifier.Verify(context, [], token);
+ foreach (var error in verifier.VerifyErrors)
+ AddError(error);
+ }
+
+ [LoggerMessage(LogLevel.Trace, "Verifying {entityType} - '{name}'")]
+ static partial void LogVerifyingEntityTypeName(ILogger? logger, string entityType, string name);
+
+ [LoggerMessage(LogLevel.Debug, "Checking {entityType} for duplicate entries")]
+ static partial void LogCheckingEntityTypeForDuplicateEntries(ILogger logger, string entityType);
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/ReferencedModelsVerifier.cs b/src/ModVerify/Verifiers/ReferencedModelsVerifier.cs
deleted file mode 100644
index 4a5feb6..0000000
--- a/src/ModVerify/Verifiers/ReferencedModelsVerifier.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-using AET.ModVerify.Settings;
-using AET.ModVerify.Verifiers.Commons;
-using PG.StarWarsGame.Engine;
-using System;
-using System.Linq;
-using System.Threading;
-
-namespace AET.ModVerify.Verifiers;
-
-public sealed class ReferencedModelsVerifier(
- IStarWarsGameEngine engine,
- GameVerifySettings settings,
- IServiceProvider serviceProvider)
- : GameVerifier(null, engine, settings, serviceProvider)
-{
- public override string FriendlyName => "Referenced Models";
-
- public override void Verify(CancellationToken token)
- {
- var gameObjectEntries = GameEngine.GameObjectTypeManager.Entries.ToList();
- var hardcodedModels = FocHardcodedConstants.HardcodedModels.ToList();
-
- var totalModelsCount = gameObjectEntries.Sum(x => x.Models.Count()) + hardcodedModels.Count;
-
- if (totalModelsCount == 0)
- return;
-
- var counter = 0;
-
- var inner = new SingleModelVerifier(this, GameEngine, Settings, Services);
- try
- {
- inner.Error += OnModelError;
-
- var context = new string[1];
- foreach (var gameObject in gameObjectEntries)
- {
- context[0] = $"GameObject: {gameObject.Name}";
- foreach (var model in gameObject.Models)
- {
- OnProgress((double)++counter / totalModelsCount, $"Model - '{model}'");
- inner.Verify(model, context, token);
- }
- }
-
- context[0] = "Hardcoded Model";
- foreach (var hardcodedModel in hardcodedModels)
- {
- OnProgress((double)++counter / totalModelsCount, $"Model - '{hardcodedModel}'");
- inner.Verify(hardcodedModel, context, token);
- }
- }
- finally
- {
- inner.Error -= OnModelError;
- }
- }
-
- private void OnModelError(object sender, VerificationErrorEventArgs e)
- {
- AddError(e.Error);
- }
-}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/SfxEvents/SfxEventVerifier.Samples.cs b/src/ModVerify/Verifiers/SfxEvents/SfxEventVerifier.Samples.cs
new file mode 100644
index 0000000..68aee32
--- /dev/null
+++ b/src/ModVerify/Verifiers/SfxEvents/SfxEventVerifier.Samples.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Buffers;
+using System.Threading;
+using AET.ModVerify.Verifiers.Commons;
+using AnakinRaW.CommonUtilities.FileSystem.Normalization;
+using PG.StarWarsGame.Engine;
+using PG.StarWarsGame.Engine.Audio.Sfx;
+using PG.StarWarsGame.Engine.Localization;
+
+namespace AET.ModVerify.Verifiers.SfxEvents;
+
+public partial class SfxEventVerifier
+{
+ private void VerifySamples(SfxEvent sfxEvent, string[] context, CancellationToken token)
+ {
+ var isAmbient = IsAmbient2D(sfxEvent);
+ foreach (var codedSample in sfxEvent.AllSamples)
+ VerifySample(codedSample.AsSpan(), sfxEvent, context, isAmbient, token);
+ }
+
+ private void VerifySample(
+ ReadOnlySpan sample,
+ SfxEvent sfxEvent,
+ string[] context,
+ bool isAmbient,
+ CancellationToken token)
+ {
+ char[]? pooledBuffer = null;
+
+ var buffer = sample.Length < PGConstants.MaxMegEntryPathLength
+ ? stackalloc char[PGConstants.MaxMegEntryPathLength]
+ : pooledBuffer = ArrayPool.Shared.Rent(sample.Length);
+
+ try
+ {
+ var length = PathNormalizer.Normalize(sample, buffer, SampleNormalizerOptions);
+ var sampleNameBuffer = buffer.Slice(0, length);
+
+ if (sfxEvent.IsLocalized)
+ {
+ foreach (var language in _languagesToVerify)
+ {
+ VerifySampleLocalized(context, sampleNameBuffer, isAmbient, language, out var localized, token);
+ if (!localized)
+ {
+ // There is no reason to continue if we failed to localize the sample name, because the verification will fail anyway
+ // and we want to avoid multiple errors for the same sample.
+ return;
+ }
+ }
+ }
+ else
+ {
+ var audioInfo = new AudioFileInfo(sampleNameBuffer.ToString(), AudioFileType.Wav, isAmbient);
+ _audioFileVerifier.Verify(audioInfo, context, token);
+ }
+ }
+ finally
+ {
+ if (pooledBuffer is not null)
+ ArrayPool.Shared.Return(pooledBuffer);
+ }
+ }
+
+ private void VerifySampleLocalized(string[] context,
+ ReadOnlySpan sample,
+ bool isAmbient,
+ LanguageType language,
+ out bool localized,
+ CancellationToken token)
+ {
+ char[]? pooledBuffer = null;
+
+ var buffer = sample.Length < PGConstants.MaxMegEntryPathLength
+ ? stackalloc char[PGConstants.MaxMegEntryPathLength]
+ : pooledBuffer = ArrayPool.Shared.Rent(sample.Length);
+ try
+ {
+ var l = _languageManager.LocalizeFileName(sample, language, buffer, out localized);
+ var localizedName = buffer.Slice(0, l);
+
+ var audioInfo = new AudioFileInfo(localizedName.ToString(), AudioFileType.Wav, isAmbient);
+ _audioFileVerifier.Verify(audioInfo, context, token);
+ }
+ finally
+ {
+ if (pooledBuffer is not null)
+ ArrayPool.Shared.Return(pooledBuffer);
+ }
+ }
+
+ // Some heuristics whether a SFXEvent is most likely to be an ambient sound.
+ private bool IsAmbient2D(SfxEvent sfxEvent)
+ {
+ if (!sfxEvent.Is2D)
+ return false;
+
+ if (sfxEvent.IsPreset)
+ return false;
+
+ // If the event is located in SFXEventsAmbient.xml we simply assume it's an ambient sound.
+ var fileName = _fileSystem.Path.GetFileName(sfxEvent.Location.XmlFile).AsSpan();
+ if (fileName.Equals("SFXEventsAmbient.xml".AsSpan(), StringComparison.OrdinalIgnoreCase))
+ return true;
+
+ if (string.IsNullOrEmpty(sfxEvent.UsePresetName))
+ return false;
+
+ if (sfxEvent.UsePresetName!.StartsWith("Preset_AMB_2D", StringComparison.OrdinalIgnoreCase))
+ return true;
+
+ return false;
+ }
+}
diff --git a/src/ModVerify/Verifiers/SfxEvents/SfxEventVerifier.XRef.cs b/src/ModVerify/Verifiers/SfxEvents/SfxEventVerifier.XRef.cs
new file mode 100644
index 0000000..ffdb772
--- /dev/null
+++ b/src/ModVerify/Verifiers/SfxEvents/SfxEventVerifier.XRef.cs
@@ -0,0 +1,21 @@
+using AET.ModVerify.Reporting;
+using PG.StarWarsGame.Engine.Audio.Sfx;
+
+namespace AET.ModVerify.Verifiers.SfxEvents;
+
+public partial class SfxEventVerifier
+{
+ private void VerifyPresetRef(SfxEvent sfxEvent, string[] context)
+ {
+ if (!string.IsNullOrEmpty(sfxEvent.UsePresetName) && sfxEvent.Preset is null)
+ {
+ AddError(VerificationError.Create(
+ this,
+ VerifierErrorCodes.MissingXRef,
+ $"Missing preset '{sfxEvent.UsePresetName}' for SFXEvent '{sfxEvent.Name}'.",
+ VerificationSeverity.Error,
+ [..context, "Preset"],
+ sfxEvent.UsePresetName));
+ }
+ }
+}
diff --git a/src/ModVerify/Verifiers/SfxEvents/SfxEventVerifier.cs b/src/ModVerify/Verifiers/SfxEvents/SfxEventVerifier.cs
new file mode 100644
index 0000000..c688634
--- /dev/null
+++ b/src/ModVerify/Verifiers/SfxEvents/SfxEventVerifier.cs
@@ -0,0 +1,81 @@
+using AET.ModVerify.Reporting;
+using AET.ModVerify.Settings;
+using AET.ModVerify.Verifiers.Commons;
+using AnakinRaW.CommonUtilities.FileSystem.Normalization;
+using Microsoft.Extensions.DependencyInjection;
+using PG.StarWarsGame.Engine;
+using PG.StarWarsGame.Engine.Audio.Sfx;
+using PG.StarWarsGame.Engine.Localization;
+using System;
+using System.Collections.Generic;
+using System.IO.Abstractions;
+using System.Threading;
+
+namespace AET.ModVerify.Verifiers.SfxEvents;
+
+public sealed partial class SfxEventVerifier : NamedGameEntityVerifier
+{
+ private static readonly PathNormalizeOptions SampleNormalizerOptions = new()
+ {
+ UnifyCase = UnifyCasingKind.UpperCaseForce,
+ UnifySeparatorKind = DirectorySeparatorKind.Windows,
+ UnifyDirectorySeparators = true
+ };
+
+ private readonly IGameLanguageManager _languageManager;
+ private readonly IFileSystem _fileSystem;
+ private readonly AudioFileVerifier _audioFileVerifier;
+ private readonly IReadOnlyCollection _languagesToVerify;
+
+ public override IGameManager GameManager => GameEngine.SfxGameManager;
+ public override string FriendlyName => "SFX Events";
+ public override string EntityTypeName => "SFXEvent";
+
+ public SfxEventVerifier(
+ IStarWarsGameEngine gameEngine,
+ GameVerifySettings settings,
+ IServiceProvider serviceProvider)
+ : base(gameEngine, settings, serviceProvider)
+ {
+ _languageManager = serviceProvider.GetRequiredService()
+ .GetLanguageManager(Repository.EngineType);
+ _fileSystem = serviceProvider.GetRequiredService();
+ _audioFileVerifier = new AudioFileVerifier(this);
+ _languagesToVerify = GetLanguagesToVerify();
+ }
+
+ protected override void VerifyEntity(SfxEvent entity, string[] context, double progress, CancellationToken token)
+ {
+ if (entity.Name.Length >= PGConstants.MaxSFXEventName)
+ {
+ AddError(VerificationError.Create(this, VerifierErrorCodes.NameTooLong,
+ $"The SFXEvent name '{entity.Name}' is too long. Maximum length is {PGConstants.MaxSFXEventName}.",
+ VerificationSeverity.Critical, entity.Name));
+ }
+ VerifyPresetRef(entity, context);
+ VerifySamples(entity, context, token);
+ }
+
+ protected override void PostEntityVerify(CancellationToken token)
+ {
+ foreach (var sampleError in _audioFileVerifier.VerifyErrors)
+ AddError(sampleError);
+ }
+
+ private IReadOnlyCollection GetLanguagesToVerify()
+ {
+ switch (Settings.LocalizationOption)
+ {
+ case VerifyLocalizationOption.English:
+ return [LanguageType.English];
+ case VerifyLocalizationOption.CurrentSystem:
+ return [_languageManager.GetLanguagesFromUser()];
+ case VerifyLocalizationOption.AllInstalled:
+ return [..GameEngine.InstalledLanguages];
+ case VerifyLocalizationOption.All:
+ return [.._languageManager.SupportedLanguages];
+ default:
+ throw new NotSupportedException($"{Settings.LocalizationOption} is not supported");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/Utilities/DuplicateVerificationContextExtensions.cs b/src/ModVerify/Verifiers/Utilities/DuplicateVerificationContextExtensions.cs
new file mode 100644
index 0000000..cd81de6
--- /dev/null
+++ b/src/ModVerify/Verifiers/Utilities/DuplicateVerificationContextExtensions.cs
@@ -0,0 +1,22 @@
+using AET.ModVerify.Verifiers.Commons;
+using PG.StarWarsGame.Engine;
+using PG.StarWarsGame.Files.MTD.Files;
+using PG.StarWarsGame.Files.XML.Data;
+
+namespace AET.ModVerify.Verifiers.Utilities;
+
+public static class DuplicateVerificationContextExtensions
+{
+ extension(IDuplicateVerificationContext)
+ {
+ public static IDuplicateVerificationContext CreateForMtd(IMtdFile mtdFile)
+ {
+ return new MtdDuplicateVerificationContext(mtdFile);
+ }
+
+ public static IDuplicateVerificationContext CreateForNamedXmlObjects(IGameManager gameManager, string databaseName) where T : NamedXmlObject
+ {
+ return new NamedXmlObjectDuplicateVerificationContext(databaseName, gameManager);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/Utilities/GameVerifierInfoExtensions.cs b/src/ModVerify/Verifiers/Utilities/GameVerifierInfoExtensions.cs
new file mode 100644
index 0000000..05787a8
--- /dev/null
+++ b/src/ModVerify/Verifiers/Utilities/GameVerifierInfoExtensions.cs
@@ -0,0 +1,18 @@
+using System.Collections.Generic;
+
+namespace AET.ModVerify.Verifiers.Utilities;
+
+internal static class GameVerifierInfoExtensions
+{
+ public static IReadOnlyList GetVerifierChain(this IGameVerifierInfo verifier)
+ {
+ if (verifier.Parent is null)
+ return [verifier];
+
+ var parentChain = verifier.Parent.VerifierChain;
+ var result = new List(parentChain.Count + 1);
+ result.AddRange(parentChain);
+ result.Add(verifier);
+ return result;
+ }
+}
diff --git a/src/ModVerify/Verifiers/NameBasedEqualityComparer.cs b/src/ModVerify/Verifiers/Utilities/NameBasedEqualityComparer.cs
similarity index 94%
rename from src/ModVerify/Verifiers/NameBasedEqualityComparer.cs
rename to src/ModVerify/Verifiers/Utilities/NameBasedEqualityComparer.cs
index 01f396f..1a44506 100644
--- a/src/ModVerify/Verifiers/NameBasedEqualityComparer.cs
+++ b/src/ModVerify/Verifiers/Utilities/NameBasedEqualityComparer.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace AET.ModVerify.Verifiers;
+namespace AET.ModVerify.Verifiers.Utilities;
internal sealed class NameBasedEqualityComparer : IEqualityComparer, IEqualityComparer
{
diff --git a/src/ModVerify/Verifiers/VerifierErrorCodes.cs b/src/ModVerify/Verifiers/VerifierErrorCodes.cs
index 57d3209..04a900d 100644
--- a/src/ModVerify/Verifiers/VerifierErrorCodes.cs
+++ b/src/ModVerify/Verifiers/VerifierErrorCodes.cs
@@ -10,14 +10,19 @@ public static class VerifierErrorCodes
public const string GenericExceptionErrorCode = "MV00";
- public const string FileCorrupt = "ENG00";
+ public const string BinaryFileCorrupt = "BIN00";
public const string FileNotFound = "FILE00";
public const string FilePathTooLong = "FILE01";
public const string InvalidFilePath = "FILE02";
- public const string DuplicateFound = "DUP00";
+ public const string Duplicate = "DUP00";
+ public const string MissingXRef = "XREF00";
+
+ public const string NameTooLong = "NAME00";
+
+ public const string MissingPreset = "SFX00";
public const string SampleNotPCM = "WAV00";
public const string SampleNotMono = "WAV01";
@@ -36,4 +41,6 @@ public static class VerifierErrorCodes
public const string XmlDataBeforeHeader = "XML08";
public const string XmlMissingNode = "XML09";
public const string XmlUnsupportedTag = "XML10";
+ public const string XmlElementsInTag = "XML11";
+ public const string XmlUnexceptedElementName = "XML12";
}
\ No newline at end of file
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/Audio/Sfx/SfxEvent.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/Audio/Sfx/SfxEvent.cs
index aed53f2..43f437d 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/Audio/Sfx/SfxEvent.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/Audio/Sfx/SfxEvent.cs
@@ -1,11 +1,14 @@
using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
using System.Linq;
using PG.Commons.Hashing;
-using PG.StarWarsGame.Engine.Xml;
using PG.StarWarsGame.Files.XML;
+using PG.StarWarsGame.Files.XML.Data;
namespace PG.StarWarsGame.Engine.Audio.Sfx;
+[DebuggerDisplay("{Name}")]
public sealed class SfxEvent : NamedXmlObject
{
private byte _minVolume = DefaultMinVolume;
@@ -25,11 +28,11 @@ public sealed class SfxEvent : NamedXmlObject
public const byte MaxPan2dValue = 100;
public const byte MinPriorityValue = 1;
public const byte MaxPriorityValue = 5;
- public const byte MaxProbability = 100;
- public const sbyte MinMaxInstances = 0;
- public const sbyte InfinitivePlayCount = -1;
- public const float MinLoopSeconds = 0.0f;
- public const float MinVolumeSaturation = 0.0f;
+ public const byte MaxProbabilityValue = 100;
+ public const sbyte MinMaxInstancesValue = 0;
+ public const sbyte InfinitivePlayCountValue = -1;
+ public const float MinLoopSecondsValue = 0.0f;
+ public const float MinVolumeSaturationValue = 0.0f;
// Default values which are not the default value of the type
public const byte DefaultPriority = 3;
@@ -45,6 +48,11 @@ public sealed class SfxEvent : NamedXmlObject
public const byte DefaultMaxPan2d = 50;
public const float DefaultVolumeSaturationDistance = 300.0f;
+ internal readonly List PreSamplesInternal = new();
+ internal readonly List SamplesInternal = new();
+ internal readonly List PostSamplesInternal = new();
+ internal readonly List LocalizedTextIDsInternal = new();
+
public bool IsPreset { get; internal set; }
public bool Is3D { get; internal set; } = DefaultIs3d;
@@ -69,14 +77,14 @@ public sealed class SfxEvent : NamedXmlObject
public IEnumerable AllSamples => PreSamples.Concat(Samples).Concat(PostSamples);
- public IReadOnlyList PreSamples { get; internal set; } = [];
-
- public IReadOnlyList Samples { get; internal set; } = [];
+ public IReadOnlyList PreSamples { get; }
- public IReadOnlyList PostSamples { get; internal set; } = [];
+ public IReadOnlyList Samples { get; }
- public IReadOnlyList LocalizedTextIDs { get; internal set; } = [];
+ public IReadOnlyList PostSamples { get; }
+ public IReadOnlyList LocalizedTextIDs { get; }
+
public byte Priority { get; internal set; } = DefaultPriority;
public byte Probability { get; internal set; } = DefaultProbability;
@@ -161,9 +169,13 @@ public uint MaxPostdelay
internal SfxEvent(string name, Crc32 nameCrc, XmlLocationInfo location)
: base(name, nameCrc, location)
{
+ PreSamples = new ReadOnlyCollection(PreSamplesInternal);
+ Samples = new ReadOnlyCollection(SamplesInternal);
+ PostSamples = new ReadOnlyCollection(PostSamplesInternal);
+ LocalizedTextIDs = new ReadOnlyCollection(LocalizedTextIDsInternal);
}
- internal override void CoerceValues()
+ internal void FixupValues()
{
AdjustMinMaxValues(ref _minVolume, ref _maxVolume);
AdjustMinMaxValues(ref _minPitch, ref _maxPitch);
@@ -187,6 +199,8 @@ internal override void CoerceValues()
*/
public void ApplyPreset(SfxEvent preset)
{
+ Preset = preset;
+
Is3D = preset.Is3D;
Is2D = preset.Is2D;
IsGui = preset.IsGui;
@@ -194,13 +208,11 @@ public void ApplyPreset(SfxEvent preset)
IsUnitResponseVo = preset.IsUnitResponseVo;
IsAmbientVo = preset.IsAmbientVo;
IsLocalized = preset.IsLocalized;
- Preset = preset;
- UsePresetName = preset.Name;
PlaySequentially = preset.PlaySequentially;
- PreSamples = preset.PreSamples;
- Samples = preset.Samples;
- PostSamples = preset.PostSamples;
- LocalizedTextIDs = preset.LocalizedTextIDs;
+ SetList(PreSamplesInternal, preset.PreSamplesInternal);
+ SetList(SamplesInternal, preset.SamplesInternal);
+ SetList(PostSamplesInternal, preset.PostSamplesInternal);
+ SetList(LocalizedTextIDsInternal, preset.LocalizedTextIDsInternal);
Priority = preset.Priority;
Probability = preset.Probability;
PlayCount = preset.PlayCount;
@@ -219,6 +231,13 @@ public void ApplyPreset(SfxEvent preset)
MaxPitch = preset.MaxPitch;
MinPan2D = preset.MinPan2D;
MaxPan2D = preset.MaxPan2D;
+ return;
+
+ static void SetList(List target, List source)
+ {
+ target.Clear();
+ target.AddRange(source);
+ }
}
private static void AdjustMinMaxValues(ref byte minValue, ref byte maxValue)
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/Audio/Sfx/SfxEventGameManager.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/Audio/Sfx/SfxEventGameManager.cs
index b037939..99f1c31 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/Audio/Sfx/SfxEventGameManager.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/Audio/Sfx/SfxEventGameManager.cs
@@ -7,11 +7,14 @@
using PG.StarWarsGame.Engine.ErrorReporting;
using PG.StarWarsGame.Engine.IO.Repositories;
using PG.StarWarsGame.Engine.Localization;
-using PG.StarWarsGame.Engine.Xml.Parsers;
+using PG.StarWarsGame.Engine.Xml;
namespace PG.StarWarsGame.Engine.Audio.Sfx;
-internal class SfxEventGameManager(GameRepository repository, GameEngineErrorReporterWrapper errorReporter, IServiceProvider serviceProvider)
+internal class SfxEventGameManager(
+ GameRepository repository,
+ GameEngineErrorReporterWrapper errorReporter,
+ IServiceProvider serviceProvider)
: GameManagerBase(repository, errorReporter, serviceProvider), ISfxEventGameManager
{
public IEnumerable InstalledLanguages { get; private set; } = [];
@@ -24,42 +27,20 @@ protected override async Task InitializeCoreAsync(CancellationToken token)
Logger?.LogInformation("Parsing SFXEvents...");
- var contentParser = new XmlContainerContentParser(ServiceProvider, ErrorReporter);
- contentParser.XmlParseError += OnParseError;
- try
- {
- await Task.Run(() => contentParser.ParseEntriesFromFileListXml(
- "DATA\\XML\\SFXEventFiles.XML",
- GameRepository,
- "DATA\\XML",
- NamedEntries,
- VerifyFilePathLength),
- token);
- }
- finally
- {
- contentParser.XmlParseError -= OnParseError;
- }
- }
-
- private void OnParseError(object sender, XmlContainerParserErrorEventArgs e)
- {
- if (e.ErrorInXmlFileList || e.HasException)
- {
- e.Continue = false;
- ErrorReporter.Report(new InitializationError
+ var contentParser = new PetroglyphStarWarsGameXmlParser(GameRepository,
+ new PetroglyphStarWarsGameXmlParseSettings
{
GameManager = ToString(),
- Message = GetMessage(e)
- });
- }
- }
-
- private static string GetMessage(XmlContainerParserErrorEventArgs errorEventArgs)
- {
- if (errorEventArgs.HasException)
- return $"Error while parsing SFXEvent XML file '{errorEventArgs.File}': {errorEventArgs.Exception.Message}";
- return "Could not find SFXEventFiles.xml";
+ InvalidObjectXmlFailsInitialization = true,
+ InvalidFilesListXmlFailsInitialization = true
+ }, ServiceProvider, ErrorReporter);
+
+ await Task.Run(() => contentParser.ParseEntriesFromFileListXml(
+ "DATA\\XML\\SFXEventFiles.XML",
+ "DATA\\XML",
+ NamedEntries,
+ VerifyFilePathLength),
+ token);
}
private void VerifyFilePathLength(string filePath)
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/CommandBarGameManager.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/CommandBarGameManager.cs
index 0b8687e..a012a50 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/CommandBarGameManager.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/CommandBarGameManager.cs
@@ -1,27 +1,21 @@
using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
using PG.Commons.Hashing;
using PG.StarWarsGame.Engine.CommandBar.Components;
-using PG.StarWarsGame.Engine.CommandBar.Xml;
using PG.StarWarsGame.Engine.ErrorReporting;
using PG.StarWarsGame.Engine.GameConstants;
using PG.StarWarsGame.Engine.IO.Repositories;
using PG.StarWarsGame.Engine.Rendering;
using PG.StarWarsGame.Engine.Rendering.Font;
-using PG.StarWarsGame.Engine.Xml.Parsers;
-using PG.StarWarsGame.Files.Binary;
using PG.StarWarsGame.Files.MTD.Files;
using PG.StarWarsGame.Files.MTD.Services;
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using AnakinRaW.CommonUtilities.Collections;
+using System.Numerics;
+using PG.StarWarsGame.Engine.GameObjects;
namespace PG.StarWarsGame.Engine.CommandBar;
-internal class CommandBarGameManager(
+internal partial class CommandBarGameManager(
GameRepository repository,
PGRender pgRender,
IGameConstants gameConstants,
@@ -33,16 +27,14 @@ internal class CommandBarGameManager(
private readonly ICrc32HashingService _hashingService = serviceProvider.GetRequiredService();
private readonly IMtdFileService _mtdFileService = serviceProvider.GetRequiredService();
private readonly Dictionary _groups = new();
- private readonly PGRender _pgRender = pgRender;
- private bool _megaTextureExists;
private FontData? _defaultFont;
public ICollection Components => Entries;
public IReadOnlyDictionary Groups => _groups;
- public FontData? DefaultFont
+ public FontData? DefaultFont
{
get
{
@@ -56,7 +48,7 @@ private set
}
}
- public IMtdFile? MegaTextureFile
+ public IMtdFile? MtdFile
{
get
{
@@ -70,224 +62,39 @@ private set
}
}
- protected override async Task InitializeCoreAsync(CancellationToken token)
+ public string? MegaTextureFileName
{
- Logger?.LogInformation("Creating command bar components...");
-
- var contentParser = new XmlContainerContentParser(ServiceProvider, ErrorReporter);
- contentParser.XmlParseError += OnParseError;
-
- var parsedCommandBarComponents = new FrugalValueListDictionary();
-
- try
- {
- await Task.Run(() => contentParser.ParseEntriesFromFileListXml(
- "DATA\\XML\\CommandBarComponentFiles.XML",
- GameRepository,
- ".\\DATA\\XML",
- parsedCommandBarComponents,
- VerifyFilePathLength),
- token);
- }
- finally
- {
- contentParser.XmlParseError -= OnParseError;
- }
-
- // Create Scene
- // Create Camera
- // Resize(true)
-
- foreach (var parsedCommandBarComponent in parsedCommandBarComponents.Values)
+ get
{
- var component = CommandBarBaseComponent.Create(parsedCommandBarComponent, ErrorReporter);
- if (component is not null)
- {
- var crc = _hashingService.GetCrc32(component.Name, PGConstants.DefaultPGEncoding);
- NamedEntries.Add(crc, component);
- }
+ ThrowIfNotInitialized();
+ return field;
}
-
- SetComponentGroup(Components);
- SetMegaTexture();
- SetDefaultFont();
-
- LinkComponentsToShell();
- LinkComponentsWithActions();
- }
-
- private void LinkComponentsWithActions()
- {
- var nameLookup = SupportedCommandBarComponentData.GetComponentIdsForEngine(GameRepository.EngineType);
-
- foreach (var idPair in nameLookup)
+ private set
{
- var crc = _hashingService.GetCrc32(idPair.Value, PGConstants.DefaultPGEncoding);
- if (NamedEntries.TryGetFirstValue(crc, out var component))
- component.Id = idPair.Key;
+ ThrowIfAlreadyInitialized();
+ field = value;
}
}
- private void LinkComponentsToShell()
- {
- if (!Groups.TryGetValue(CommandBarConstants.ShellGroupName, out var shellGroup))
- return;
- var modelCache = new Dictionary();
- foreach (var component in Components)
- {
- if (component.Type == CommandBarComponentType.Shell)
- continue;
+ public Vector3 CommandBarScale { get; }
- foreach (var shellComponent in shellGroup.Components)
- {
- if (LinkToShell(component, shellComponent as CommandBarShellComponent, modelCache))
- break;
- }
- }
+ public Vector3 CommandBarOffset { get; internal set; }
- foreach (var model in modelCache.Values)
- model?.Dispose();
- }
-
- private bool LinkToShell(
- CommandBarBaseComponent component,
- CommandBarShellComponent? shell,
- IDictionary modelCache)
+ public bool IconExists(GameObject gameObject)
{
- if (shell is null)
- {
- ErrorReporter.Assert(
- EngineAssert.FromNullOrEmpty(
- [component.Name], $"Cannot link component '{component}' because shell component is null."));
- return false;
- }
-
- var componentName = component.Name;
- if (string.IsNullOrEmpty(componentName))
- return false;
-
- var modelPath = shell.ModelPath;
- if (string.IsNullOrEmpty(modelPath))
- return false;
-
- if (!modelCache.TryGetValue(shell.Name, out var model))
- {
- model = _pgRender.LoadModelAndAnimations(modelPath.AsSpan(), null, true);
- modelCache.Add(shell.Name, model);
- }
-
- if (model is null)
- {
- ErrorReporter.Assert(
- EngineAssert.FromNullOrEmpty(
- [$"component='{component.Name}'", $"shell='{shell.Name}'"],
- $"Cannot link component '{componentName}' to shell '{shell.Name}' because model '{modelPath}' could not be loaded."));
- return false;
- }
+ ThrowIfNotInitialized();
+ if (gameObject == null)
+ throw new ArgumentNullException(nameof(gameObject));
- if (!model.IsModel)
- {
- ErrorReporter.Assert(
- EngineAssert.FromNullOrEmpty(
- [$"component='{component.Name}'", $"shell='{shell.Name}'"],
- $"Cannot link component '{componentName}' to shell '{shell.Name}' because the loaded file '{modelPath}' is not a model."));
+ if (MtdFile is null)
return false;
- }
- var boneIndex = model.IndexOfBone(componentName);
-
- if (boneIndex == -1)
+ if (string.IsNullOrEmpty(gameObject.IconName))
return false;
- component.Bone = boneIndex;
- component.ParentShell = shell;
- return true;
- }
- private void SetDefaultFont()
- {
- // The code is only triggered iff at least one Text CommandbarBar component existed
- if (Components.FirstOrDefault(x => x is CommandBarTextComponent or CommandBarTextButtonComponent) is null)
- return;
+ var crc = _hashingService.GetCrc32Upper(gameObject.IconName, PGConstants.DefaultPGEncoding);
- if (_defaultFont is null)
- {
- // TODO: From GameConstants
- var fontName = PGConstants.DefaultUnicodeFontName;
- var size = 11;
- var font = fontManager.CreateFont(fontName, size, true, false, false, 1.0f);
- if (font is null)
- ErrorReporter.Assert(EngineAssert.FromNullOrEmpty([ToString()], $"Unable to create Default from name {fontName}"));
- DefaultFont = font;
- }
- }
-
- private void SetMegaTexture()
- {
- // The code is only triggered iff at least one Shell CommandbarBar component existed
- if (Components.FirstOrDefault(x => x is CommandBarShellComponent) is null)
- return;
- // Note: The tag is not used by the engine
- var mtdPath = FileSystem.Path.Combine("DATA\\ART\\TEXTURES", $"{CommandBarConstants.MegaTextureBaseName}.mtd");
- using var megaTexture = GameRepository.TryOpenFile(mtdPath);
-
- try
- {
- MegaTextureFile = megaTexture is null ? null : _mtdFileService.Load(megaTexture);
- }
- catch (BinaryCorruptedException e)
- {
- var message = $"Failed to load MTD file '{mtdPath}': {e.Message}";
- Logger?.LogError(e, message);
- ErrorReporter.Assert(EngineAssert.Create(EngineAssertKind.CorruptBinary, mtdPath, [], message));
- }
- _megaTextureExists = GameRepository.TextureRepository.FileExists($"{CommandBarConstants.MegaTextureBaseName}.tga");
- }
-
- private void SetComponentGroup(IEnumerable components)
- {
- var groupData = components
- .Where(x => !string.IsNullOrEmpty(x.XmlData.Group))
- .GroupBy(x => x.XmlData.Group!, StringComparer.Ordinal);
-
- foreach (var grouping in groupData)
- {
- var group = new CommandBarComponentGroup(grouping.Key, grouping);
- _groups.Add(grouping.Key, group);
- foreach (var component in grouping)
- component.Group = group;
- }
- }
-
- private void OnParseError(object sender, XmlContainerParserErrorEventArgs e)
- {
- if (e.ErrorInXmlFileList || e.HasException)
- {
- e.Continue = false;
- ErrorReporter.Report(new InitializationError
- {
- GameManager = ToString(),
- Message = GetMessage(e)
- });
- }
- }
-
- private static string GetMessage(XmlContainerParserErrorEventArgs errorEventArgs)
- {
- if (errorEventArgs.HasException)
- return $"Error while parsing CommandBar XML file '{errorEventArgs.File}': {errorEventArgs.Exception.Message}";
- return "Could not find CommandBarComponentFiles.xml";
- }
-
- private void VerifyFilePathLength(string filePath)
- {
- if (filePath.Length > PGConstants.MaxCommandBarDatabaseFileName)
- {
- ErrorReporter.Report(new InitializationError
- {
- GameManager = ToString(),
- Message = $"CommandBar file '{filePath}' is longer than {PGConstants.MaxCommandBarDatabaseFileName} characters."
- });
- }
+ return MtdFile.Content.Contains(crc);
}
-}
+}
\ No newline at end of file
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/CommandBarGameManager_Initialization.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/CommandBarGameManager_Initialization.cs
new file mode 100644
index 0000000..4835ed3
--- /dev/null
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/CommandBarGameManager_Initialization.cs
@@ -0,0 +1,243 @@
+using AnakinRaW.CommonUtilities.Collections;
+using Microsoft.Extensions.Logging;
+using PG.Commons.Hashing;
+using PG.StarWarsGame.Engine.CommandBar.Components;
+using PG.StarWarsGame.Engine.CommandBar.Xml;
+using PG.StarWarsGame.Engine.ErrorReporting;
+using PG.StarWarsGame.Engine.Rendering;
+using PG.StarWarsGame.Engine.Xml;
+using PG.StarWarsGame.Files.Binary;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace PG.StarWarsGame.Engine.CommandBar;
+
+internal partial class CommandBarGameManager
+{
+ protected override async Task InitializeCoreAsync(CancellationToken token)
+ {
+ Logger?.LogInformation("Creating command bar components...");
+
+ var contentParser = new PetroglyphStarWarsGameXmlParser(GameRepository, new PetroglyphStarWarsGameXmlParseSettings
+ {
+ GameManager = ToString(),
+ InvalidObjectXmlFailsInitialization = true,
+ InvalidFilesListXmlFailsInitialization = true
+ }, ServiceProvider, ErrorReporter);
+
+ var parsedCommandBarComponents = new FrugalValueListDictionary();
+
+ await Task.Run(() => contentParser.ParseEntriesFromFileListXml(
+ ".\\Data\\XML\\CommandBarComponentFiles.xml",
+ ".\\DATA\\XML\\",
+ parsedCommandBarComponents,
+ VerifyFilePathLength),
+ token);
+
+ CommandBarOffset = new Vector3(-0.5f, -0.5f, 0.0f);
+
+ // Create Scene
+ // Create Camera
+ // Resize(force: true)
+
+ foreach (var parsedCommandBarComponent in parsedCommandBarComponents.Values)
+ {
+ var component = CommandBarBaseComponent.Create(parsedCommandBarComponent, ErrorReporter);
+ if (component is not null)
+ {
+ var crc = _hashingService.GetCrc32(component.Name, PGConstants.DefaultPGEncoding);
+ NamedEntries.Add(crc, component);
+ }
+
+ if (component is CommandBarShellComponent shellComponent)
+ SetModelTransform(shellComponent);
+ }
+
+ SetComponentGroup(Components);
+ SetMegaTexture();
+ SetDefaultFont();
+
+ LinkComponentsToShell();
+ LinkComponentsWithActions();
+
+
+ // CommandBarClass::Set_Encyclopedia_Delay_Time(this);
+ // CommandBarClass::Find_Neighbors(this);
+
+ // CommandBarClass::Load_Hero_Particles(this);
+ // CommandBarClass::Load_Corruption_Particle(this);
+ }
+
+ private void SetModelTransform(CommandBarShellComponent shellComponent)
+ {
+ if (string.IsNullOrEmpty(shellComponent.ModelPath) ||
+ !GameRepository.ModelRepository.FileExists(shellComponent.ModelPath))
+ return;
+ shellComponent.SetOffsetAndScale(CommandBarOffset, CommandBarScale);
+ }
+
+ private void LinkComponentsWithActions()
+ {
+ var nameLookup = SupportedCommandBarComponentData.GetComponentIdsForEngine(GameRepository.EngineType);
+ foreach (var idPair in nameLookup)
+ {
+ // The engine does not uppercase the name here
+ var crc = _hashingService.GetCrc32(idPair.Value, PGConstants.DefaultPGEncoding);
+ if (NamedEntries.TryGetFirstValue(crc, out var component))
+ {
+ // NB: Currently we do not have "action"
+ // but we keep the original method name 'LinkComponentsWithActions'
+ component.Id = idPair.Key;
+ }
+ }
+ }
+
+ private void LinkComponentsToShell()
+ {
+ if (!Groups.TryGetValue(CommandBarConstants.ShellGroupName, out var shellGroup))
+ return;
+
+ var modelCache = new Dictionary();
+ foreach (var component in Components)
+ {
+ if (component.Type == CommandBarComponentType.Shell)
+ continue;
+
+ foreach (var shellComponent in shellGroup.Components)
+ {
+ if (LinkToShell(component, shellComponent as CommandBarShellComponent, modelCache))
+ break;
+ }
+ }
+
+ foreach (var model in modelCache.Values)
+ model?.Dispose();
+ }
+
+ private bool LinkToShell(
+ CommandBarBaseComponent component,
+ CommandBarShellComponent? shell,
+ IDictionary modelCache)
+ {
+ if (shell is null)
+ {
+ ErrorReporter.Assert(
+ EngineAssert.FromNullOrEmpty(
+ [component.Name], $"Cannot link component '{component}' because shell component is null."));
+ return false;
+ }
+
+ var componentName = component.Name;
+ if (string.IsNullOrEmpty(componentName))
+ return false;
+
+ var modelPath = shell.ModelPath;
+ if (string.IsNullOrEmpty(modelPath))
+ return false;
+
+ if (!modelCache.TryGetValue(shell.Name, out var model))
+ {
+ model = pgRender.LoadModelAndAnimations(modelPath.AsSpan(), null, true);
+ modelCache.Add(shell.Name, model);
+ }
+
+ if (model is null)
+ {
+ ErrorReporter.Assert(
+ EngineAssert.FromNullOrEmpty(
+ [$"component='{component.Name}'", $"shell='{shell.Name}'"],
+ $"Cannot link component '{componentName}' to shell '{shell.Name}' because model '{modelPath}' could not be loaded."));
+ return false;
+ }
+
+ if (!model.IsModel)
+ {
+ ErrorReporter.Assert(
+ EngineAssert.FromNullOrEmpty(
+ [$"component='{component.Name}'", $"shell='{shell.Name}'"],
+ $"Cannot link component '{componentName}' to shell '{shell.Name}' because the loaded file '{modelPath}' is not a model."));
+ return false;
+ }
+
+ var boneIndex = model.IndexOfBone(componentName);
+
+ if (boneIndex == -1)
+ return false;
+ component.Bone = boneIndex;
+ component.ParentShell = shell;
+ return true;
+ }
+
+ private void SetDefaultFont()
+ {
+ // The code is only triggered iff at least one Text CommandbarBar component existed
+ if (Components.FirstOrDefault(x => x is CommandBarTextComponent or CommandBarTextButtonComponent) is null)
+ return;
+
+ if (_defaultFont is null)
+ {
+ // TODO: From GameConstants
+ var fontName = PGConstants.DefaultUnicodeFontName;
+ var size = 11;
+ var font = fontManager.CreateFont(fontName, size, true, false, false, 1.0f);
+ if (font is null)
+ ErrorReporter.Assert(EngineAssert.FromNullOrEmpty([ToString()], $"Unable to create Default from name {fontName}"));
+ DefaultFont = font;
+ }
+ }
+
+ private void SetMegaTexture()
+ {
+ // The code is only triggered iff at least one Shell CommandbarBar component existed
+ if (Components.FirstOrDefault(x => x is CommandBarShellComponent) is null)
+ return;
+ // Note: The tag is not used by the engine
+ var mtdPath = FileSystem.Path.Combine("DATA\\ART\\TEXTURES", $"{CommandBarConstants.MegaTextureBaseName}.mtd");
+ using var megaTexture = GameRepository.TryOpenFile(mtdPath);
+
+ try
+ {
+ MtdFile = megaTexture is null ? null : _mtdFileService.Load(megaTexture);
+ }
+ catch (BinaryCorruptedException e)
+ {
+ var message = $"Failed to load MTD file '{mtdPath}': {e.Message}";
+ Logger?.LogError(e, message);
+ ErrorReporter.Assert(EngineAssert.Create(EngineAssertKind.CorruptBinary, mtdPath, [], message));
+ }
+
+ GameRepository.TextureRepository.FileExists($"{CommandBarConstants.MegaTextureBaseName}.tga", false, out _, out var actualFilePath);
+ MegaTextureFileName = FileSystem.Path.GetFileName(actualFilePath);
+ }
+
+ private void SetComponentGroup(IEnumerable components)
+ {
+ var groupData = components
+ .Where(x => !string.IsNullOrEmpty(x.XmlData.Group))
+ .GroupBy(x => x.XmlData.Group!, StringComparer.Ordinal);
+
+ foreach (var grouping in groupData)
+ {
+ var group = new CommandBarComponentGroup(grouping.Key, grouping);
+ _groups.Add(grouping.Key, group);
+ foreach (var component in grouping)
+ component.Group = group;
+ }
+ }
+
+ private void VerifyFilePathLength(string filePath)
+ {
+ if (filePath.Length > PGConstants.MaxCommandBarDatabaseFileName)
+ {
+ ErrorReporter.Report(new InitializationError
+ {
+ GameManager = ToString(),
+ Message = $"CommandBar file '{filePath}' is longer than {PGConstants.MaxCommandBarDatabaseFileName} characters."
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/Components/CommandBarShellComponent.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/Components/CommandBarShellComponent.cs
index 799040e..f649d80 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/Components/CommandBarShellComponent.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/Components/CommandBarShellComponent.cs
@@ -1,4 +1,7 @@
using PG.StarWarsGame.Engine.CommandBar.Xml;
+using System.Numerics;
+using PG.StarWarsGame.Engine.Rendering;
+using PG.StarWarsGame.Engine.Utilities;
namespace PG.StarWarsGame.Engine.CommandBar.Components;
@@ -10,10 +13,33 @@ public class CommandBarShellComponent : CommandBarBaseComponent
public string? ModelPath { get; }
+ public Matrix3x4 ModelTransform { get; internal set; } = Matrix3x4.Identity;
+
public CommandBarShellComponent(CommandBarComponentData xmlData) : base(xmlData)
{
ModelName = xmlData.ModelName;
if (!string.IsNullOrEmpty(ModelName))
ModelPath = $"DATA\\ART\\MODELS\\{ModelName}";
}
+
+ internal void SetOffsetAndScale(Vector3 offset, Vector3 scale)
+ {
+ var newOffset = new Vector3(0.0f, 0.0f, 0.0f);
+ var newScale = new Vector3(1.0f, 1.0f, 1.0f);
+ if (XmlData.ModelOffsetX)
+ newOffset.X = offset.X;
+ if (XmlData.ModelOffsetY)
+ newOffset.Y = offset.Y;
+ if (XmlData.ScaleModelX)
+ newScale.X = scale.X;
+ if (XmlData.ScaleModelY)
+ newScale.Y = scale.Y;
+
+ newOffset.X = PGMath.Floor(newOffset.X) + 0.5f;
+ newOffset.Y = PGMath.Floor(newOffset.Y) + 0.5f;
+
+ ModelTransform = Matrix3x4.Identity
+ * Matrix3x4.Scale(newScale)
+ * Matrix3x4.CreateTranslation(newOffset);
+ }
}
\ No newline at end of file
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/ICommandBarGameManager.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/ICommandBarGameManager.cs
index 665d217..6c2749d 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/ICommandBarGameManager.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/ICommandBarGameManager.cs
@@ -1,14 +1,19 @@
using System.Collections.Generic;
using PG.StarWarsGame.Engine.CommandBar.Components;
+using PG.StarWarsGame.Engine.GameObjects;
using PG.StarWarsGame.Files.MTD.Files;
namespace PG.StarWarsGame.Engine.CommandBar;
public interface ICommandBarGameManager : IGameManager
{
- IMtdFile? MegaTextureFile { get; }
+ IMtdFile? MtdFile { get; }
+
+ string? MegaTextureFileName { get; }
ICollection Components { get; }
IReadOnlyDictionary Groups { get; }
+
+ bool IconExists(GameObject gameObject);
}
\ No newline at end of file
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/SupportedCommandBarComponentData.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/SupportedCommandBarComponentData.cs
index 7b6eeb6..388599c 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/SupportedCommandBarComponentData.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/SupportedCommandBarComponentData.cs
@@ -5,6 +5,8 @@ namespace PG.StarWarsGame.Engine.CommandBar;
public static class SupportedCommandBarComponentData
{
+ // Unfortunately we cannot use EnumConversionDictionary, because EaW and use different enum values
+ // for the same components, so we need to maintain separate dictionaries for each engine.
public static IReadOnlyDictionary GetComponentIdsForEngine(GameEngineType engineType)
{
return engineType switch
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/Xml/CommandBarComponentData.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/Xml/CommandBarComponentData.cs
index 057745e..659130a 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/Xml/CommandBarComponentData.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/Xml/CommandBarComponentData.cs
@@ -1,15 +1,14 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Numerics;
using PG.Commons.Hashing;
using PG.Commons.Numerics;
-using PG.StarWarsGame.Engine.Xml;
using PG.StarWarsGame.Files.XML;
+using PG.StarWarsGame.Files.XML.Data;
namespace PG.StarWarsGame.Engine.CommandBar.Xml;
-public sealed class CommandBarComponentData(string name, Crc32 crc, XmlLocationInfo location) : NamedXmlObject(name, crc, location)
+public sealed class CommandBarComponentData : NamedXmlObject
{
public const float DefaultScale = 1.0f;
public const float DefaultBlinkRate = 0.2f;
@@ -17,18 +16,31 @@ public sealed class CommandBarComponentData(string name, Crc32 crc, XmlLocationI
public static readonly Vector2 DefaultOffsetWidescreenValue = new(9.9999998e17f, 9.9999998e17f);
public static readonly Vector4Int WhiteColor = new(255, 255, 255, 255);
- public IReadOnlyList SelectedTextureNames { get; internal set; } = [];
- public IReadOnlyList BlankTextureNames { get; internal set; } = [];
- public IReadOnlyList IconAlternateTextureNames { get; internal set; } = [];
- public IReadOnlyList MouseOverTextureNames { get; internal set; } = [];
- public IReadOnlyList BarTextureNames { get; internal set; } = [];
- public IReadOnlyList BarOverlayNames { get; internal set; } = [];
- public IReadOnlyList AlternateFontNames { get; internal set; } = [];
- public IReadOnlyList TooltipTexts { get; internal set; } = [];
- public IReadOnlyList LowerEffectTextureNames { get; internal set; } = [];
- public IReadOnlyList UpperEffectTextureNames { get; internal set; } = [];
- public IReadOnlyList OverlayTextureNames { get; internal set; } = [];
- public IReadOnlyList Overlay2TextureNames { get; internal set; } = [];
+ internal readonly List SelectedTextureNamesInternal = [];
+ internal readonly List BlankTextureNamesInternal = [];
+ internal readonly List IconAlternateTextureNamesInternal = [];
+ internal readonly List MouseOverTextureNamesInternal = [];
+ internal readonly List BarTextureNamesInternal = [];
+ internal readonly List BarOverlayNamesInternal = [];
+ internal readonly List AlternateFontNamesInternal = [];
+ internal readonly List TooltipTextsInternal = [];
+ internal readonly List LowerEffectTextureNamesInternal = [];
+ internal readonly List UpperEffectTextureNamesInternal = [];
+ internal readonly List OverlayTextureNamesInternal = [];
+ internal readonly List Overlay2TextureNamesInternal = [];
+
+ public IReadOnlyList SelectedTextureNames { get; }
+ public IReadOnlyList BlankTextureNames { get; }
+ public IReadOnlyList IconAlternateTextureNames { get; }
+ public IReadOnlyList MouseOverTextureNames { get; }
+ public IReadOnlyList BarTextureNames { get; }
+ public IReadOnlyList BarOverlayNames { get; }
+ public IReadOnlyList AlternateFontNames { get; }
+ public IReadOnlyList TooltipTexts { get; }
+ public IReadOnlyList LowerEffectTextureNames { get; }
+ public IReadOnlyList UpperEffectTextureNames { get; }
+ public IReadOnlyList OverlayTextureNames { get; }
+ public IReadOnlyList Overlay2TextureNames { get; }
public string? IconTextureName { get; internal set; }
public string? DisabledTextureName { get; internal set; }
@@ -128,22 +140,26 @@ public sealed class CommandBarComponentData(string name, Crc32 crc, XmlLocationI
public Vector4Int? TextColor2 { get; internal set; }
public Vector4Int? MaxBarColor { get; internal set; } = WhiteColor;
- internal override void CoerceValues()
+ public CommandBarComponentData(string name, Crc32 crc, XmlLocationInfo location) : base(name, crc, location)
{
- base.CoerceValues();
- if (AlternateFontNames.Count == 0)
- return;
- var newFontNames = new string[AlternateFontNames.Count];
- for (var i = 0; i < AlternateFontNames.Count; i++)
- {
- var current = AlternateFontNames[i];
+ SelectedTextureNames = new ReadOnlyCollection(SelectedTextureNamesInternal);
+ BlankTextureNames = new ReadOnlyCollection(BlankTextureNamesInternal);
+ IconAlternateTextureNames = new ReadOnlyCollection(IconAlternateTextureNamesInternal);
+ MouseOverTextureNames = new ReadOnlyCollection(MouseOverTextureNamesInternal);
+ BarTextureNames = new ReadOnlyCollection(BarTextureNamesInternal);
+ BarOverlayNames = new ReadOnlyCollection(BarOverlayNamesInternal);
+ AlternateFontNames = new ReadOnlyCollection(AlternateFontNamesInternal);
+ TooltipTexts = new ReadOnlyCollection(TooltipTextsInternal);
+ LowerEffectTextureNames = new ReadOnlyCollection(LowerEffectTextureNamesInternal);
+ UpperEffectTextureNames = new ReadOnlyCollection(UpperEffectTextureNamesInternal);
+ OverlayTextureNames = new ReadOnlyCollection(OverlayTextureNamesInternal);
+ Overlay2TextureNames = new ReadOnlyCollection(Overlay2TextureNamesInternal);
+ }
- if (current.AsSpan().IndexOf('_') != -1)
- newFontNames[i] = current.Replace('_', ' ');
- else
- newFontNames[i] = current;
- }
- AlternateFontNames = new ReadOnlyCollection(newFontNames);
+ internal void FixupValues()
+ {
+ for (var i = 0; i < AlternateFontNamesInternal.Count; i++)
+ AlternateFontNamesInternal[i] = AlternateFontNamesInternal[i].Replace('_', ' ');
}
}
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/Commons/MultiNameReferenceList.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/Commons/MultiNameReferenceList.cs
new file mode 100644
index 0000000..ff828a4
--- /dev/null
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/Commons/MultiNameReferenceList.cs
@@ -0,0 +1,57 @@
+using System.Collections;
+using System.Collections.Generic;
+
+namespace PG.StarWarsGame.Engine.Commons;
+
+public class MultiNameReferenceList : IReadOnlyList