diff --git a/C7/Animations/AnimationManager.cs b/C7/Animations/AnimationManager.cs index 467932015..10196a1f8 100644 --- a/C7/Animations/AnimationManager.cs +++ b/C7/Animations/AnimationManager.cs @@ -28,15 +28,15 @@ public static string BaseAnimationKey(string unitName, MapUnit.AnimatedAction ac return String.Format("{0}_{1}", unitName, action.ToString()); } - public static string BaseAnimationKey(UnitPrototype unit, MapUnit.AnimatedAction action) { - return BaseAnimationKey(unit.artName, action); + public static string BaseAnimationKey(MapUnit unit, MapUnit.AnimatedAction action) { + return BaseAnimationKey(unit.GetArtName(), action); } public static string AnimationKey(string baseKey, TileDirection direction) { return String.Format("{0}_{1}", baseKey, direction.ToString()); } - public static string AnimationKey(UnitPrototype unit, MapUnit.AnimatedAction action, TileDirection direction) { + public static string AnimationKey(MapUnit unit, MapUnit.AnimatedAction action, TileDirection direction) { return AnimationKey(BaseAnimationKey(unit, action), direction); } @@ -69,11 +69,11 @@ public IniData getINIData(string pathKey) { return tr; } - public static string GetUnitDefaultThumbnailKey(UnitPrototype unit) { - return $"{unit.artName}_{thumbnailDirection}_{thumbnailAction}_{thumbnailFrame}"; + public static string GetUnitDefaultThumbnailKey(MapUnit unit) { + return $"{unit.GetArtName()}_{thumbnailDirection}_{thumbnailAction}_{thumbnailFrame}"; } - public (ImageTexture baseFrame, ImageTexture tintFrame) GetAnimationFrameAndTintTextures(UnitPrototype unit) { + public (ImageTexture baseFrame, ImageTexture tintFrame) GetAnimationFrameAndTintTextures(MapUnit unit) { string key = GetUnitDefaultThumbnailKey(unit); @@ -112,9 +112,9 @@ public IniData getUnitINIData(string unitTypeName) { return getINIData(string.Format("Art/Units/{0}/{0}.INI", unitTypeName)); } - public string getUnitFlicFilepath(UnitPrototype unit, MapUnit.AnimatedAction action) { - string directory = string.Format("Art/Units/{0}", unit.artName); - IniData ini = getUnitINIData(unit.artName); + public string getUnitFlicFilepath(MapUnit unit, MapUnit.AnimatedAction action) { + string directory = string.Format("Art/Units/{0}", unit.GetArtName()); + IniData ini = getUnitINIData(unit.GetArtName()); string filename = getFlicFileName(ini, action); return directory.PathJoin(filename); } @@ -169,8 +169,8 @@ public static void loadFlicAnimation(string path, string name, ref SpriteFrames } } - public bool LoadAnimation(UnitPrototype unit, MapUnit.AnimatedAction action) { - string name = BaseAnimationKey(unit.artName, action); + public bool LoadAnimation(MapUnit unit, MapUnit.AnimatedAction action) { + string name = BaseAnimationKey(unit.GetArtName(), action); string testName = AnimationKey(name, TileDirection.NORTH); if (spriteFrames.HasAnimation(testName) && tintFrames.HasAnimation(testName)) { return false; @@ -210,7 +210,7 @@ public void playSound(string rootPath, IniData iniData, MapUnit.AnimatedAction a } } - public C7Animation forUnit(UnitPrototype unit, MapUnit.AnimatedAction action) { + public C7Animation forUnit(MapUnit unit, MapUnit.AnimatedAction action) { return new C7Animation(this, unit, action); } @@ -228,13 +228,13 @@ public partial class C7Animation { public AnimationManager animationManager { get; private set; } public string folderPath { get; private set; } // For example "Art/Units/Warrior" or "Art/Animations/Trajectory" public string iniFileName { get; private set; } - private UnitPrototype unit; + private MapUnit unit; public MapUnit.AnimatedAction action { get; private set; } - public C7Animation(AnimationManager civ3AnimData, UnitPrototype unit, MapUnit.AnimatedAction action) { + public C7Animation(AnimationManager civ3AnimData, MapUnit unit, MapUnit.AnimatedAction action) { this.animationManager = civ3AnimData; - this.folderPath = "Art/Units/" + unit.artName; - this.iniFileName = unit.artName + ".ini"; + this.folderPath = "Art/Units/" + unit.GetArtName(); + this.iniFileName = unit.GetArtName() + ".ini"; this.action = action; this.unit = unit; } diff --git a/C7/Animations/AnimationTracker.cs b/C7/Animations/AnimationTracker.cs index 9b58591c4..57a056db0 100644 --- a/C7/Animations/AnimationTracker.cs +++ b/C7/Animations/AnimationTracker.cs @@ -49,7 +49,7 @@ private void startAnimation(ID id, C7Animation anim, Action completionEvent, Ani } public void startAnimation(MapUnit unit, MapUnit.AnimatedAction action, Action completionEvent, AnimationEnding ending) { - startAnimation(unit.id, civ3AnimData.forUnit(unit.unitType, action), completionEvent, ending); + startAnimation(unit.id, civ3AnimData.forUnit(unit, action), completionEvent, ending); } public void startAnimation(Tile tile, AnimatedEffect effect, Action completionEvent, AnimationEnding ending) { diff --git a/C7/Lua/game_modes/base-ruleset.json b/C7/Lua/game_modes/base-ruleset.json index 204faf85d..251402984 100644 --- a/C7/Lua/game_modes/base-ruleset.json +++ b/C7/Lua/game_modes/base-ruleset.json @@ -766,14 +766,32 @@ "unitPrototypes": [ { "name": "Settler", - "artName": "Settler", + "art": { + "mainArt": { + "defaultName": "Settler", + "variations": { + "ERAS_Industrial_Age": "Settler Modern Times", + "ERAS_Modern_Era": "Settler Modern Times" + } + }, + "thumbnailArt": { + "defaultIndex": 0, + "variations": { + "ERAS_Industrial_Age": 72, + "ERAS_Modern_Era": 72 + } + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\00settlersmall.pcx", + "large": "art\\civilopedia\\icons\\units\\00settlerlarge.pcx" + } + }, "shieldCost": 30, "populationCost": 2, "attack": 0, "defense": 0, "bombard": 0, "movement": 1, - "iconIndex": 0, "producibleBy": [ "Rome", "Egypt", @@ -823,14 +841,33 @@ }, { "name": "Worker", - "artName": "Worker", + "art": { + "mainArt": { + "defaultName": "Worker", + "variations": { + "ERAS_Industrial_Age": "Worker Modern Times", + "ERAS_Modern_Era": "Worker Modern Times", + "SLAVE": "Enslaved Worker" + } + }, + "thumbnailArt": { + "defaultIndex": 1, + "variations": { + "ERAS_Industrial_Age": 73, + "ERAS_Modern_Era": 73 + } + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\01workersmall.pcx", + "large": "art\\civilopedia\\icons\\units\\01workerlarge.pcx" + } + }, "shieldCost": 10, "populationCost": 1, "attack": 0, "defense": 0, "bombard": 0, "movement": 1, - "iconIndex": 1, "producibleBy": [ "Rome", "Egypt", @@ -890,14 +927,24 @@ }, { "name": "Scout", - "artName": "Scout", + "art": { + "mainArt": { + "defaultName": "Scout" + }, + "thumbnailArt": { + "defaultIndex": 2 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\02scoutsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\02scoutlarge.pcx" + } + }, "shieldCost": 10, "populationCost": 0, "attack": 0, "defense": 0, "bombard": 0, "movement": 2, - "iconIndex": 2, "producibleBy": [ "Russia", "America", @@ -923,7 +970,18 @@ }, { "name": "Explorer", - "artName": "Explorer", + "art": { + "mainArt": { + "defaultName": "Explorer" + }, + "thumbnailArt": { + "defaultIndex": 3 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\03Explorersmall.pcx", + "large": "art\\civilopedia\\icons\\units\\03Explorerlarge.pcx" + } + }, "shieldCost": 20, "populationCost": 0, "requiredTech": "tech-33", @@ -931,7 +989,6 @@ "defense": 0, "bombard": 0, "movement": 2, - "iconIndex": 3, "producibleBy": [ "Rome", "Egypt", @@ -979,7 +1036,18 @@ }, { "name": "Marine", - "artName": "Marine", + "art": { + "mainArt": { + "defaultName": "Marine" + }, + "thumbnailArt": { + "defaultIndex": 4 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\04marinesmall.pcx", + "large": "art\\civilopedia\\icons\\units\\04marinelarge.pcx" + } + }, "shieldCost": 120, "populationCost": 0, "requiredTech": "tech-60", @@ -987,7 +1055,6 @@ "defense": 6, "bombard": 0, "movement": 1, - "iconIndex": 4, "producibleBy": [ "Rome", "Egypt", @@ -1039,7 +1106,18 @@ }, { "name": "Modern Paratrooper", - "artName": "Paratrooper", + "art": { + "mainArt": { + "defaultName": "Paratrooper" + }, + "thumbnailArt": { + "defaultIndex": 5 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\05paratroopersmall.pcx", + "large": "art\\civilopedia\\icons\\units\\05paratrooperlarge.pcx" + } + }, "shieldCost": 110, "populationCost": 0, "requiredTech": "tech-74", @@ -1047,7 +1125,6 @@ "defense": 11, "bombard": 0, "movement": 1, - "iconIndex": 5, "producibleBy": [ "Rome", "Egypt", @@ -1100,14 +1177,24 @@ }, { "name": "Warrior", - "artName": "Warrior", + "art": { + "mainArt": { + "defaultName": "Warrior" + }, + "thumbnailArt": { + "defaultIndex": 6 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\06warriorsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\06warriorlarge.pcx" + } + }, "shieldCost": 10, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 1, - "iconIndex": 6, "producibleBy": [ "A Barbarian Chiefdom", "Rome", @@ -1157,7 +1244,18 @@ }, { "name": "Archer", - "artName": "Archer", + "art": { + "mainArt": { + "defaultName": "Archer" + }, + "thumbnailArt": { + "defaultIndex": 7 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\07archersmall.pcx", + "large": "art\\civilopedia\\icons\\units\\07archerlarge.pcx" + } + }, "shieldCost": 20, "populationCost": 0, "requiredTech": "tech-6", @@ -1165,7 +1263,6 @@ "defense": 1, "bombard": 1, "movement": 1, - "iconIndex": 7, "producibleBy": [ "Rome", "Egypt", @@ -1213,7 +1310,18 @@ }, { "name": "Spearman", - "artName": "Spearman", + "art": { + "mainArt": { + "defaultName": "Spearman" + }, + "thumbnailArt": { + "defaultIndex": 8 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\08spearmansmall.pcx", + "large": "art\\civilopedia\\icons\\units\\08spearmanlarge.pcx" + } + }, "shieldCost": 20, "populationCost": 0, "requiredTech": "tech-1", @@ -1221,7 +1329,6 @@ "defense": 2, "bombard": 0, "movement": 1, - "iconIndex": 8, "producibleBy": [ "Rome", "Egypt", @@ -1267,7 +1374,18 @@ }, { "name": "Swordsman", - "artName": "Swordsman", + "art": { + "mainArt": { + "defaultName": "Swordsman" + }, + "thumbnailArt": { + "defaultIndex": 9 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\09swordsmansmall.pcx", + "large": "art\\civilopedia\\icons\\units\\09swordsmanlarge.pcx" + } + }, "shieldCost": 30, "populationCost": 0, "requiredTech": "tech-8", @@ -1275,7 +1393,6 @@ "defense": 2, "bombard": 0, "movement": 1, - "iconIndex": 9, "producibleBy": [ "Egypt", "Greece", @@ -1325,7 +1442,18 @@ }, { "name": "Chariot", - "artName": "chariot", + "art": { + "mainArt": { + "defaultName": "chariot" + }, + "thumbnailArt": { + "defaultIndex": 10 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\10chariotsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\10chariotlarge.pcx" + } + }, "shieldCost": 20, "populationCost": 0, "requiredTech": "tech-5", @@ -1333,7 +1461,6 @@ "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 10, "producibleBy": [ "Rome", "Greece", @@ -1384,7 +1511,18 @@ }, { "name": "Horseman", - "artName": "Horseman", + "art": { + "mainArt": { + "defaultName": "Horseman" + }, + "thumbnailArt": { + "defaultIndex": 11 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\11Horsemansmall.pcx", + "large": "art\\civilopedia\\icons\\units\\11horsemanlarge.pcx" + } + }, "shieldCost": 30, "populationCost": 0, "requiredTech": "tech-16", @@ -1392,7 +1530,6 @@ "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 11, "producibleBy": [ "A Barbarian Chiefdom", "Rome", @@ -1445,7 +1582,18 @@ }, { "name": "Pikeman", - "artName": "Pikeman", + "art": { + "mainArt": { + "defaultName": "Pikeman" + }, + "thumbnailArt": { + "defaultIndex": 12 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\12pikemansmall.pcx", + "large": "art\\civilopedia\\icons\\units\\12pikemanlarge.pcx" + } + }, "shieldCost": 30, "populationCost": 0, "requiredTech": "tech-23", @@ -1453,7 +1601,6 @@ "defense": 3, "bombard": 0, "movement": 1, - "iconIndex": 12, "producibleBy": [ "Rome", "Egypt", @@ -1503,7 +1650,18 @@ }, { "name": "Longbowman", - "artName": "Longbowman", + "art": { + "mainArt": { + "defaultName": "Longbowman" + }, + "thumbnailArt": { + "defaultIndex": 13 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\13longbowmansmall.pcx", + "large": "art\\civilopedia\\icons\\units\\13longbowmanlarge.pcx" + } + }, "shieldCost": 40, "populationCost": 0, "requiredTech": "tech-27", @@ -1511,7 +1669,6 @@ "defense": 1, "bombard": 2, "movement": 1, - "iconIndex": 13, "producibleBy": [ "Rome", "Egypt", @@ -1560,7 +1717,18 @@ }, { "name": "Musketman", - "artName": "Musketman", + "art": { + "mainArt": { + "defaultName": "Musketman" + }, + "thumbnailArt": { + "defaultIndex": 14 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\14musketmansmall.pcx", + "large": "art\\civilopedia\\icons\\units\\14musketmanlarge.pcx" + } + }, "shieldCost": 60, "populationCost": 0, "requiredTech": "tech-31", @@ -1568,7 +1736,6 @@ "defense": 4, "bombard": 0, "movement": 1, - "iconIndex": 14, "producibleBy": [ "Rome", "Egypt", @@ -1620,7 +1787,18 @@ }, { "name": "Knight", - "artName": "Knight", + "art": { + "mainArt": { + "defaultName": "Knight" + }, + "thumbnailArt": { + "defaultIndex": 15 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\15knightsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\15knightlarge.pcx" + } + }, "shieldCost": 70, "populationCost": 0, "requiredTech": "tech-26", @@ -1628,7 +1806,6 @@ "defense": 3, "bombard": 0, "movement": 2, - "iconIndex": 15, "producibleBy": [ "Rome", "Egypt", @@ -1677,7 +1854,18 @@ }, { "name": "Rifleman", - "artName": "Rifleman", + "art": { + "mainArt": { + "defaultName": "Rifleman" + }, + "thumbnailArt": { + "defaultIndex": 16 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\16riflemansmall.pcx", + "large": "art\\civilopedia\\icons\\units\\16riflemanlarge.pcx" + } + }, "shieldCost": 80, "populationCost": 0, "requiredTech": "tech-44", @@ -1685,7 +1873,6 @@ "defense": 6, "bombard": 0, "movement": 1, - "iconIndex": 16, "producibleBy": [ "Rome", "Egypt", @@ -1735,7 +1922,18 @@ }, { "name": "Cavalry", - "artName": "Cavalry", + "art": { + "mainArt": { + "defaultName": "Cavalry" + }, + "thumbnailArt": { + "defaultIndex": 17 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\17cavalrysmall.pcx", + "large": "art\\civilopedia\\icons\\units\\17cavalrylarge.pcx" + } + }, "shieldCost": 80, "populationCost": 0, "requiredTech": "tech-43", @@ -1743,7 +1941,6 @@ "defense": 3, "bombard": 0, "movement": 3, - "iconIndex": 17, "producibleBy": [ "Rome", "Egypt", @@ -1794,7 +1991,18 @@ }, { "name": "Infantry", - "artName": "Infantry", + "art": { + "mainArt": { + "defaultName": "Infantry" + }, + "thumbnailArt": { + "defaultIndex": 18 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\18infantrysmall.pcx", + "large": "art\\civilopedia\\icons\\units\\18infantrylarge.pcx" + } + }, "shieldCost": 90, "populationCost": 0, "requiredTech": "tech-58", @@ -1802,7 +2010,6 @@ "defense": 10, "bombard": 0, "movement": 1, - "iconIndex": 18, "producibleBy": [ "Rome", "Egypt", @@ -1855,7 +2062,18 @@ }, { "name": "Tank", - "artName": "Tank", + "art": { + "mainArt": { + "defaultName": "Tank" + }, + "thumbnailArt": { + "defaultIndex": 19 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\19shermantanksmall.pcx", + "large": "art\\civilopedia\\icons\\units\\19shermantanklarge.pcx" + } + }, "shieldCost": 100, "populationCost": 0, "requiredTech": "tech-63", @@ -1863,7 +2081,6 @@ "defense": 8, "bombard": 0, "movement": 2, - "iconIndex": 19, "producibleBy": [ "Rome", "Egypt", @@ -1916,7 +2133,18 @@ }, { "name": "Mech Infantry", - "artName": "Mech Infantry", + "art": { + "mainArt": { + "defaultName": "Mech Infantry" + }, + "thumbnailArt": { + "defaultIndex": 20 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\20mechanizedinfantrysmall.pcx", + "large": "art\\civilopedia\\icons\\units\\20mechanizedinfantrylarge.pcx" + } + }, "shieldCost": 110, "populationCost": 0, "requiredTech": "tech-67", @@ -1924,7 +2152,6 @@ "defense": 18, "bombard": 0, "movement": 2, - "iconIndex": 20, "producibleBy": [ "Rome", "Egypt", @@ -1977,7 +2204,18 @@ }, { "name": "Modern Armor", - "artName": "Modern Armor", + "art": { + "mainArt": { + "defaultName": "Modern Armor" + }, + "thumbnailArt": { + "defaultIndex": 21 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\21modernarmorsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\21modernarmorlarge.pcx" + } + }, "shieldCost": 120, "populationCost": 0, "requiredTech": "tech-74", @@ -1985,7 +2223,6 @@ "defense": 16, "bombard": 0, "movement": 3, - "iconIndex": 21, "producibleBy": [ "Rome", "Egypt", @@ -2038,7 +2275,18 @@ }, { "name": "Catapult", - "artName": "Catapult", + "art": { + "mainArt": { + "defaultName": "Catapult" + }, + "thumbnailArt": { + "defaultIndex": 22 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\22catapultsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\22catapultlarge.pcx" + } + }, "shieldCost": 20, "populationCost": 0, "requiredTech": "tech-11", @@ -2046,7 +2294,6 @@ "defense": 0, "bombard": 4, "movement": 1, - "iconIndex": 22, "producibleBy": [ "Rome", "Egypt", @@ -2097,7 +2344,18 @@ }, { "name": "Cannon", - "artName": "Cannon", + "art": { + "mainArt": { + "defaultName": "Cannon" + }, + "thumbnailArt": { + "defaultIndex": 23 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\23cannonsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\23cannonlarge.pcx" + } + }, "shieldCost": 40, "populationCost": 0, "requiredTech": "tech-39", @@ -2105,7 +2363,6 @@ "defense": 0, "bombard": 8, "movement": 1, - "iconIndex": 23, "producibleBy": [ "Rome", "Egypt", @@ -2159,7 +2416,18 @@ }, { "name": "Artillery", - "artName": "Artillery", + "art": { + "mainArt": { + "defaultName": "Artillery" + }, + "thumbnailArt": { + "defaultIndex": 24 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\24artillerysmall.pcx", + "large": "art\\civilopedia\\icons\\units\\24artillerylarge.pcx" + } + }, "shieldCost": 80, "populationCost": 0, "requiredTech": "tech-58", @@ -2167,7 +2435,6 @@ "defense": 0, "bombard": 12, "movement": 1, - "iconIndex": 24, "producibleBy": [ "Rome", "Egypt", @@ -2218,7 +2485,18 @@ }, { "name": "Radar Artillery", - "artName": "Radar Artillery", + "art": { + "mainArt": { + "defaultName": "Radar Artillery" + }, + "thumbnailArt": { + "defaultIndex": 25 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\25radarartillerysmall.pcx", + "large": "art\\civilopedia\\icons\\units\\25radarartillerylarge.pcx" + } + }, "shieldCost": 120, "populationCost": 0, "requiredTech": "tech-80", @@ -2226,7 +2504,6 @@ "defense": 0, "bombard": 16, "movement": 2, - "iconIndex": 25, "producibleBy": [ "Rome", "Egypt", @@ -2279,7 +2556,18 @@ }, { "name": "Cruise Missile", - "artName": "Cruise Missile", + "art": { + "mainArt": { + "defaultName": "Cruise Missile" + }, + "thumbnailArt": { + "defaultIndex": 26 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\26cruisemissilesmall.pcx", + "large": "art\\civilopedia\\icons\\units\\26cruisemissilelarge.pcx" + } + }, "shieldCost": 60, "populationCost": 0, "requiredTech": "tech-65", @@ -2287,7 +2575,6 @@ "defense": 0, "bombard": 16, "movement": 1, - "iconIndex": 26, "producibleBy": [ "Rome", "Egypt", @@ -2339,7 +2626,18 @@ }, { "name": "Tactical Nuke", - "artName": "Tactical Nuke", + "art": { + "mainArt": { + "defaultName": "Tactical Nuke" + }, + "thumbnailArt": { + "defaultIndex": 27 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\27icbmtacticalsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\27icbmtacticallarge.pcx" + } + }, "shieldCost": 300, "populationCost": 0, "requiredTech": "tech-69", @@ -2347,7 +2645,6 @@ "defense": 0, "bombard": 0, "movement": 1, - "iconIndex": 27, "producibleBy": [ "Rome", "Egypt", @@ -2401,7 +2698,18 @@ }, { "name": "ICBM", - "artName": "ICBM", + "art": { + "mainArt": { + "defaultName": "ICBM" + }, + "thumbnailArt": { + "defaultIndex": 28 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\28icbmsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\28icbmlarge.pcx" + } + }, "shieldCost": 500, "populationCost": 0, "requiredTech": "tech-75", @@ -2409,7 +2717,6 @@ "defense": 0, "bombard": 0, "movement": 1, - "iconIndex": 28, "producibleBy": [ "Rome", "Egypt", @@ -2462,7 +2769,18 @@ }, { "name": "Galley", - "artName": "Galley", + "art": { + "mainArt": { + "defaultName": "Galley" + }, + "thumbnailArt": { + "defaultIndex": 29 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\29galley(trireme)small.pcx", + "large": "art\\civilopedia\\icons\\units\\29galley(trireme)large.pcx" + } + }, "shieldCost": 30, "populationCost": 0, "requiredTech": "tech-15", @@ -2470,7 +2788,6 @@ "defense": 1, "bombard": 0, "movement": 3, - "iconIndex": 29, "producibleBy": [ "Rome", "Egypt", @@ -2519,7 +2836,18 @@ }, { "name": "Caravel", - "artName": "Caravel", + "art": { + "mainArt": { + "defaultName": "Caravel" + }, + "thumbnailArt": { + "defaultIndex": 30 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\30caravelsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\30caravellarge.pcx" + } + }, "shieldCost": 40, "populationCost": 0, "requiredTech": "tech-33", @@ -2527,7 +2855,6 @@ "defense": 2, "bombard": 0, "movement": 4, - "iconIndex": 30, "producibleBy": [ "Rome", "Egypt", @@ -2576,7 +2903,18 @@ }, { "name": "Frigate", - "artName": "Frigate", + "art": { + "mainArt": { + "defaultName": "Frigate" + }, + "thumbnailArt": { + "defaultIndex": 31 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\31frigatesmall.pcx", + "large": "art\\civilopedia\\icons\\units\\31frigatelarge.pcx" + } + }, "shieldCost": 60, "populationCost": 0, "requiredTech": "tech-42", @@ -2584,7 +2922,6 @@ "defense": 2, "bombard": 3, "movement": 5, - "iconIndex": 31, "producibleBy": [ "Rome", "Egypt", @@ -2637,7 +2974,18 @@ }, { "name": "Galleon", - "artName": "Galleon", + "art": { + "mainArt": { + "defaultName": "Galleon" + }, + "thumbnailArt": { + "defaultIndex": 32 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\32galleonsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\32galleonlarge.pcx" + } + }, "shieldCost": 50, "populationCost": 0, "requiredTech": "tech-42", @@ -2645,7 +2993,6 @@ "defense": 2, "bombard": 0, "movement": 4, - "iconIndex": 32, "producibleBy": [ "Rome", "Egypt", @@ -2695,7 +3042,18 @@ }, { "name": "Ironclad", - "artName": "Ironclad", + "art": { + "mainArt": { + "defaultName": "Ironclad" + }, + "thumbnailArt": { + "defaultIndex": 33 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\33ironcladsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\33ironcladlarge.pcx" + } + }, "shieldCost": 90, "populationCost": 0, "requiredTech": "tech-82", @@ -2703,7 +3061,6 @@ "defense": 6, "bombard": 6, "movement": 3, - "iconIndex": 33, "producibleBy": [ "Rome", "Egypt", @@ -2758,7 +3115,18 @@ }, { "name": "Transport", - "artName": "Transport", + "art": { + "mainArt": { + "defaultName": "Transport" + }, + "thumbnailArt": { + "defaultIndex": 34 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\34transportsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\34transportlarge.pcx" + } + }, "shieldCost": 100, "populationCost": 0, "requiredTech": "tech-57", @@ -2766,7 +3134,6 @@ "defense": 2, "bombard": 0, "movement": 6, - "iconIndex": 34, "producibleBy": [ "Rome", "Egypt", @@ -2818,7 +3185,18 @@ }, { "name": "Carrier", - "artName": "Carrier", + "art": { + "mainArt": { + "defaultName": "Carrier" + }, + "thumbnailArt": { + "defaultIndex": 35 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\35nimitzsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\35nimitzlarge.pcx" + } + }, "shieldCost": 180, "populationCost": 0, "requiredTech": "tech-61", @@ -2826,7 +3204,6 @@ "defense": 8, "bombard": 0, "movement": 7, - "iconIndex": 35, "producibleBy": [ "Rome", "Egypt", @@ -2878,7 +3255,18 @@ }, { "name": "Submarine", - "artName": "Submarine", + "art": { + "mainArt": { + "defaultName": "Submarine" + }, + "thumbnailArt": { + "defaultIndex": 36 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\36submarinesmall.pcx", + "large": "art\\civilopedia\\icons\\units\\36submarinelarge.pcx" + } + }, "shieldCost": 100, "populationCost": 0, "requiredTech": "tech-61", @@ -2886,7 +3274,6 @@ "defense": 4, "bombard": 0, "movement": 4, - "iconIndex": 36, "producibleBy": [ "Rome", "Egypt", @@ -2938,7 +3325,18 @@ }, { "name": "Destroyer", - "artName": "Destroyer", + "art": { + "mainArt": { + "defaultName": "Destroyer" + }, + "thumbnailArt": { + "defaultIndex": 37 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\37destroyersmall.pcx", + "large": "art\\civilopedia\\icons\\units\\37destroyerlarge.pcx" + } + }, "shieldCost": 120, "populationCost": 0, "requiredTech": "tech-57", @@ -2946,7 +3344,6 @@ "defense": 8, "bombard": 6, "movement": 8, - "iconIndex": 37, "producibleBy": [ "Rome", "Egypt", @@ -2999,7 +3396,18 @@ }, { "name": "Battleship", - "artName": "Battleship", + "art": { + "mainArt": { + "defaultName": "Battleship" + }, + "thumbnailArt": { + "defaultIndex": 38 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\38iowabattleshipsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\38iowabattleshiplarge.pcx" + } + }, "shieldCost": 200, "populationCost": 0, "requiredTech": "tech-61", @@ -3007,7 +3415,6 @@ "defense": 12, "bombard": 8, "movement": 5, - "iconIndex": 38, "producibleBy": [ "Rome", "Egypt", @@ -3060,7 +3467,18 @@ }, { "name": "AEGIS Cruiser", - "artName": "AEGIS Cruiser", + "art": { + "mainArt": { + "defaultName": "AEGIS Cruiser" + }, + "thumbnailArt": { + "defaultIndex": 39 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\39aegiscruisersmall.pcx", + "large": "art\\civilopedia\\icons\\units\\39aegiscruiserlarge.pcx" + } + }, "shieldCost": 160, "populationCost": 0, "requiredTech": "tech-80", @@ -3068,7 +3486,6 @@ "defense": 10, "bombard": 6, "movement": 7, - "iconIndex": 39, "producibleBy": [ "Rome", "Egypt", @@ -3122,7 +3539,18 @@ }, { "name": "Nuclear Submarine", - "artName": "Nuclear Submarine", + "art": { + "mainArt": { + "defaultName": "Nuclear Submarine" + }, + "thumbnailArt": { + "defaultIndex": 40 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\40nuclearsubmarinesmall.pcx", + "large": "art\\civilopedia\\icons\\units\\40nuclearsubmarinelarge.pcx" + } + }, "shieldCost": 140, "populationCost": 0, "requiredTech": "tech-66", @@ -3130,7 +3558,6 @@ "defense": 4, "bombard": 0, "movement": 5, - "iconIndex": 40, "producibleBy": [ "Rome", "Egypt", @@ -3182,7 +3609,18 @@ }, { "name": "Fighter", - "artName": "Fighter", + "art": { + "mainArt": { + "defaultName": "Fighter" + }, + "thumbnailArt": { + "defaultIndex": 41 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\41fightersmall.pcx", + "large": "art\\civilopedia\\icons\\units\\41fighterlarge.pcx" + } + }, "shieldCost": 80, "populationCost": 0, "requiredTech": "tech-59", @@ -3190,7 +3628,6 @@ "defense": 2, "bombard": 3, "movement": 1, - "iconIndex": 41, "producibleBy": [ "Rome", "Egypt", @@ -3241,7 +3678,18 @@ }, { "name": "Bomber", - "artName": "Bomber", + "art": { + "mainArt": { + "defaultName": "Bomber" + }, + "thumbnailArt": { + "defaultIndex": 42 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\42bombersmall.pcx", + "large": "art\\civilopedia\\icons\\units\\42bomberlarge.pcx" + } + }, "shieldCost": 100, "populationCost": 0, "requiredTech": "tech-59", @@ -3249,7 +3697,6 @@ "defense": 2, "bombard": 12, "movement": 1, - "iconIndex": 42, "producibleBy": [ "Rome", "Egypt", @@ -3299,7 +3746,18 @@ }, { "name": "Helicopter", - "artName": "Helicopter", + "art": { + "mainArt": { + "defaultName": "Helicopter" + }, + "thumbnailArt": { + "defaultIndex": 43 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\43transporthelicoptersmall.pcx", + "large": "art\\civilopedia\\icons\\units\\43transporthelicopterlarge.pcx" + } + }, "shieldCost": 100, "populationCost": 0, "requiredTech": "tech-64", @@ -3307,7 +3765,6 @@ "defense": 2, "bombard": 0, "movement": 1, - "iconIndex": 43, "producibleBy": [ "Rome", "Egypt", @@ -3358,7 +3815,18 @@ }, { "name": "Jet Fighter", - "artName": "Jet Fighter", + "art": { + "mainArt": { + "defaultName": "Jet Fighter" + }, + "thumbnailArt": { + "defaultIndex": 44 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\44jetfightersmall.pcx", + "large": "art\\civilopedia\\icons\\units\\44jetfighterlarge.pcx" + } + }, "shieldCost": 100, "populationCost": 0, "requiredTech": "tech-65", @@ -3366,7 +3834,6 @@ "defense": 4, "bombard": 3, "movement": 1, - "iconIndex": 44, "producibleBy": [ "Rome", "Egypt", @@ -3416,7 +3883,18 @@ }, { "name": "Stealth Fighter", - "artName": "Stealth Fighter", + "art": { + "mainArt": { + "defaultName": "Stealth Fighter" + }, + "thumbnailArt": { + "defaultIndex": 45 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\45stealthfightersmall.pcx", + "large": "art\\civilopedia\\icons\\units\\45stealthfighterlarge.pcx" + } + }, "shieldCost": 120, "populationCost": 0, "requiredTech": "tech-78", @@ -3424,7 +3902,6 @@ "defense": 6, "bombard": 6, "movement": 1, - "iconIndex": 45, "producibleBy": [ "Rome", "Egypt", @@ -3475,7 +3952,18 @@ }, { "name": "Stealth Bomber", - "artName": "Stealth Bomber", + "art": { + "mainArt": { + "defaultName": "Stealth Bomber" + }, + "thumbnailArt": { + "defaultIndex": 46 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\46stealthbombersmall.pcx", + "large": "art\\civilopedia\\icons\\units\\46stealthbomberlarge.pcx" + } + }, "shieldCost": 240, "populationCost": 0, "requiredTech": "tech-78", @@ -3483,7 +3971,6 @@ "defense": 5, "bombard": 18, "movement": 1, - "iconIndex": 46, "producibleBy": [ "Rome", "Egypt", @@ -3534,14 +4021,37 @@ }, { "name": "Leader", - "artName": "Leader Modern Times", + "art": { + "mainArt": { + "defaultName": "Leader Ancient Times", + "variations": { + "ERAS_Ancient_Times": "Leader Ancient Times", + "ERAS_Middle_Ages": "Leader Middle Ages", + "ERAS_Industrial_Age": "Leader Industrial Ages", + "ERAS_Modern_Era": "Leader Modern Times", + "SCI": "SciLeader" + } + }, + "thumbnailArt": { + "defaultIndex": 47, + "variations": { + "ERAS_Middle_Ages": 66, + "ERAS_Industrial_Age": 67, + "ERAS_Modern_Era": 68, + "SCI": 169 + } + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\47leadersmall.pcx", + "large": "art\\civilopedia\\icons\\units\\47leaderlarge.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 0, "defense": 0, "bombard": 0, "movement": 3, - "iconIndex": 47, "producibleBy": [ "Rome", "Egypt", @@ -3590,14 +4100,35 @@ }, { "name": "Army", - "artName": "Army Modern Times", + "art": { + "mainArt": { + "defaultName": "Army Ancient Times", + "variations": { + "ERAS_Ancient_Times": "Army Ancient Times", + "ERAS_Middle_Ages": "Army Middle Ages", + "ERAS_Industrial_Age": "Army Industrial Ages", + "ERAS_Modern_Era": "Army Modern Times" + } + }, + "thumbnailArt": { + "defaultIndex": 48, + "variations": { + "ERAS_Middle_Ages": 69, + "ERAS_Industrial_Age": 70, + "ERAS_Modern_Era": 71 + } + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\48armysmall.pcx", + "large": "art\\civilopedia\\icons\\units\\48armylarge.pcx" + } + }, "shieldCost": 400, "populationCost": 0, "attack": 0, "defense": 0, "bombard": 0, "movement": 1, - "iconIndex": 48, "producibleBy": [ "Rome", "Egypt", @@ -3646,7 +4177,18 @@ }, { "name": "Jaguar Warrior", - "artName": "Jaguar Warrior", + "art": { + "mainArt": { + "defaultName": "Jaguar Warrior" + }, + "thumbnailArt": { + "defaultIndex": 49 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\49aztecjaguarwarriorsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\49aztecJaguarwarriorlarge.pcx" + } + }, "shieldCost": 15, "populationCost": 0, "requiredTech": "tech-6", @@ -3654,7 +4196,6 @@ "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 49, "producibleBy": [ "Aztecs" ], @@ -3674,7 +4215,18 @@ }, { "name": "Bowman", - "artName": "Bowman", + "art": { + "mainArt": { + "defaultName": "Bowman" + }, + "thumbnailArt": { + "defaultIndex": 50 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\50bowman(babylonianarcher)small.pcx", + "large": "art\\civilopedia\\icons\\units\\50bowman(babylonianarcher)large.pcx" + } + }, "shieldCost": 20, "populationCost": 0, "requiredTech": "tech-6", @@ -3682,7 +4234,6 @@ "defense": 2, "bombard": 1, "movement": 1, - "iconIndex": 50, "producibleBy": [ "Babylon" ], @@ -3702,7 +4253,18 @@ }, { "name": "Hoplite", - "artName": "Hoplite", + "art": { + "mainArt": { + "defaultName": "Hoplite" + }, + "thumbnailArt": { + "defaultIndex": 51 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\51hoplite(greekphalanx)small.pcx", + "large": "art\\civilopedia\\icons\\units\\51hoplite(greekphalanx)large.pcx" + } + }, "shieldCost": 20, "populationCost": 0, "requiredTech": "tech-1", @@ -3710,7 +4272,6 @@ "defense": 3, "bombard": 0, "movement": 1, - "iconIndex": 51, "producibleBy": [ "Greece" ], @@ -3730,7 +4291,18 @@ }, { "name": "Impi", - "artName": "Impi", + "art": { + "mainArt": { + "defaultName": "Impi" + }, + "thumbnailArt": { + "defaultIndex": 52 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\52zuluspearmansmall.pcx", + "large": "art\\civilopedia\\icons\\units\\52zuluspearmanlarge.pcx" + } + }, "shieldCost": 20, "populationCost": 0, "requiredTech": "tech-1", @@ -3738,7 +4310,6 @@ "defense": 2, "bombard": 0, "movement": 2, - "iconIndex": 52, "producibleBy": [ "Zululand" ], @@ -3758,7 +4329,18 @@ }, { "name": "Legionary", - "artName": "Legionary", + "art": { + "mainArt": { + "defaultName": "Legionary" + }, + "thumbnailArt": { + "defaultIndex": 53 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\53romanlegionsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\53romanlegionlarge.pcx" + } + }, "shieldCost": 30, "populationCost": 0, "requiredTech": "tech-8", @@ -3766,7 +4348,6 @@ "defense": 3, "bombard": 0, "movement": 1, - "iconIndex": 53, "producibleBy": [ "Rome" ], @@ -3789,7 +4370,18 @@ }, { "name": "Immortals", - "artName": "Immortals", + "art": { + "mainArt": { + "defaultName": "Immortals" + }, + "thumbnailArt": { + "defaultIndex": 54 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\54immortalsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\54immortallarge.pcx" + } + }, "shieldCost": 30, "populationCost": 0, "requiredTech": "tech-8", @@ -3797,7 +4389,6 @@ "defense": 2, "bombard": 0, "movement": 1, - "iconIndex": 54, "producibleBy": [ "Persia" ], @@ -3820,7 +4411,18 @@ }, { "name": "War Chariot", - "artName": "War Chariot", + "art": { + "mainArt": { + "defaultName": "War Chariot" + }, + "thumbnailArt": { + "defaultIndex": 55 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\55egyptianchariotsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\55egyptianchariotlarge.pcx" + } + }, "shieldCost": 20, "populationCost": 0, "requiredTech": "tech-5", @@ -3828,7 +4430,6 @@ "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 55, "producibleBy": [ "Egypt" ], @@ -3851,7 +4452,18 @@ }, { "name": "Rider", - "artName": "Rider", + "art": { + "mainArt": { + "defaultName": "Rider" + }, + "thumbnailArt": { + "defaultIndex": 56 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\56chinesehorsemansmall.pcx", + "large": "art\\civilopedia\\icons\\units\\56chinesehorsemanlarge.pcx" + } + }, "shieldCost": 70, "populationCost": 0, "requiredTech": "tech-26", @@ -3859,7 +4471,6 @@ "defense": 3, "bombard": 0, "movement": 3, - "iconIndex": 56, "producibleBy": [ "China" ], @@ -3883,7 +4494,18 @@ }, { "name": "Mounted Warrior", - "artName": "Mounted Warrior", + "art": { + "mainArt": { + "defaultName": "Mounted Warrior" + }, + "thumbnailArt": { + "defaultIndex": 57 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\57horsearchersmall.pcx", + "large": "art\\civilopedia\\icons\\units\\57horsearcherlarge.pcx" + } + }, "shieldCost": 30, "populationCost": 0, "requiredTech": "tech-16", @@ -3891,7 +4513,6 @@ "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 57, "producibleBy": [ "Iroquois" ], @@ -3914,7 +4535,18 @@ }, { "name": "Musketeer", - "artName": "Musketeer", + "art": { + "mainArt": { + "defaultName": "Musketeer" + }, + "thumbnailArt": { + "defaultIndex": 58 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\58frenchmusketeersmall.pcx", + "large": "art\\civilopedia\\icons\\units\\58frenchmusketeerlarge.pcx" + } + }, "shieldCost": 60, "populationCost": 0, "requiredTech": "tech-31", @@ -3922,7 +4554,6 @@ "defense": 5, "bombard": 2, "movement": 1, - "iconIndex": 58, "producibleBy": [ "France" ], @@ -3945,7 +4576,18 @@ }, { "name": "Samurai", - "artName": "Samurai", + "art": { + "mainArt": { + "defaultName": "Samurai" + }, + "thumbnailArt": { + "defaultIndex": 59 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\59japaneseSamuraismall.pcx", + "large": "art\\civilopedia\\icons\\units\\59japanesesamurailarge.pcx" + } + }, "shieldCost": 70, "populationCost": 0, "requiredTech": "tech-26", @@ -3953,7 +4595,6 @@ "defense": 4, "bombard": 0, "movement": 2, - "iconIndex": 59, "producibleBy": [ "Japan" ], @@ -3976,7 +4617,18 @@ }, { "name": "War Elephant", - "artName": "War Elephant", + "art": { + "mainArt": { + "defaultName": "War Elephant" + }, + "thumbnailArt": { + "defaultIndex": 60 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\60warelephantsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\60warelephantlarge.pcx" + } + }, "shieldCost": 70, "populationCost": 0, "requiredTech": "tech-26", @@ -3984,7 +4636,6 @@ "defense": 3, "bombard": 0, "movement": 2, - "iconIndex": 60, "producibleBy": [ "India" ], @@ -4004,7 +4655,18 @@ }, { "name": "Cossack", - "artName": "Cossack", + "art": { + "mainArt": { + "defaultName": "Cossack" + }, + "thumbnailArt": { + "defaultIndex": 61 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\61russiancossacksmall.pcx", + "large": "art\\civilopedia\\icons\\units\\61russiancossacklarge.pcx" + } + }, "shieldCost": 90, "populationCost": 0, "requiredTech": "tech-43", @@ -4012,7 +4674,6 @@ "defense": 3, "bombard": 0, "movement": 3, - "iconIndex": 61, "producibleBy": [ "Russia" ], @@ -4035,7 +4696,18 @@ }, { "name": "Panzer", - "artName": "Panzer", + "art": { + "mainArt": { + "defaultName": "Panzer" + }, + "thumbnailArt": { + "defaultIndex": 62 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\62germanpanzersmall.pcx", + "large": "art\\civilopedia\\icons\\units\\62germanpanzerlarge.pcx" + } + }, "shieldCost": 100, "populationCost": 0, "requiredTech": "tech-63", @@ -4043,7 +4715,6 @@ "defense": 8, "bombard": 0, "movement": 3, - "iconIndex": 62, "producibleBy": [ "Germany" ], @@ -4067,7 +4738,18 @@ }, { "name": "Man-O-War", - "artName": "Man-O-War", + "art": { + "mainArt": { + "defaultName": "Man-O-War" + }, + "thumbnailArt": { + "defaultIndex": 63 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\63englishmanowarsmall.pcx", + "large": "art\\civilopedia\\icons\\units\\63englishmanowarlarge.pcx" + } + }, "shieldCost": 65, "populationCost": 0, "requiredTech": "tech-42", @@ -4075,7 +4757,6 @@ "defense": 2, "bombard": 4, "movement": 5, - "iconIndex": 63, "producibleBy": [ "England" ], @@ -4099,7 +4780,18 @@ }, { "name": "F-15", - "artName": "F-15", + "art": { + "mainArt": { + "defaultName": "F-15" + }, + "thumbnailArt": { + "defaultIndex": 64 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\64americanf15small.pcx", + "large": "art\\civilopedia\\icons\\units\\64americanf15large.pcx" + } + }, "shieldCost": 100, "populationCost": 0, "requiredTech": "tech-65", @@ -4107,7 +4799,6 @@ "defense": 4, "bombard": 6, "movement": 1, - "iconIndex": 64, "producibleBy": [ "America" ], @@ -4128,7 +4819,18 @@ }, { "name": "Privateer", - "artName": "Privateer", + "art": { + "mainArt": { + "defaultName": "Privateer" + }, + "thumbnailArt": { + "defaultIndex": 65 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\65privateersmall.pcx", + "large": "art\\civilopedia\\icons\\units\\65privateerlarge.pcx" + } + }, "shieldCost": 50, "populationCost": 0, "requiredTech": "tech-42", @@ -4136,7 +4838,6 @@ "defense": 1, "bombard": 3, "movement": 5, - "iconIndex": 65, "producibleBy": [ "Rome", "Egypt", @@ -4189,7 +4890,18 @@ }, { "name": "Keshik", - "artName": "Keshik", + "art": { + "mainArt": { + "defaultName": "Keshik" + }, + "thumbnailArt": { + "defaultIndex": 76 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_keshik civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_keshik civpedia lg.pcx" + } + }, "shieldCost": 60, "populationCost": 0, "requiredTech": "tech-26", @@ -4197,7 +4909,6 @@ "defense": 2, "bombard": 0, "movement": 2, - "iconIndex": 76, "producibleBy": [ "Mongols" ], @@ -4220,7 +4931,18 @@ }, { "name": "Conquistador", - "artName": "Conquistador", + "art": { + "mainArt": { + "defaultName": "Conquistador" + }, + "thumbnailArt": { + "defaultIndex": 75 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_conquist civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_conquist civpedia lg.pcx" + } + }, "shieldCost": 70, "populationCost": 0, "requiredTech": "tech-33", @@ -4228,7 +4950,6 @@ "defense": 2, "bombard": 0, "movement": 2, - "iconIndex": 75, "producibleBy": [ "Spain" ], @@ -4250,7 +4971,18 @@ }, { "name": "Berserk", - "artName": "Berserk", + "art": { + "mainArt": { + "defaultName": "Berserk" + }, + "thumbnailArt": { + "defaultIndex": 74 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_berserk civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_berserk civpedia lg.pcx" + } + }, "shieldCost": 70, "populationCost": 0, "requiredTech": "tech-27", @@ -4258,7 +4990,6 @@ "defense": 2, "bombard": 0, "movement": 1, - "iconIndex": 74, "producibleBy": [ "Scandinavia" ], @@ -4278,7 +5009,18 @@ }, { "name": "Sipahi", - "artName": "Sipahi", + "art": { + "mainArt": { + "defaultName": "Sipahi" + }, + "thumbnailArt": { + "defaultIndex": 77 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_sipahi civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_sipahi civpedia lg.pcx" + } + }, "shieldCost": 100, "populationCost": 0, "requiredTech": "tech-43", @@ -4286,7 +5028,6 @@ "defense": 3, "bombard": 0, "movement": 3, - "iconIndex": 77, "producibleBy": [ "Ottomans" ], @@ -4309,7 +5050,18 @@ }, { "name": "Gallic Swordsman", - "artName": "gallic swordsman", + "art": { + "mainArt": { + "defaultName": "gallic swordsman" + }, + "thumbnailArt": { + "defaultIndex": 78 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_gallic swordsman civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_gallic swordsman civpedia lg.pcx" + } + }, "shieldCost": 40, "populationCost": 0, "requiredTech": "tech-8", @@ -4317,7 +5069,6 @@ "defense": 2, "bombard": 0, "movement": 2, - "iconIndex": 78, "producibleBy": [ "Celts" ], @@ -4340,7 +5091,18 @@ }, { "name": "Ansar Warrior", - "artName": "ansar warrior", + "art": { + "mainArt": { + "defaultName": "ansar warrior" + }, + "thumbnailArt": { + "defaultIndex": 82 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Ansar Warrior civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Ansar Warrior civpedia lg.pcx" + } + }, "shieldCost": 60, "populationCost": 0, "requiredTech": "tech-26", @@ -4348,7 +5110,6 @@ "defense": 2, "bombard": 0, "movement": 3, - "iconIndex": 82, "producibleBy": [ "Arabia" ], @@ -4372,7 +5133,18 @@ }, { "name": "Numidian Mercenary", - "artName": "Libyan Mercenary", + "art": { + "mainArt": { + "defaultName": "Libyan Mercenary" + }, + "thumbnailArt": { + "defaultIndex": 80 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Libyan Mercenary civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Libyan Mercenary civpedia lg.pcx" + } + }, "shieldCost": 30, "populationCost": 0, "requiredTech": "tech-1", @@ -4380,7 +5152,6 @@ "defense": 3, "bombard": 0, "movement": 1, - "iconIndex": 80, "producibleBy": [ "Carthage" ], @@ -4400,7 +5171,18 @@ }, { "name": "Hwach\u0027a", - "artName": "Hwacha", + "art": { + "mainArt": { + "defaultName": "Hwacha" + }, + "thumbnailArt": { + "defaultIndex": 79 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Hwacha civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Hwacha civpedia lg.pcx" + } + }, "shieldCost": 40, "populationCost": 0, "requiredTech": "tech-39", @@ -4408,7 +5190,6 @@ "defense": 0, "bombard": 8, "movement": 1, - "iconIndex": 79, "producibleBy": [ "Korea" ], @@ -4432,7 +5213,18 @@ }, { "name": "Medieval Infantry", - "artName": "Medieval Infantry", + "art": { + "mainArt": { + "defaultName": "Medieval Infantry" + }, + "thumbnailArt": { + "defaultIndex": 84 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Medieval Infantry civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Medieval Infantry civpedia lg.pcx" + } + }, "shieldCost": 40, "populationCost": 0, "requiredTech": "tech-23", @@ -4440,7 +5232,6 @@ "defense": 2, "bombard": 0, "movement": 1, - "iconIndex": 84, "producibleBy": [ "Rome", "Egypt", @@ -4492,7 +5283,18 @@ }, { "name": "Guerilla", - "artName": "Guerilla", + "art": { + "mainArt": { + "defaultName": "Guerilla" + }, + "thumbnailArt": { + "defaultIndex": 85 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Guerilla civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Guerilla civpedia lg.pcx" + } + }, "shieldCost": 90, "populationCost": 0, "requiredTech": "tech-58", @@ -4500,7 +5302,6 @@ "defense": 6, "bombard": 3, "movement": 1, - "iconIndex": 85, "producibleBy": [ "Rome", "Egypt", @@ -4550,14 +5351,24 @@ }, { "name": "Princess", - "artName": "Princess", + "art": { + "mainArt": { + "defaultName": "Princess" + }, + "thumbnailArt": { + "defaultIndex": 121 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_princess civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_princess civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 0, "defense": 0, "bombard": 0, "movement": 1, - "iconIndex": 121, "producibleBy": [], "unproducible": true, "categories": [ @@ -4571,14 +5382,24 @@ }, { "name": "Lincoln", - "artName": "King American", + "art": { + "mainArt": { + "defaultName": "King American" + }, + "thumbnailArt": { + "defaultIndex": 97 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Abe civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Abe civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 97, "producibleBy": [], "unproducible": true, "categories": [ @@ -4594,14 +5415,24 @@ }, { "name": "Hammurabi", - "artName": "King Babylonian", + "art": { + "mainArt": { + "defaultName": "King Babylonian" + }, + "thumbnailArt": { + "defaultIndex": 100 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Hammurabi civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Hammurabi civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 100, "producibleBy": [], "unproducible": true, "categories": [ @@ -4617,14 +5448,24 @@ }, { "name": "Mao", - "artName": "King Chinese", + "art": { + "mainArt": { + "defaultName": "King Chinese" + }, + "thumbnailArt": { + "defaultIndex": 103 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Mao civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Mao civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 103, "producibleBy": [], "unproducible": true, "categories": [ @@ -4640,14 +5481,24 @@ }, { "name": "Bismarck", - "artName": "King German", + "art": { + "mainArt": { + "defaultName": "King German" + }, + "thumbnailArt": { + "defaultIndex": 107 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Bismarck civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Bismarck civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 107, "producibleBy": [], "unproducible": true, "categories": [ @@ -4663,14 +5514,24 @@ }, { "name": "Alexander", - "artName": "King Greek", + "art": { + "mainArt": { + "defaultName": "King Greek" + }, + "thumbnailArt": { + "defaultIndex": 108 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Alexander civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Alexander civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 108, "producibleBy": [], "unproducible": true, "categories": [ @@ -4686,14 +5547,24 @@ }, { "name": "Caesar", - "artName": "King Roman", + "art": { + "mainArt": { + "defaultName": "King Roman" + }, + "thumbnailArt": { + "defaultIndex": 116 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Caesar civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Caesar civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 116, "producibleBy": [], "unproducible": true, "categories": [ @@ -4709,14 +5580,24 @@ }, { "name": "Xerxes", - "artName": "King Persian", + "art": { + "mainArt": { + "defaultName": "King Persian" + }, + "thumbnailArt": { + "defaultIndex": 115 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Xerxes civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Xerxes civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 115, "producibleBy": [], "unproducible": true, "categories": [ @@ -4732,14 +5613,24 @@ }, { "name": "Hiawatha", - "artName": "King Iroquois", + "art": { + "mainArt": { + "defaultName": "King Iroquois" + }, + "thumbnailArt": { + "defaultIndex": 110 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Hiawatha civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Hiawatha civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 110, "producibleBy": [], "unproducible": true, "categories": [ @@ -4755,14 +5646,24 @@ }, { "name": "Shaka", - "artName": "King Zulu", + "art": { + "mainArt": { + "defaultName": "King Zulu" + }, + "thumbnailArt": { + "defaultIndex": 120 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Shaka civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Shaka civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 120, "producibleBy": [], "unproducible": true, "categories": [ @@ -4778,14 +5679,24 @@ }, { "name": "Montezuma", - "artName": "King Aztec", + "art": { + "mainArt": { + "defaultName": "King Aztec" + }, + "thumbnailArt": { + "defaultIndex": 99 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Montezuma civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Montezuma civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 99, "producibleBy": [], "unproducible": true, "categories": [ @@ -4801,14 +5712,24 @@ }, { "name": "Cleopatra", - "artName": "King Egyptian", + "art": { + "mainArt": { + "defaultName": "King Egyptian" + }, + "thumbnailArt": { + "defaultIndex": 104 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Cleopatra civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Cleopatra civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 104, "producibleBy": [], "unproducible": true, "categories": [ @@ -4824,14 +5745,24 @@ }, { "name": "Elizabeth", - "artName": "King English", + "art": { + "mainArt": { + "defaultName": "King English" + }, + "thumbnailArt": { + "defaultIndex": 105 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Elizabeth civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Elizabeth civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 105, "producibleBy": [], "unproducible": true, "categories": [ @@ -4847,14 +5778,24 @@ }, { "name": "Catherine", - "artName": "King Russian", + "art": { + "mainArt": { + "defaultName": "King Russian" + }, + "thumbnailArt": { + "defaultIndex": 117 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Catherine civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Catherine civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 117, "producibleBy": [], "unproducible": true, "categories": [ @@ -4870,14 +5811,24 @@ }, { "name": "Abu", - "artName": "King Arab", + "art": { + "mainArt": { + "defaultName": "King Arab" + }, + "thumbnailArt": { + "defaultIndex": 98 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Abu Bakr civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Abu Bakr civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 98, "producibleBy": [], "unproducible": true, "categories": [ @@ -4893,14 +5844,24 @@ }, { "name": "Hannibal", - "artName": "King Carthaginian", + "art": { + "mainArt": { + "defaultName": "King Carthaginian" + }, + "thumbnailArt": { + "defaultIndex": 101 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Hannibal civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Hannibal civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 101, "producibleBy": [], "unproducible": true, "categories": [ @@ -4916,14 +5877,24 @@ }, { "name": "Osman", - "artName": "King Ottoman", + "art": { + "mainArt": { + "defaultName": "King Ottoman" + }, + "thumbnailArt": { + "defaultIndex": 114 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Osman civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Osman civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 114, "producibleBy": [], "unproducible": true, "categories": [ @@ -4939,14 +5910,24 @@ }, { "name": "Temujin", - "artName": "King Mongol", + "art": { + "mainArt": { + "defaultName": "King Mongol" + }, + "thumbnailArt": { + "defaultIndex": 113 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Temujin civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Temujin civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 113, "producibleBy": [], "unproducible": true, "categories": [ @@ -4962,14 +5943,24 @@ }, { "name": "Gandhi", - "artName": "King Indian", + "art": { + "mainArt": { + "defaultName": "King Indian" + }, + "thumbnailArt": { + "defaultIndex": 109 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Gandhi civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Gandhi civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 109, "producibleBy": [], "unproducible": true, "categories": [ @@ -4985,14 +5976,24 @@ }, { "name": "Ragnar", - "artName": "King Viking", + "art": { + "mainArt": { + "defaultName": "King Viking" + }, + "thumbnailArt": { + "defaultIndex": 119 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Ragnar civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Ragnar civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 119, "producibleBy": [], "unproducible": true, "categories": [ @@ -5008,14 +6009,24 @@ }, { "name": "Brennus", - "artName": "King Celtic", + "art": { + "mainArt": { + "defaultName": "King Celtic" + }, + "thumbnailArt": { + "defaultIndex": 102 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Brennus civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Brennus civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 102, "producibleBy": [], "unproducible": true, "categories": [ @@ -5031,14 +6042,24 @@ }, { "name": "Tokugawa", - "artName": "King Japanese", + "art": { + "mainArt": { + "defaultName": "King Japanese" + }, + "thumbnailArt": { + "defaultIndex": 111 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Tokugawa civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Tokugawa civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 111, "producibleBy": [], "unproducible": true, "categories": [ @@ -5054,14 +6075,24 @@ }, { "name": "Joan d\u0027Arc", - "artName": "King French", + "art": { + "mainArt": { + "defaultName": "King French" + }, + "thumbnailArt": { + "defaultIndex": 106 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Joan civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Joan civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 106, "producibleBy": [], "unproducible": true, "categories": [ @@ -5077,14 +6108,24 @@ }, { "name": "Wang Kon", - "artName": "King Korean", + "art": { + "mainArt": { + "defaultName": "King Korean" + }, + "thumbnailArt": { + "defaultIndex": 112 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Wang civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Wang civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 112, "producibleBy": [], "unproducible": true, "categories": [ @@ -5100,14 +6141,24 @@ }, { "name": "Isabella", - "artName": "King Spanish", + "art": { + "mainArt": { + "defaultName": "King Spanish" + }, + "thumbnailArt": { + "defaultIndex": 118 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x_Isabella civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x_Isabella civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 118, "producibleBy": [], "unproducible": true, "categories": [ @@ -5123,14 +6174,24 @@ }, { "name": "Enkidu Warrior", - "artName": "Enkidu Warrior", + "art": { + "mainArt": { + "defaultName": "Enkidu Warrior" + }, + "thumbnailArt": { + "defaultIndex": 175 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x2_Endiku civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x2_Endiku civpedia lg.pcx" + } + }, "shieldCost": 10, "populationCost": 0, "attack": 1, "defense": 2, "bombard": 0, "movement": 1, - "iconIndex": 175, "producibleBy": [ "Sumeria" ], @@ -5150,7 +6211,18 @@ }, { "name": "Three-Man Chariot", - "artName": "Three Man Chariot", + "art": { + "mainArt": { + "defaultName": "Three Man Chariot" + }, + "thumbnailArt": { + "defaultIndex": 186 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\X2_3ManChariot civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\X2_3ManChariot civpedia lg.pcx" + } + }, "shieldCost": 30, "populationCost": 0, "requiredTech": "tech-5", @@ -5158,7 +6230,6 @@ "defense": 2, "bombard": 0, "movement": 2, - "iconIndex": 186, "producibleBy": [ "Hittites" ], @@ -5181,14 +6252,24 @@ }, { "name": "Mursilis", - "artName": "King Hatti", + "art": { + "mainArt": { + "defaultName": "King Hatti" + }, + "thumbnailArt": { + "defaultIndex": 169 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x2_Mursilis civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x2_Mursilis civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 169, "producibleBy": [], "unproducible": true, "categories": [ @@ -5204,14 +6285,24 @@ }, { "name": "Gilgamesh", - "artName": "King Sumeria", + "art": { + "mainArt": { + "defaultName": "King Sumeria" + }, + "thumbnailArt": { + "defaultIndex": 174 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x2_Gilgamesh civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x2_Gilgamesh civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 174, "producibleBy": [], "unproducible": true, "categories": [ @@ -5227,14 +6318,24 @@ }, { "name": "Henry", - "artName": "King Portugal", + "art": { + "mainArt": { + "defaultName": "King Portugal" + }, + "thumbnailArt": { + "defaultIndex": 173 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x2_Henry civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x2_Henry civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 173, "producibleBy": [], "unproducible": true, "categories": [ @@ -5250,7 +6351,18 @@ }, { "name": "Carrack", - "artName": "Carrack", + "art": { + "mainArt": { + "defaultName": "Carrack" + }, + "thumbnailArt": { + "defaultIndex": 198 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x2_carrack civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x2_carrack civpedia lg.pcx" + } + }, "shieldCost": 40, "populationCost": 0, "requiredTech": "tech-33", @@ -5258,7 +6370,6 @@ "defense": 2, "bombard": 0, "movement": 4, - "iconIndex": 198, "producibleBy": [ "Portugal" ], @@ -5278,7 +6389,18 @@ }, { "name": "Swiss Mercenary", - "artName": "Swiss Mercenary", + "art": { + "mainArt": { + "defaultName": "Swiss Mercenary" + }, + "thumbnailArt": { + "defaultIndex": 181 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x2_SwissMerc civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x2_SwissMerc civpedia lg.pcx" + } + }, "shieldCost": 30, "populationCost": 0, "requiredTech": "tech-23", @@ -5286,7 +6408,6 @@ "defense": 4, "bombard": 0, "movement": 1, - "iconIndex": 181, "producibleBy": [ "Netherlands" ], @@ -5309,14 +6430,24 @@ }, { "name": "William of Orange", - "artName": "King Netherlands", + "art": { + "mainArt": { + "defaultName": "King Netherlands" + }, + "thumbnailArt": { + "defaultIndex": 172 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x2_William civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x2_William civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 172, "producibleBy": [], "unproducible": true, "categories": [ @@ -5332,7 +6463,18 @@ }, { "name": "Trebuchet", - "artName": "Trebuchet", + "art": { + "mainArt": { + "defaultName": "Trebuchet" + }, + "thumbnailArt": { + "defaultIndex": 190 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x2_Trebuchet civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x2_Trebuchet civpedia lg.pcx" + } + }, "shieldCost": 30, "populationCost": 0, "requiredTech": "tech-24", @@ -5340,7 +6482,6 @@ "defense": 0, "bombard": 6, "movement": 1, - "iconIndex": 190, "producibleBy": [ "Rome", "Egypt", @@ -5391,14 +6532,24 @@ }, { "name": "Pachacuti", - "artName": "King Incan", + "art": { + "mainArt": { + "defaultName": "King Incan" + }, + "thumbnailArt": { + "defaultIndex": 170 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x2_Pachacuti civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x2_Pachacuti civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 170, "producibleBy": [], "unproducible": true, "categories": [ @@ -5414,14 +6565,24 @@ }, { "name": "Smoke-Jaguar", - "artName": "King Mayan", + "art": { + "mainArt": { + "defaultName": "King Mayan" + }, + "thumbnailArt": { + "defaultIndex": 171 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x2_SmokeJag civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x2_SmokeJag civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 171, "producibleBy": [], "unproducible": true, "categories": [ @@ -5437,14 +6598,24 @@ }, { "name": "Theodora", - "artName": "King Byzantines", + "art": { + "mainArt": { + "defaultName": "King Byzantines" + }, + "thumbnailArt": { + "defaultIndex": 168 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x2_Theodora civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x2_Theodora civpedia lg.pcx" + } + }, "shieldCost": 0, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 168, "producibleBy": [], "unproducible": true, "categories": [ @@ -5460,14 +6631,24 @@ }, { "name": "Chasqui Scout", - "artName": "Chasquis Scout", + "art": { + "mainArt": { + "defaultName": "Chasquis Scout" + }, + "thumbnailArt": { + "defaultIndex": 176 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x2_ChasquisScout civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x2_ChasquisScout civpedia lg.pcx" + } + }, "shieldCost": 20, "populationCost": 0, "attack": 1, "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 176, "producibleBy": [ "Inca" ], @@ -5487,7 +6668,18 @@ }, { "name": "Javelin Thrower", - "artName": "Javelin Thrower", + "art": { + "mainArt": { + "defaultName": "Javelin Thrower" + }, + "thumbnailArt": { + "defaultIndex": 177 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x2_JavelinThrower civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x2_JavelinThrower civpedia lg.pcx" + } + }, "shieldCost": 30, "populationCost": 0, "requiredTech": "tech-6", @@ -5495,7 +6687,6 @@ "defense": 2, "bombard": 0, "movement": 1, - "iconIndex": 177, "producibleBy": [ "Maya" ], @@ -5515,7 +6706,18 @@ }, { "name": "Dromon", - "artName": "Dromon", + "art": { + "mainArt": { + "defaultName": "Dromon" + }, + "thumbnailArt": { + "defaultIndex": 196 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x2_Dromon civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x2_Dromon civpedia lg.pcx" + } + }, "shieldCost": 30, "populationCost": 0, "requiredTech": "tech-15", @@ -5523,7 +6725,6 @@ "defense": 1, "bombard": 2, "movement": 3, - "iconIndex": 196, "producibleBy": [ "Byzantines" ], @@ -5544,7 +6745,18 @@ }, { "name": "Cruiser", - "artName": "Cruiser", + "art": { + "mainArt": { + "defaultName": "Cruiser" + }, + "thumbnailArt": { + "defaultIndex": 200 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x2_HvCruiser civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x2_HvCruiser civpedia lg.pcx" + } + }, "shieldCost": 160, "populationCost": 0, "requiredTech": "tech-57", @@ -5552,7 +6764,6 @@ "defense": 10, "bombard": 7, "movement": 6, - "iconIndex": 200, "producibleBy": [ "Rome", "Egypt", @@ -5606,14 +6817,24 @@ }, { "name": "Crusader", - "artName": "Crusader", + "art": { + "mainArt": { + "defaultName": "Crusader" + }, + "thumbnailArt": { + "defaultIndex": 180 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x2_Crusader civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x2_Crusader civpedia lg.pcx" + } + }, "shieldCost": 70, "populationCost": 0, "attack": 5, "defense": 3, "bombard": 0, "movement": 1, - "iconIndex": 180, "producibleBy": [], "unproducible": true, "categories": [ @@ -5633,14 +6854,24 @@ }, { "name": "Ancient Cavalry", - "artName": "Ancient Cavalry", + "art": { + "mainArt": { + "defaultName": "Ancient Cavalry" + }, + "thumbnailArt": { + "defaultIndex": 187 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x2_AncientCavalry civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x2_AncientCavalry civpedia lg.pcx" + } + }, "shieldCost": 40, "populationCost": 0, "attack": 3, "defense": 2, "bombard": 0, "movement": 2, - "iconIndex": 187, "producibleBy": [], "unproducible": true, "categories": [ @@ -5657,7 +6888,18 @@ }, { "name": "Curragh", - "artName": "Curragh", + "art": { + "mainArt": { + "defaultName": "Curragh" + }, + "thumbnailArt": { + "defaultIndex": 195 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x2_Curragh civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x2_Curragh civpedia lg.pcx" + } + }, "shieldCost": 15, "populationCost": 0, "requiredTech": "tech-3", @@ -5665,7 +6907,6 @@ "defense": 1, "bombard": 0, "movement": 2, - "iconIndex": 195, "upgradeTo": "Galley", "producibleBy": [ "Rome", @@ -5715,7 +6956,18 @@ }, { "name": "Paratrooper", - "artName": "WWII Paratrooper", + "art": { + "mainArt": { + "defaultName": "WWII Paratrooper" + }, + "thumbnailArt": { + "defaultIndex": 185 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\X2_WWIIParatrooper_sm.pcx", + "large": "art\\civilopedia\\icons\\units\\X2_WWIIParatrooper_lg.pcx" + } + }, "shieldCost": 90, "populationCost": 0, "requiredTech": "tech-64", @@ -5723,7 +6975,6 @@ "defense": 9, "bombard": 0, "movement": 1, - "iconIndex": 185, "producibleBy": [ "Rome", "Egypt", @@ -5777,7 +7028,18 @@ }, { "name": "TOW Infantry", - "artName": "TOW Infantry", + "art": { + "mainArt": { + "defaultName": "TOW Infantry" + }, + "thumbnailArt": { + "defaultIndex": 203 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x2_TOWinfantrry_civpedia sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x2_TOWinfantrry_civpedia lg.pcx" + } + }, "shieldCost": 120, "populationCost": 0, "requiredTech": "tech-65", @@ -5785,7 +7047,6 @@ "defense": 14, "bombard": 6, "movement": 1, - "iconIndex": 203, "producibleBy": [ "Rome", "Egypt", @@ -5834,7 +7095,18 @@ }, { "name": "Flak", - "artName": "Flak", + "art": { + "mainArt": { + "defaultName": "Flak" + }, + "thumbnailArt": { + "defaultIndex": 205 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\X2_20mmQuadFlak38_sm.pcx", + "large": "art\\civilopedia\\icons\\units\\X2_20mmQuadFlak38_lg.pcx" + } + }, "shieldCost": 70, "populationCost": 0, "requiredTech": "tech-59", @@ -5842,7 +7114,6 @@ "defense": 6, "bombard": 0, "movement": 1, - "iconIndex": 205, "producibleBy": [ "Rome", "Egypt", @@ -5892,7 +7163,18 @@ }, { "name": "Mobile SAM", - "artName": "Mobile SAM", + "art": { + "mainArt": { + "defaultName": "Mobile SAM" + }, + "thumbnailArt": { + "defaultIndex": 206 + }, + "pediaArt": { + "small": "art\\civilopedia\\icons\\units\\x2_MobileSAM sm.pcx", + "large": "art\\civilopedia\\icons\\units\\x2_MobileSAM lg.pcx" + } + }, "shieldCost": 100, "populationCost": 0, "requiredTech": "tech-65", @@ -5900,7 +7182,6 @@ "defense": 6, "bombard": 0, "movement": 2, - "iconIndex": 206, "producibleBy": [ "Rome", "Egypt", diff --git a/C7/Lua/game_modes/standalone.lua b/C7/Lua/game_modes/standalone.lua index 96213bd86..9629cd706 100644 --- a/C7/Lua/game_modes/standalone.lua +++ b/C7/Lua/game_modes/standalone.lua @@ -50,7 +50,11 @@ return function(civ3_game_mode) -- Only preserve a unit if we have an art replacement for it if replacement_art then - unit_prototype.artName = replacement_art + unit_prototype.art.mainArt.defaultName = replacement_art + + -- TODO: these are just placeholders until we have some proper art + unit_prototype.art.pediaArt.large = "art\\civilopedia\\icons\\units\\unit_large.png" + unit_prototype.art.pediaArt.small = "art\\civilopedia\\icons\\units\\unit_small.png" -- Remove the unit upgrade if we don't have a sprite for it local upgrade = unit_prototype.upgradeTo diff --git a/C7/Lua/texture_configs/civ3/unit_icons.lua b/C7/Lua/texture_configs/civ3/unit_icons.lua index f93dc321e..ef8782c6d 100644 --- a/C7/Lua/texture_configs/civ3/unit_icons.lua +++ b/C7/Lua/texture_configs/civ3/unit_icons.lua @@ -7,14 +7,32 @@ local unit_icons = { path = "Art/Units/units_32.pcx", }, } + +-- Context - ItemContext (UnitPrototype proto, Player player) +function unit_icons:map_object_to_sprite(context) + local proto = context.proto + local player = context.player -function unit_icons:map_object_to_sprite(unit_prototype) - if (unit_prototype:GetType().Name ~= "UnitPrototype") then + if (proto:GetType().Name ~= "UnitPrototype") then error "Expected a UnitPrototype object" end + if (player:GetType().Name ~= "Player") then + error "Expected a Player object" + end + + local index = proto.art.thumbnailArt.defaultIndex + + local variations = proto.art.thumbnailArt.variations + local key = player.eraCivilopediaName + + if (variations and variations[key]) then + index = variations[key] + end + + -- TODO: add SCI leader logic - local x = 1 + (ICON_WIDTH + 1) * (unit_prototype.iconIndex % ICONS_PER_ROW) - local y = 1 + (ICON_HEIGHT + 1) * math.floor(unit_prototype.iconIndex / ICONS_PER_ROW) + local x = 1 + (ICON_WIDTH + 1) * (index % ICONS_PER_ROW) + local y = 1 + (ICON_HEIGHT + 1) * math.floor(index / ICONS_PER_ROW) return { path = self.extra_data.path, diff --git a/C7/Map/UnitLayer.cs b/C7/Map/UnitLayer.cs index 799de418b..0d37cfaa7 100644 --- a/C7/Map/UnitLayer.cs +++ b/C7/Map/UnitLayer.cs @@ -115,10 +115,10 @@ public AnimationInstance getBlankAnimationInstance(LooseView looseView) { public void drawUnitAnimFrame(LooseView looseView, MapUnit unit, MapUnit.Appearance appearance, Vector2 tileCenter) { AnimationInstance inst = getBlankAnimationInstance(looseView); - C7Animation unitAnimation = looseView.mapView.game.animationController.civ3AnimData.forUnit(unit.unitType, appearance.action); + C7Animation unitAnimation = looseView.mapView.game.animationController.civ3AnimData.forUnit(unit, appearance.action); unitAnimation.loadSpriteAnimation(); - string animName = AnimationManager.AnimationKey(unit.unitType, appearance.action, appearance.direction); + string animName = AnimationManager.AnimationKey(unit, appearance.action, appearance.direction); Vector2 framePosition = GetFramePosition(appearance, unitAnimation, inst, animName, tileCenter); diff --git a/C7/UIElements/Advisors/TechBox.cs b/C7/UIElements/Advisors/TechBox.cs index 5e77dd36f..840e444a8 100644 --- a/C7/UIElements/Advisors/TechBox.cs +++ b/C7/UIElements/Advisors/TechBox.cs @@ -197,9 +197,8 @@ private List TechEffectTextures() { // Units foreach (UnitPrototype unit in Units[tech.id]) { - // TODO : load the correct textures - // ImageTexture texture = ... - // textures.Add(texture); + ImageTexture texture = TextureLoader.LoadByPath(unit.art.pediaArt.small); + textures.Add(texture); } // Buildings diff --git a/C7/UIElements/CityScreen/CityScreen.cs b/C7/UIElements/CityScreen/CityScreen.cs index adf8ba747..ef876ddb8 100644 --- a/C7/UIElements/CityScreen/CityScreen.cs +++ b/C7/UIElements/CityScreen/CityScreen.cs @@ -596,10 +596,11 @@ private void RenderProductionDetails(GameData gameData, City city) { int marginTop = 35; - if (city.itemBeingProduced is UnitPrototype up) { - AnimationManager animationManager = mapView.game.animationController.civ3AnimData.forUnit(up, MapUnit.AnimatedAction.DEFAULT).animationManager; + if (city.itemBeingProduced is UnitPrototype proto) { + var unit = proto.GetInstance(gameData.GenerateID(proto.name), proto, city.owner); + AnimationManager animationManager = mapView.game.animationController.civ3AnimData.forUnit(unit, MapUnit.AnimatedAction.DEFAULT).animationManager; ShaderMaterial material = PlayerTextureUtil.GetShaderMaterialForUnit(city.owner.GetPlayerColor()); - (ImageTexture baseImage, ImageTexture imageTint) = animationManager.GetAnimationFrameAndTintTextures(up); + (ImageTexture baseImage, ImageTexture imageTint) = animationManager.GetAnimationFrameAndTintTextures(unit); // Add the base sprite. Sprite2D baseImageSprite = new(); diff --git a/C7/UIElements/CityScreen/ProductionMenu.cs b/C7/UIElements/CityScreen/ProductionMenu.cs index 1aacdbd32..5f243c0c2 100644 --- a/C7/UIElements/CityScreen/ProductionMenu.cs +++ b/C7/UIElements/CityScreen/ProductionMenu.cs @@ -54,7 +54,7 @@ public void AddItems(GameData gameData, City city, Action choosePro } child.SetText(0, text); child.SetText(1, $"{buildTime} turns"); - child.SetIcon(0, RightClickChooseProductionMenu.GetProducibleIcon(option)); + child.SetIcon(0, RightClickChooseProductionMenu.GetProducibleIcon(option, city.owner)); child.SetCustomMinimumHeight(40); child.SetAutowrapMode(0, TextServer.AutowrapMode.WordSmart); tree.SetColumnTitleAlignment(1, HorizontalAlignment.Right); diff --git a/C7/UIElements/GameStatus/LowerRightInfoBox.cs b/C7/UIElements/GameStatus/LowerRightInfoBox.cs index aaec99b84..5d0905a0d 100644 --- a/C7/UIElements/GameStatus/LowerRightInfoBox.cs +++ b/C7/UIElements/GameStatus/LowerRightInfoBox.cs @@ -276,7 +276,7 @@ private void UpdateUnitGraphic(MapUnit unit) { return; } - string key = AnimationManager.GetUnitDefaultThumbnailKey(unit.unitType); + string key = AnimationManager.GetUnitDefaultThumbnailKey(unit); ImageTexture baseFrame = AnimationManager.AnimationThumbnails[key]; ImageTexture tintFrame = AnimationManager.AnimationTintThumbnails[key]; diff --git a/C7/UIElements/RightClickMenu.cs b/C7/UIElements/RightClickMenu.cs index 8a8e75e31..bde138547 100644 --- a/C7/UIElements/RightClickMenu.cs +++ b/C7/UIElements/RightClickMenu.cs @@ -287,9 +287,9 @@ public void ResetItems(Tile tile) { public partial class RightClickChooseProductionMenu : RightClickMenu { private ID cityID; - public static ImageTexture GetProducibleIcon(IProducible producible) { + public static ImageTexture GetProducibleIcon(IProducible producible, Player player) { if (producible is UnitPrototype proto) { - return TextureLoader.Load("unit_icons", proto, useCache: true); + return TextureLoader.Load("unit_icons", new ItemContext(proto, player), useCache: true); } else if (producible is Building b) { return TextureLoader.Load("building_icons.small", b, useCache: true); } else if (producible is Inflow inflow) { @@ -304,7 +304,7 @@ public RightClickChooseProductionMenu(Game game, City city) : base(game) { EngineStorage.ReadGameData((GameData gameData) => { foreach (IProducible option in city.ListProductionOptions(gameData)) { int buildTime = city.TurnsToProduce(option); - AddItem($"{option.name} ({buildTime} turns)", () => ChooseProduction(option.name), GetProducibleIcon(option)); + AddItem($"{option.name} ({buildTime} turns)", () => ChooseProduction(option.name), GetProducibleIcon(option, city.owner)); } }); } diff --git a/C7/UnitSelector.cs b/C7/UnitSelector.cs index 6be8664ad..46ecdf035 100644 --- a/C7/UnitSelector.cs +++ b/C7/UnitSelector.cs @@ -107,7 +107,7 @@ public bool SetSelectedUnit(MapUnit unit) { unit.wake(); NoMoreAutoselectableUnitsEmitted = false; ParameterWrapper wrappedUnit = new(CurrentlySelectedUnit); - PreLoadUnitAnimationThumbnail(wrappedUnit.Value.unitType); + PreLoadUnitAnimationThumbnail(wrappedUnit.Value); EmitSignal(SignalName.NewAutoselectedUnit, wrappedUnit); return true; } @@ -120,7 +120,7 @@ public bool SetSelectedUnit(MapUnit unit) { return false; } - private void PreLoadUnitAnimationThumbnail(UnitPrototype unit) { + private void PreLoadUnitAnimationThumbnail(MapUnit unit) { game.animationController.civ3AnimData.GetAnimationFrameAndTintTextures(unit); } } diff --git a/C7/Util.cs b/C7/Util.cs index 0ef13566a..99426ee26 100644 --- a/C7/Util.cs +++ b/C7/Util.cs @@ -107,7 +107,6 @@ public static void setModPath(string modPathParam) { /// Assumes Conquests/Complete /// /// The media path, e.g. Art/Units/units_32.pcx - /// The mod path for a scenario, e.g. RFRE /// The path to the media on the file system, or an exception if it cannot be found /// public static string Civ3MediaPath(string mediaPath) { diff --git a/C7Engine/AI/ChooseProducible.cs b/C7Engine/AI/ChooseProducible.cs index 102a3d217..74ac49694 100644 --- a/C7Engine/AI/ChooseProducible.cs +++ b/C7Engine/AI/ChooseProducible.cs @@ -78,10 +78,7 @@ private static float ScoreUnit(ProducibleStats stats, City city, Player player, // Create a fake version of this unit so we can check what AI we // would give it. - MapUnit temp = unit.GetInstance(EngineStorage.gameData); - temp.owner = player; - temp.nationality = player.civilization; - temp.location = city.location; + MapUnit temp = unit.GetInstance(EngineStorage.gameData.GenerateID(unit.name), unit, player, location: city.location); //////////////////////////////////////////////////////////////////// /// diff --git a/C7Engine/C7GameData/City.cs b/C7Engine/C7GameData/City.cs index 1405bdd0c..acfce357f 100644 --- a/C7Engine/C7GameData/City.cs +++ b/C7Engine/C7GameData/City.cs @@ -699,14 +699,10 @@ public void AddBuilding(Building building) { }); } - public void AddUnit(UnitPrototype prototype, GameData gameData) { - MapUnit newUnit = prototype.GetInstance(gameData); - newUnit.owner = owner; - newUnit.nationality = owner.civilization; - newUnit.location = location; + public void AddUnit(UnitPrototype proto, GameData gameData) { + MapUnit newUnit = proto.GetInstance(gameData.GenerateID(proto.name), proto, owner, location: location); newUnit.experienceLevelKey = gameData.defaultExperienceLevelKey; newUnit.experienceLevel = gameData.defaultExperienceLevel; - newUnit.facingDirection = TileDirection.SOUTHWEST; location.unitsOnTile.Add(newUnit); gameData.mapUnits.Add(newUnit); diff --git a/C7Engine/C7GameData/GameData.cs b/C7Engine/C7GameData/GameData.cs index 01e50854e..48e962f08 100644 --- a/C7Engine/C7GameData/GameData.cs +++ b/C7Engine/C7GameData/GameData.cs @@ -270,13 +270,10 @@ internal void RemoveUnit(MapUnit unit) { log.Information($"Player {owner} removed unit: {unit}"); } - internal void SpawnUnit(Player player, UnitPrototype unitType, Tile tile) { + internal void SpawnUnit(Player player, UnitPrototype proto, Tile tile) { // TODO: consolidate unit spawning routines (here) - MapUnit newUnit = unitType.GetInstance(this); - newUnit.location = tile; - newUnit.owner = player; - newUnit.nationality = player.civilization; + MapUnit newUnit = proto.GetInstance(this.GenerateID(proto.name), proto, player, location: tile); // TODO: make this a conscript. newUnit.experienceLevelKey = defaultExperienceLevelKey; newUnit.experienceLevel = defaultExperienceLevel; @@ -287,7 +284,7 @@ internal void SpawnUnit(Player player, UnitPrototype unitType, Tile tile) { player.units.Add(newUnit); log.Debug("New unit of type {type} added at {tile} for player {player}", - unitType.name, tile, player); + proto.name, tile, player); } public int TechCostFor(Tech tech, Player player) { @@ -383,4 +380,10 @@ private bool ResolveTileOwnershipConflict(City a, City b, Tile t, out City owner throw new Exception($"Failed to resolve ownership of {t} between {a.name} and {b.name}, something went wrong"); } } + + public static class GameDataUtils { + public static ID GenerateID(this GameData gameData, string identifier) { + return gameData.ids.CreateID(identifier); + } + } } diff --git a/C7Engine/C7GameData/ImportCiv3.cs b/C7Engine/C7GameData/ImportCiv3.cs index 797bd951d..2babfd5cd 100644 --- a/C7Engine/C7GameData/ImportCiv3.cs +++ b/C7Engine/C7GameData/ImportCiv3.cs @@ -1139,14 +1139,20 @@ private void ImportUnitPrototypes() { } prototype.name = prto.Name; - prototype.artName = pediaIcons.GetUnitArtName(prto.CivilopediaEntry); + + Art unitArt = new Art(); + unitArt.mainArt = pediaIcons.GetUnitMainArt(prto.CivilopediaEntry); + unitArt.thumbnailArt = pediaIcons.GetUnitThumbnailArt(prto.CivilopediaEntry, prto.IconIndex); + unitArt.pediaArt = pediaIcons.GetUnitCivilopediaArt(prto.CivilopediaEntry); + prototype.art = unitArt; + prototype.attack = prto.Attack; prototype.defense = prto.Defense; prototype.movement = prto.Movement; prototype.shieldCost = prto.ShieldCost; prototype.populationCost = prto.PopulationCost; prototype.bombard = prto.BombardStrength; - prototype.iconIndex = prto.IconIndex; + prototype.actions.UnionWith(GetUnitActions(prto)); prototype.terraformActions.UnionWith(GetUnitTerraforms(prto).Select(tfKey => terraformIdByCiv3Key[tfKey])); diff --git a/C7Engine/C7GameData/MapUnit.cs b/C7Engine/C7GameData/MapUnit.cs index b7d721ee7..5e33e8dd5 100644 --- a/C7Engine/C7GameData/MapUnit.cs +++ b/C7Engine/C7GameData/MapUnit.cs @@ -100,6 +100,23 @@ public string GetDisplayName() { return this.IsCaptive() ? $"{this.name} ({this.nationality.name})" : this.name; } + // TODO: best move this to lua at some point + public string GetArtName() { + if (this.unitType.art.mainArt.variations != null) { + if (this.unitType.isWorker && this.IsCaptive()) { + if (this.unitType.art.mainArt.variations.FirstOrDefault(s => s.Key.EndsWith("SLAVE")).Value != null) + return this.unitType.art.mainArt.variations.First(s => s.Key.EndsWith("SLAVE")).Value; + } + + if (this.unitType.art.mainArt.variations.TryGetValue($"{this.owner.eraCivilopediaName}", out var value)) + return value; + + //TODO: add military + science leader variation + } + + return this.unitType.art.mainArt.defaultName; + } + public string Describe() { UnitPrototype type = this.unitType; string exp = this.HasRank() ? $"{this.experienceLevel.displayName}" : ""; diff --git a/C7Engine/C7GameData/PediaIcons.cs b/C7Engine/C7GameData/PediaIcons.cs index 4513ae7ae..861331354 100644 --- a/C7Engine/C7GameData/PediaIcons.cs +++ b/C7Engine/C7GameData/PediaIcons.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using Serilog; namespace C7GameData { @@ -28,6 +29,11 @@ class PediaIcons { // building icon art file. public readonly Dictionary buildingToRowNumberMapping = new(); + private readonly Dictionary civilopediaLargeIcons = new(); + private readonly Dictionary civilopediaSmallIcons = new(); + + private readonly Dictionary unitSmallIconsIndex = new(); + private readonly string pediaIconsPath; public PediaIcons(string path) { @@ -38,16 +44,10 @@ public PediaIcons(string path) { for (int i = 0; i < lines.Length - 1; ++i) { if (lines[i].StartsWith(animNamePrefix)) { string civilopediaName = lines[i].Substring(animNamePrefix.Length); - if (civilopediaName.Contains("_ERAS_")) { - // HACK: The civilopedia name for leaders differs by era, but the current - // approach for resolving the artwork is era independent. Given a line like - // #ANIMNAME_PRTO_Leader_ERAS_Ancient_Times we want to end up with - // PRTO_Leader to match the biq file. - civilopediaName = civilopediaName.Substring(0, civilopediaName.IndexOf("_ERAS_")); - } string artName = lines[i + 1]; - unitArtMapping[civilopediaName] = artName; + unitArtMapping.TryAdd(civilopediaName, artName); + continue; } @@ -69,6 +69,15 @@ public PediaIcons(string path) { // support that yet. buildingToRowNumberMapping[lines[i].Substring(6)] = Int32.Parse(lines[i + 2]); } + + if (lines[i].StartsWith("#UNITICON_PRTO") && i + 1 < lines.Length) { + unitSmallIconsIndex[lines[i].Substring(10)] = Int32.Parse(lines[i + 1]); + } + + if (lines[i].StartsWith("#ICON_PRTO") && i + 2 < lines.Length) { + civilopediaLargeIcons[lines[i].Substring(6)] = lines[i + 1]; + civilopediaSmallIcons[lines[i].Substring(6)] = lines[i + 2]; + } } } @@ -76,13 +85,39 @@ public string GetTechIconPath(string civilopediaEntry) { return techSmallIconMapping[civilopediaEntry]; } - public string GetUnitArtName(string civilopediaEntry) { - string artName = unitArtMapping[civilopediaEntry]; - if (artName == null) { - log.Error($"Could not find #ANIMNAME_{civilopediaEntry} in PediaIcons file '{pediaIconsPath}"); - return "Warrior"; + public MainArt GetUnitMainArt(string civilopediaEntry) { + if (!unitArtMapping.TryGetValue(civilopediaEntry, out string artName)) { + log.Warning($"Could not find #ANIMNAME_{civilopediaEntry} in PediaIcons file '{pediaIconsPath}"); + artName = unitArtMapping.First(e => e.Key.StartsWith(civilopediaEntry)).Value; + artName = artName.Replace($"{civilopediaEntry}_", ""); } - return artName; + + var variations = unitArtMapping + .Where(e => e.Key != civilopediaEntry && e.Key.StartsWith(civilopediaEntry)) + .ToDictionary(e => e.Key.Replace($"{civilopediaEntry}_", ""), e => e.Value); + + return new MainArt() { + defaultName = artName, + variations = variations.Count > 0 ? variations : null, + }; + } + + public ThumbNailArt GetUnitThumbnailArt(string civilopediaEntry, int index) { + var variations = unitSmallIconsIndex + .Where(e => e.Key != civilopediaEntry && e.Key.StartsWith(civilopediaEntry)) + .ToDictionary(e => e.Key.Replace($"{civilopediaEntry}_", ""), e => e.Value); + + return new ThumbNailArt() { + defaultIndex = index, + variations = variations.Count > 0 ? variations : null, + }; + } + + public PediaArt GetUnitCivilopediaArt(string civilopediaEntry) { + return new PediaArt() { + large = civilopediaLargeIcons[civilopediaEntry], + small = civilopediaSmallIcons[civilopediaEntry], + }; } public string GetLeaderArtName(string civilopediaEntry) { diff --git a/C7Engine/C7GameData/Save/SaveUnitPrototype.cs b/C7Engine/C7GameData/Save/SaveUnitPrototype.cs index fc2b18299..1be0486c0 100644 --- a/C7Engine/C7GameData/Save/SaveUnitPrototype.cs +++ b/C7Engine/C7GameData/Save/SaveUnitPrototype.cs @@ -4,7 +4,7 @@ namespace C7GameData.Save { public class SaveUnitPrototype { public string name { get; set; } - public string artName { get; set; } + public Art art { get; set; } public int shieldCost { get; set; } public int populationCost { get; set; } public ID requiredTech { get; set; } @@ -12,7 +12,6 @@ public class SaveUnitPrototype { public int defense { get; set; } public int bombard { get; set; } public int movement { get; set; } - public int iconIndex { get; set; } public HashSet producibleBy = []; @@ -32,10 +31,10 @@ public class SaveUnitPrototype { public SaveUnitPrototype() { } public SaveUnitPrototype(UnitPrototype proto) { - (name, artName, shieldCost, populationCost, unproducible, - attack, defense, bombard, movement, iconIndex) = - (proto.name, proto.artName, proto.shieldCost, proto.populationCost, proto.unproducible, - proto.attack, proto.defense, proto.bombard, proto.movement, proto.iconIndex); + (name, art, shieldCost, populationCost, unproducible, + attack, defense, bombard, movement) = + (proto.name, proto.art, proto.shieldCost, proto.populationCost, proto.unproducible, + proto.attack, proto.defense, proto.bombard, proto.movement); if (proto.requiredTech != null) requiredTech = proto.requiredTech.id; diff --git a/C7Engine/C7GameData/UnitPrototype.cs b/C7Engine/C7GameData/UnitPrototype.cs index f4390dd82..9e6ae4c50 100644 --- a/C7Engine/C7GameData/UnitPrototype.cs +++ b/C7Engine/C7GameData/UnitPrototype.cs @@ -18,14 +18,41 @@ public enum UnitAction { Automate } + public struct ItemContext(UnitPrototype proto, Player player) { + public UnitPrototype proto = proto; + public Player player = player; + } + + // A container for all the art for this unit + public struct Art { + public MainArt mainArt; + public ThumbNailArt thumbnailArt; + public PediaArt pediaArt; + } + + // the main art contains the Animation art folder path for the unit + public struct MainArt { + public string defaultName; + public Dictionary variations; + } + // the thumbnail art contains the index to the small unit icons used in city screen production, etc + public struct ThumbNailArt { + public int defaultIndex; + public Dictionary variations; + } + // the icons being used by the civilopedia and also other places like the Science Advisor + public struct PediaArt { + public string small; + public string large; + } + /** * The prototype for a unit, which defines the characteristics of a unit. * For example, a Spearman might have 1 attack, 2 defense, and 1 movement. **/ public class UnitPrototype : IProducible { public string name { get; set; } - // The name to use when searching for animations for this unit. - public string artName { get; set; } + public Art art { get; set; } public int shieldCost { get; set; } public int populationCost { get; set; } public Tech requiredTech { get; set; } @@ -33,9 +60,7 @@ public class UnitPrototype : IProducible { public int defense { get; set; } public int bombard { get; set; } public int movement { get; set; } - public int iconIndex { get; set; } public HashSet producibleBy { get; set; } = []; - public UnitPrototype upgradeTo; public bool unproducible; @@ -54,9 +79,9 @@ public class UnitPrototype : IProducible { public UnitPrototype() { } public UnitPrototype(SaveUnitPrototype proto, IEnumerable terraforms) { - (name, artName, shieldCost, populationCost, attack, defense, bombard, movement, iconIndex, unproducible) = - (proto.name, proto.artName, proto.shieldCost, proto.populationCost, - proto.attack, proto.defense, proto.bombard, proto.movement, proto.iconIndex, proto.unproducible); + (name, art, shieldCost, populationCost, attack, defense, bombard, movement, unproducible) = + (proto.name, proto.art, proto.shieldCost, proto.populationCost, + proto.attack, proto.defense, proto.bombard, proto.movement, proto.unproducible); categories = new HashSet(proto.categories); actions = proto.actions; @@ -93,11 +118,18 @@ public double BaseStrength(CombatRole role) { } } - public MapUnit GetInstance(GameData gameData) { - MapUnit instance = new MapUnit(gameData.ids.CreateID(this.name)); - instance.unitType = this; - instance.name = this.name; - instance.hitPointsRemaining = 3; //todo: make this configurable + public MapUnit GetInstance(ID id, UnitPrototype proto, Player owner, Civilization nationality = null, Tile location = null, TileDirection facingDirection = TileDirection.SOUTHWEST, int hitPoints = 3) { + MapUnit instance = new MapUnit(id); + instance.unitType = proto; + instance.name = proto.name; + instance.hitPointsRemaining = hitPoints; //todo: make this configurable + instance.owner = owner; + if (nationality != null) + instance.nationality = nationality; + else + instance.nationality = owner.civilization; + instance.location = location; + instance.movementPoints.reset(movement); return instance; }