diff --git a/android/Images/ImprovementIcons/Offshore Platform.png b/android/Images/ImprovementIcons/Offshore Platform.png new file mode 100644 index 0000000000..84d6419415 Binary files /dev/null and b/android/Images/ImprovementIcons/Offshore Platform.png differ diff --git a/android/assets/game.atlas b/android/assets/game.atlas index af481c51f1..812cb4fc1d 100644 --- a/android/assets/game.atlas +++ b/android/assets/game.atlas @@ -6,4557 +6,4564 @@ filter: MipMapLinearLinear, MipMapLinearLinear repeat: none EmojiIcons/Culture rotate: false - xy: 1948, 1236 + xy: 1142, 999 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Faith rotate: false - xy: 768, 557 + xy: 1590, 1238 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Food rotate: false - xy: 826, 557 + xy: 1764, 1238 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Gold rotate: false - xy: 1358, 1178 + xy: 1474, 1180 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Happiness rotate: false - xy: 1532, 1178 + xy: 1648, 1180 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Production rotate: false - xy: 718, 495 + xy: 942, 551 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Science rotate: false - xy: 884, 607 + xy: 1058, 601 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Turn rotate: false - xy: 834, 383 + xy: 844, 377 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 ImprovementIcons/Academy rotate: false - xy: 4, 1044 + xy: 4, 1046 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Ancient ruins rotate: false - xy: 4, 828 + xy: 4, 830 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Barbarian encampment rotate: false - xy: 4, 396 + xy: 4, 398 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Camp rotate: false - xy: 1362, 1942 + xy: 1362, 1944 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Citadel rotate: false - xy: 1902, 1942 + xy: 1902, 1944 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/City center rotate: false - xy: 590, 1834 + xy: 590, 1836 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/City ruins rotate: false - xy: 698, 1834 + xy: 698, 1836 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Customs house rotate: false - xy: 112, 936 + xy: 112, 938 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Farm rotate: false - xy: 397, 1540 + xy: 397, 1542 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Fishing Boats rotate: false - xy: 505, 1618 + xy: 505, 1620 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Fort rotate: false - xy: 829, 1726 + xy: 829, 1728 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Holy site rotate: false - xy: 1477, 1726 + xy: 1477, 1728 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Landmark rotate: false - xy: 1261, 1510 + xy: 1261, 1512 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Lumber mill rotate: false - xy: 1585, 1510 + xy: 1585, 1512 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Manufactory rotate: false - xy: 1801, 1510 + xy: 1801, 1512 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Mine rotate: false - xy: 1149, 1402 + xy: 1149, 1404 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Moai rotate: false - xy: 1257, 1402 + xy: 1257, 1404 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +ImprovementIcons/Offshore Platform + rotate: false + xy: 220, 948 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Oil well rotate: false - xy: 220, 838 + xy: 220, 732 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Pasture rotate: false - xy: 220, 514 + xy: 220, 408 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Plantation rotate: false - xy: 298, 1216 + xy: 328, 1110 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Polder rotate: false - xy: 328, 1108 + xy: 328, 1002 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Quarry rotate: false - xy: 328, 352 + xy: 328, 246 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Road rotate: false - xy: 1054, 1294 + xy: 1162, 1296 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Terrace farm rotate: false - xy: 976, 1186 + xy: 436, 540 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Trading post rotate: false - xy: 868, 970 + xy: 976, 1080 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/America rotate: false - xy: 714, 1942 + xy: 714, 1944 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Arabia rotate: false - xy: 822, 1942 + xy: 822, 1944 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Austria rotate: false - xy: 930, 1942 + xy: 930, 1944 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Aztecs rotate: false - xy: 4, 612 + xy: 4, 614 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Babylon rotate: false - xy: 1038, 1942 + xy: 1038, 1944 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Byzantium rotate: false - xy: 4, 288 + xy: 4, 290 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Carthage rotate: false - xy: 4, 180 + xy: 4, 182 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Celts rotate: false - xy: 4, 72 + xy: 4, 74 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/China rotate: false - xy: 1686, 1942 + xy: 1686, 1944 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/CityState rotate: false - xy: 1022, 1834 + xy: 1022, 1836 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Denmark rotate: false - xy: 112, 720 + xy: 112, 722 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Egypt rotate: false - xy: 112, 180 + xy: 112, 182 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/England rotate: false - xy: 112, 72 + xy: 112, 74 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Ethiopia rotate: false - xy: 289, 1648 + xy: 289, 1650 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/France rotate: false - xy: 937, 1726 + xy: 937, 1728 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Germany rotate: false - xy: 1045, 1618 + xy: 1045, 1620 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Greece rotate: false - xy: 1261, 1726 + xy: 1261, 1728 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Inca rotate: false - xy: 1693, 1726 + xy: 1693, 1728 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/India rotate: false - xy: 1801, 1726 + xy: 1801, 1728 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Iroquois rotate: false - xy: 1909, 1726 + xy: 1909, 1728 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Japan rotate: false - xy: 613, 1510 + xy: 613, 1512 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Korea rotate: false - xy: 1045, 1510 + xy: 1045, 1512 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Mongolia rotate: false - xy: 1473, 1402 + xy: 1473, 1404 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Persia rotate: false - xy: 220, 82 + xy: 298, 1326 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Polynesia rotate: false - xy: 328, 1000 + xy: 328, 894 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Rome rotate: false - xy: 1162, 1294 + xy: 1270, 1296 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Russia rotate: false - xy: 1270, 1294 + xy: 1378, 1296 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Siam rotate: false - xy: 544, 1186 + xy: 436, 972 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Songhai rotate: false - xy: 544, 970 + xy: 652, 1080 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Spain rotate: false - xy: 652, 1078 + xy: 760, 1188 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/Sweden rotate: false - xy: 652, 868 + xy: 760, 978 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/The Huns rotate: false - xy: 436, 538 + xy: 544, 648 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/The Maya rotate: false - xy: 544, 646 + xy: 652, 756 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/The Netherlands rotate: false - xy: 652, 760 + xy: 760, 870 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 NationIcons/The Ottomans rotate: false - xy: 760, 862 + xy: 868, 972 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Aircraft rotate: false - xy: 976, 889 + xy: 1084, 999 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 OtherIcons/ArrowRight rotate: false - xy: 436, 264 + xy: 544, 374 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 StatIcons/Movement rotate: false - xy: 436, 264 + xy: 544, 374 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 OtherIcons/BackArrow rotate: false - xy: 544, 439 + xy: 652, 549 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 OtherIcons/Banner rotate: false - xy: 1146, 1942 + xy: 1146, 1944 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Camera rotate: false - xy: 856, 350 + xy: 676, 44 size: 25, 25 orig: 25, 25 offset: 0, 0 index: -1 OtherIcons/Checkmark rotate: false - xy: 1578, 1942 + xy: 1578, 1944 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Circle rotate: false - xy: 296, 1864 + xy: 296, 1866 size: 178, 178 orig: 178, 178 offset: 0, 0 index: -1 OtherIcons/Cities rotate: false - xy: 190, 1230 + xy: 190, 1232 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/CityState rotate: false - xy: 1484, 1236 + xy: 818, 721 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 OtherIcons/Close rotate: false - xy: 1130, 1834 + xy: 1130, 1836 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/CrosshairB rotate: false - xy: 1778, 1834 + xy: 1778, 1836 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Cultured rotate: false - xy: 112, 1044 + xy: 112, 1046 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Diplomacy rotate: false - xy: 112, 612 + xy: 112, 614 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/DiplomacyW rotate: false - xy: 112, 504 + xy: 112, 506 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/DisbandUnit rotate: false - xy: 112, 396 + xy: 112, 398 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/ExclamationMark rotate: false - xy: 289, 1540 + xy: 289, 1542 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Fire rotate: false - xy: 393, 1432 + xy: 393, 1434 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Hexagon rotate: false - xy: 4, 1582 + xy: 4, 1584 size: 277, 240 orig: 277, 240 offset: 0, 0 index: -1 TileSets/Default/Hexagon rotate: false - xy: 4, 1582 + xy: 4, 1584 size: 277, 240 orig: 277, 240 offset: 0, 0 index: -1 TileSets/FantasyHex/Hexagon rotate: false - xy: 4, 1582 + xy: 4, 1584 size: 277, 240 orig: 277, 240 offset: 0, 0 index: -1 OtherIcons/Improvements rotate: false - xy: 1764, 1178 + xy: 1880, 1180 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 OtherIcons/Link rotate: false - xy: 494, 188 + xy: 670, 375 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 OtherIcons/Load rotate: false - xy: 1369, 1510 + xy: 1369, 1512 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Lock rotate: false - xy: 1477, 1510 + xy: 1477, 1512 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/MapEditor rotate: false - xy: 1909, 1510 + xy: 1909, 1512 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Maritime rotate: false - xy: 609, 1402 + xy: 609, 1404 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/MenuIcon rotate: false - xy: 825, 1402 + xy: 825, 1404 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Mercantile rotate: false - xy: 933, 1402 + xy: 933, 1404 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Militaristic rotate: false - xy: 1041, 1402 + xy: 1041, 1404 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Mods rotate: false - xy: 1365, 1402 + xy: 1365, 1404 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Multiplayer rotate: false - xy: 1689, 1402 + xy: 1689, 1404 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Nations rotate: false - xy: 934, 723 + xy: 710, 605 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 OtherIcons/New rotate: false - xy: 1905, 1402 + xy: 1905, 1404 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Options rotate: false - xy: 220, 730 + xy: 220, 624 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Pencil rotate: false - xy: 220, 298 + xy: 220, 192 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Pentagon rotate: false - xy: 220, 190 + xy: 220, 84 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Pillage rotate: false - xy: 298, 1324 + xy: 298, 1218 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Present rotate: false - xy: 328, 676 + xy: 328, 570 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Puppet rotate: false - xy: 328, 460 + xy: 328, 354 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Quest rotate: false - xy: 328, 244 + xy: 328, 138 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Quickstart rotate: false - xy: 328, 136 + xy: 328, 30 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Remove Heresy rotate: false - xy: 622, 1294 + xy: 730, 1296 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Resources rotate: false - xy: 838, 1294 + xy: 946, 1296 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Resume rotate: false - xy: 946, 1294 + xy: 1054, 1296 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Search rotate: false - xy: 1594, 1294 + xy: 1702, 1296 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/SecretOptions rotate: false - xy: 1702, 1294 + xy: 1810, 1296 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Settings rotate: false - xy: 1810, 1294 + xy: 1918, 1296 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Shield rotate: false - xy: 436, 1186 + xy: 436, 1080 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Sleep rotate: false - xy: 436, 862 + xy: 544, 972 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Speaker rotate: false - xy: 760, 1186 + xy: 436, 756 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Star rotate: false - xy: 652, 976 + xy: 760, 1086 size: 100, 94 orig: 100, 94 offset: 0, 0 index: -1 OtherIcons/Stop rotate: false - xy: 868, 1186 + xy: 436, 648 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Swap rotate: false - xy: 544, 754 + xy: 652, 864 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Terrains rotate: false - xy: 950, 491 + xy: 902, 435 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 OtherIcons/Triangle rotate: false - xy: 4, 1152 + xy: 4, 1154 size: 178, 178 orig: 178, 178 offset: 0, 0 index: -1 OtherIcons/Turn right rotate: false - xy: 1084, 1186 + xy: 436, 432 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Wonders rotate: false - xy: 1192, 1186 + xy: 436, 324 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/whiteDot rotate: false - xy: 473, 1855 + xy: 936, 296 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 PolicyIcons/Aesthetics rotate: false - xy: 544, 497 + xy: 652, 607 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Aristocracy rotate: false - xy: 404, 1787 + xy: 404, 1789 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Citizenship rotate: false - xy: 1426, 1236 + xy: 760, 663 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Civil Society rotate: false - xy: 1542, 1236 + xy: 818, 663 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Collective Rule rotate: false - xy: 1658, 1236 + xy: 876, 667 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Communism rotate: false - xy: 1716, 1236 + xy: 926, 783 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Constitution rotate: false - xy: 1774, 1236 + xy: 934, 725 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Cultural Diplomacy rotate: false - xy: 1890, 1236 + xy: 1034, 891 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Democracy rotate: false - xy: 760, 673 + xy: 1250, 1107 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Educated Elite rotate: false - xy: 710, 611 + xy: 1416, 1238 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Fascism rotate: false - xy: 818, 673 + xy: 1648, 1238 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Free Religion rotate: false - xy: 1034, 889 + xy: 1880, 1238 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Free Speech rotate: false - xy: 1142, 997 + xy: 1938, 1238 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Free Thought rotate: false - xy: 1250, 1105 + xy: 1416, 1180 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Humanism rotate: false - xy: 1706, 1178 + xy: 1822, 1180 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Landed Elite rotate: false - xy: 504, 304 + xy: 602, 298 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Legalism rotate: false - xy: 494, 246 + xy: 670, 433 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Mandate Of Heaven rotate: false - xy: 494, 72 + xy: 660, 259 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Mercantilism rotate: false - xy: 562, 265 + xy: 494, 226 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Merchant Navy rotate: false - xy: 552, 207 + xy: 494, 168 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Meritocracy rotate: false - xy: 552, 149 + xy: 494, 110 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Militarism rotate: false - xy: 552, 91 + xy: 494, 52 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Military Caste rotate: false - xy: 552, 33 + xy: 984, 833 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Military Tradition rotate: false - xy: 610, 207 + xy: 1042, 833 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Monarchy rotate: false - xy: 610, 91 + xy: 1200, 991 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Nationalism rotate: false - xy: 876, 723 + xy: 1258, 991 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Naval Tradition rotate: false - xy: 1092, 939 + xy: 710, 547 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Oligarchy rotate: false - xy: 1092, 881 + xy: 768, 605 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Organized Religion rotate: false - xy: 1150, 939 + xy: 768, 547 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Philantropy rotate: false - xy: 1150, 881 + xy: 826, 605 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Planned Economy rotate: false - xy: 602, 437 + xy: 884, 609 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Police State rotate: false - xy: 660, 495 + xy: 884, 551 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Populism rotate: false - xy: 660, 437 + xy: 942, 609 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Professional Army rotate: false - xy: 718, 437 + xy: 1092, 941 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Protectionism rotate: false - xy: 776, 499 + xy: 1308, 1157 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Reformation rotate: false - xy: 834, 441 + xy: 1050, 775 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Representation rotate: false - xy: 1200, 1047 + xy: 1000, 659 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Republic rotate: false - xy: 1258, 1047 + xy: 1000, 601 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Scholasticism rotate: false - xy: 884, 665 + xy: 1058, 659 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Scientific Revolution rotate: false - xy: 942, 665 + xy: 1000, 543 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Secularism rotate: false - xy: 1208, 989 + xy: 884, 493 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Socialism rotate: false - xy: 1266, 931 + xy: 1058, 485 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Sovereignty rotate: false - xy: 1266, 873 + xy: 786, 489 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Theocracy rotate: false - xy: 892, 433 + xy: 960, 427 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Total War rotate: false - xy: 950, 433 + xy: 1018, 427 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Trade Unions rotate: false - xy: 776, 383 + xy: 1076, 427 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/United Front rotate: false - xy: 892, 375 + xy: 902, 377 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Universal Suffrage rotate: false - xy: 950, 375 + xy: 960, 369 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Warrior Code rotate: false - xy: 678, 379 + xy: 1076, 369 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 ReligionIcons/Buddhism rotate: false - xy: 1254, 1942 + xy: 1254, 1944 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ReligionIcons/Christianity rotate: false - xy: 1794, 1942 + xy: 1794, 1944 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ReligionIcons/Confucianism rotate: false - xy: 1346, 1834 + xy: 1346, 1836 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ReligionIcons/Enhancer rotate: false - xy: 296, 1756 + xy: 296, 1758 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ReligionIcons/Follower rotate: false - xy: 613, 1618 + xy: 613, 1620 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ReligionIcons/Founder rotate: false - xy: 829, 1618 + xy: 829, 1620 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ReligionIcons/Hinduism rotate: false - xy: 1369, 1618 + xy: 1369, 1620 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ReligionIcons/Islam rotate: false - xy: 1909, 1618 + xy: 1909, 1620 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ReligionIcons/Judaism rotate: false - xy: 829, 1510 + xy: 829, 1512 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ReligionIcons/Pantheon rotate: false - xy: 220, 622 + xy: 220, 516 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ReligionIcons/Religion rotate: false - xy: 406, 1294 + xy: 514, 1296 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Religious rotate: false - xy: 406, 1294 + xy: 514, 1296 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ReligionIcons/Shinto rotate: false - xy: 436, 1078 + xy: 544, 1188 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ReligionIcons/Sikhism rotate: false - xy: 436, 970 + xy: 544, 1080 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ReligionIcons/Taoism rotate: false - xy: 760, 970 + xy: 868, 1080 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ReligionIcons/Tengriism rotate: false - xy: 868, 1078 + xy: 976, 1188 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ReligionIcons/Zoroastrianism rotate: false - xy: 436, 362 + xy: 544, 472 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Aluminum rotate: false - xy: 4, 936 + xy: 4, 938 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Bananas rotate: false - xy: 4, 504 + xy: 4, 506 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Cattle rotate: false - xy: 1470, 1942 + xy: 1470, 1944 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Citrus rotate: false - xy: 482, 1834 + xy: 482, 1836 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Coal rotate: false - xy: 1238, 1834 + xy: 1238, 1836 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Copper rotate: false - xy: 1454, 1834 + xy: 1454, 1836 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Cotton rotate: false - xy: 1562, 1834 + xy: 1562, 1836 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Crab rotate: false - xy: 1670, 1834 + xy: 1670, 1836 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Deer rotate: false - xy: 112, 828 + xy: 112, 830 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Dyes rotate: false - xy: 112, 288 + xy: 112, 290 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Fish rotate: false - xy: 505, 1726 + xy: 505, 1728 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Furs rotate: false - xy: 937, 1618 + xy: 937, 1620 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Gems rotate: false - xy: 1045, 1726 + xy: 1045, 1728 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Gold Ore rotate: false - xy: 1153, 1618 + xy: 1153, 1620 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Horses rotate: false - xy: 1477, 1618 + xy: 1477, 1620 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Incense rotate: false - xy: 1693, 1618 + xy: 1693, 1620 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Iron rotate: false - xy: 1801, 1618 + xy: 1801, 1620 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Ivory rotate: false - xy: 505, 1510 + xy: 505, 1512 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Jewelry rotate: false - xy: 721, 1510 + xy: 721, 1512 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Marble rotate: false - xy: 501, 1402 + xy: 501, 1404 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Oil rotate: false - xy: 220, 946 + xy: 220, 840 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Pearls rotate: false - xy: 220, 406 + xy: 220, 300 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Porcelain rotate: false - xy: 328, 784 + xy: 328, 678 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Salt rotate: false - xy: 1378, 1294 + xy: 1486, 1296 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Sheep rotate: false - xy: 1918, 1294 + xy: 436, 1188 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Silk rotate: false - xy: 544, 1078 + xy: 652, 1188 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Silver rotate: false - xy: 652, 1186 + xy: 436, 864 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Spices rotate: false - xy: 544, 862 + xy: 652, 972 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Stone rotate: false - xy: 760, 1078 + xy: 868, 1188 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Sugar rotate: false - xy: 436, 646 + xy: 544, 756 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Truffles rotate: false - xy: 976, 1078 + xy: 1084, 1188 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Uranium rotate: false - xy: 760, 754 + xy: 868, 864 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Whales rotate: false - xy: 868, 862 + xy: 976, 972 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Wheat rotate: false - xy: 976, 970 + xy: 1084, 1080 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Wine rotate: false - xy: 1084, 1078 + xy: 1192, 1188 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 StatIcons/Acquire rotate: false - xy: 606, 1942 + xy: 606, 1944 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 StatIcons/CityConnection rotate: false - xy: 806, 1834 + xy: 806, 1836 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 StatIcons/Culture rotate: false - xy: 1886, 1834 + xy: 1886, 1836 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 StatIcons/Faith rotate: false - xy: 285, 1432 + xy: 285, 1434 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 StatIcons/Food rotate: false - xy: 721, 1726 + xy: 721, 1728 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 StatIcons/Gold rotate: false - xy: 1153, 1726 + xy: 1153, 1728 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 StatIcons/Happiness rotate: false - xy: 1261, 1618 + xy: 1261, 1620 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 StatIcons/InterceptRange rotate: false - xy: 1880, 1178 + xy: 612, 414 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 StatIcons/Malcontent rotate: false - xy: 1693, 1510 + xy: 1693, 1512 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 StatIcons/Population rotate: false - xy: 328, 892 + xy: 328, 786 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 StatIcons/Production rotate: false - xy: 328, 568 + xy: 328, 462 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 StatIcons/Range rotate: false - xy: 776, 441 + xy: 992, 775 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 StatIcons/RangedStrength rotate: false - xy: 834, 499 + xy: 992, 717 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 StatIcons/ReligiousStrength rotate: false - xy: 514, 1294 + xy: 622, 1296 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 StatIcons/Resistance rotate: false - xy: 730, 1294 + xy: 838, 1296 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 StatIcons/Science rotate: false - xy: 1486, 1294 + xy: 1594, 1296 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 StatIcons/Specialist rotate: false - xy: 436, 754 + xy: 544, 864 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 StatIcons/Strength rotate: false - xy: 892, 549 + xy: 728, 431 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 TileSets/Default/Arrows/CityHasAttacked rotate: false - xy: 4, 4 + xy: 4, 6 size: 100, 60 orig: 100, 60 offset: 0, 0 index: -1 TileSets/Default/Arrows/UnitHasAttacked rotate: false - xy: 4, 4 + xy: 4, 6 size: 100, 60 orig: 100, 60 offset: 0, 0 index: -1 TileSets/FantasyHex/Arrows/UnitHasAttacked rotate: false - xy: 4, 4 - size: 100, 60 - orig: 100, 60 - offset: 0, 0 - index: -1 -TileSets/Default/AtollOverlay - rotate: false - xy: 4, 720 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 -TileSets/Default/CityOverlay - rotate: false - xy: 914, 1834 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 -TileSets/Default/FalloutOverlay - rotate: false - xy: 397, 1648 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 -TileSets/Default/Flood plainsOverlay - rotate: false - xy: 613, 1726 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 -TileSets/Default/ForestOverlay - rotate: false - xy: 721, 1618 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 -TileSets/Default/HillOverlay - rotate: false - xy: 1369, 1726 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 -TileSets/Default/IceOverlay - rotate: false - xy: 1585, 1726 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 -TileSets/Default/JungleOverlay - rotate: false - xy: 937, 1510 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 -TileSets/Default/LakesOverlay - rotate: false - xy: 1153, 1510 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 -TileSets/Default/MarshOverlay - rotate: false - xy: 717, 1402 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 -TileSets/Default/MountainOverlay - rotate: false - xy: 1581, 1402 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 -TileSets/Default/NaturalWonderOverlay - rotate: false - xy: 1797, 1402 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 -TileSets/Default/OasisOverlay - rotate: false - xy: 220, 1054 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 -TileSets/Default/Railroad - rotate: false - xy: 328, 28 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 -ImprovementIcons/Railroad - rotate: false - xy: 328, 28 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 -TileSets/Default/Road - rotate: false - xy: 404, 1845 - size: 61, 11 - orig: 61, 11 - offset: 0, 0 - index: -1 -TileSets/Default/Tiles/River-Bottom - rotate: false - xy: 1524, 878 - size: 32, 28 - orig: 32, 28 - offset: 0, 0 - index: -1 -TileSets/Default/Tiles/River-BottomLeft - rotate: false - xy: 1522, 806 - size: 32, 28 - orig: 32, 28 - offset: 0, 0 - index: -1 -TileSets/Default/Tiles/River-BottomRight - rotate: false - xy: 1512, 734 - size: 32, 28 - orig: 32, 28 - offset: 0, 0 - index: -1 -TileSets/FantasyHex/Arrows/Generic - rotate: false - xy: 190, 1162 + xy: 4, 6 size: 100, 60 orig: 100, 60 offset: 0, 0 index: -1 TileSets/Default/Arrows/Generic rotate: false - xy: 190, 1162 + xy: 190, 1164 size: 100, 60 orig: 100, 60 offset: 0, 0 index: -1 -TileSets/FantasyHex/Arrows/UnitAttacked +TileSets/FantasyHex/Arrows/Generic rotate: false - xy: 112, 4 + xy: 190, 1164 size: 100, 60 orig: 100, 60 offset: 0, 0 index: -1 TileSets/Default/Arrows/UnitAttacked rotate: false - xy: 112, 4 + xy: 112, 6 size: 100, 60 orig: 100, 60 offset: 0, 0 index: -1 -TileSets/FantasyHex/Arrows/UnitMoved +TileSets/FantasyHex/Arrows/UnitAttacked rotate: false - xy: 220, 14 + xy: 112, 6 size: 100, 60 orig: 100, 60 offset: 0, 0 index: -1 TileSets/Default/Arrows/UnitMoved rotate: false - xy: 220, 14 + xy: 220, 16 size: 100, 60 orig: 100, 60 offset: 0, 0 index: -1 -TileSets/FantasyHex/Arrows/UnitMoving +TileSets/FantasyHex/Arrows/UnitMoved rotate: false - xy: 436, 470 + xy: 220, 16 size: 100, 60 orig: 100, 60 offset: 0, 0 index: -1 TileSets/Default/Arrows/UnitMoving rotate: false - xy: 436, 470 + xy: 544, 580 size: 100, 60 orig: 100, 60 offset: 0, 0 index: -1 -TileSets/FantasyHex/Arrows/UnitTeleported +TileSets/FantasyHex/Arrows/UnitMoving rotate: false - xy: 544, 578 + xy: 544, 580 size: 100, 60 orig: 100, 60 offset: 0, 0 index: -1 TileSets/Default/Arrows/UnitTeleported rotate: false - xy: 544, 578 + xy: 652, 688 size: 100, 60 orig: 100, 60 offset: 0, 0 index: -1 -TileSets/FantasyHex/Arrows/UnitWithdrew +TileSets/FantasyHex/Arrows/UnitTeleported rotate: false - xy: 652, 692 + xy: 652, 688 size: 100, 60 orig: 100, 60 offset: 0, 0 index: -1 TileSets/Default/Arrows/UnitWithdrew rotate: false - xy: 652, 692 + xy: 760, 802 size: 100, 60 orig: 100, 60 offset: 0, 0 index: -1 -TileSets/FantasyHex/Borders/ConcaveConvexInner +TileSets/FantasyHex/Arrows/UnitWithdrew rotate: false - xy: 406, 1409 - size: 81, 15 - orig: 81, 15 + xy: 760, 802 + size: 100, 60 + orig: 100, 60 + offset: 0, 0 + index: -1 +TileSets/Default/AtollOverlay + rotate: false + xy: 4, 722 + size: 100, 100 + orig: 100, 100 offset: 0, 0 index: -1 TileSets/Default/Borders/ConcaveConvexInner rotate: false - xy: 406, 1409 + xy: 406, 1411 size: 81, 15 orig: 81, 15 offset: 0, 0 index: -1 -TileSets/FantasyHex/Borders/ConcaveConvexOuter +TileSets/FantasyHex/Borders/ConcaveConvexInner rotate: false - xy: 544, 555 + xy: 406, 1411 size: 81, 15 orig: 81, 15 offset: 0, 0 index: -1 TileSets/Default/Borders/ConcaveConvexOuter rotate: false - xy: 544, 555 + xy: 652, 665 size: 81, 15 orig: 81, 15 offset: 0, 0 index: -1 -TileSets/FantasyHex/Borders/ConcaveInner +TileSets/FantasyHex/Borders/ConcaveConvexOuter rotate: false - xy: 652, 669 + xy: 652, 665 size: 81, 15 orig: 81, 15 offset: 0, 0 index: -1 TileSets/Default/Borders/ConcaveInner rotate: false - xy: 652, 669 + xy: 760, 779 size: 81, 15 orig: 81, 15 offset: 0, 0 index: -1 -TileSets/FantasyHex/Borders/ConcaveOuter +TileSets/FantasyHex/Borders/ConcaveInner rotate: false - xy: 760, 731 + xy: 760, 779 size: 81, 15 orig: 81, 15 offset: 0, 0 index: -1 TileSets/Default/Borders/ConcaveOuter rotate: false - xy: 760, 731 + xy: 868, 841 size: 81, 15 orig: 81, 15 offset: 0, 0 index: -1 -TileSets/FantasyHex/Borders/ConvexConcaveInner +TileSets/FantasyHex/Borders/ConcaveOuter rotate: false - xy: 868, 839 + xy: 868, 841 size: 81, 15 orig: 81, 15 offset: 0, 0 index: -1 TileSets/Default/Borders/ConvexConcaveInner rotate: false - xy: 868, 839 + xy: 976, 949 size: 81, 15 orig: 81, 15 offset: 0, 0 index: -1 -TileSets/FantasyHex/Borders/ConvexConcaveOuter +TileSets/FantasyHex/Borders/ConvexConcaveInner rotate: false - xy: 976, 947 + xy: 976, 949 size: 81, 15 orig: 81, 15 offset: 0, 0 index: -1 TileSets/Default/Borders/ConvexConcaveOuter rotate: false - xy: 976, 947 + xy: 1084, 1057 size: 81, 15 orig: 81, 15 offset: 0, 0 index: -1 -TileSets/FantasyHex/Borders/ConvexInner +TileSets/FantasyHex/Borders/ConvexConcaveOuter rotate: false - xy: 1084, 1055 + xy: 1084, 1057 size: 81, 15 orig: 81, 15 offset: 0, 0 index: -1 TileSets/Default/Borders/ConvexInner rotate: false - xy: 1084, 1055 + xy: 1192, 1165 size: 81, 15 orig: 81, 15 offset: 0, 0 index: -1 -TileSets/FantasyHex/Borders/ConvexOuter +TileSets/FantasyHex/Borders/ConvexInner rotate: false - xy: 1192, 1163 + xy: 1192, 1165 size: 81, 15 orig: 81, 15 offset: 0, 0 index: -1 TileSets/Default/Borders/ConvexOuter rotate: false - xy: 1192, 1163 + xy: 1300, 1273 size: 81, 15 orig: 81, 15 offset: 0, 0 index: -1 -TileSets/FantasyHex/Crosshair +TileSets/FantasyHex/Borders/ConvexOuter rotate: false - xy: 482, 1942 - size: 116, 100 - orig: 116, 100 + xy: 1300, 1273 + size: 81, 15 + orig: 81, 15 + offset: 0, 0 + index: -1 +TileSets/Default/CityOverlay + rotate: false + xy: 914, 1836 + size: 100, 100 + orig: 100, 100 offset: 0, 0 index: -1 TileSets/Default/Crosshair rotate: false - xy: 482, 1942 + xy: 482, 1944 size: 116, 100 orig: 116, 100 offset: 0, 0 index: -1 -TileSets/FantasyHex/CrosshatchHexagon +TileSets/FantasyHex/Crosshair rotate: false - xy: 4, 1338 - size: 273, 236 - orig: 273, 236 + xy: 482, 1944 + size: 116, 100 + orig: 116, 100 offset: 0, 0 index: -1 TileSets/Default/CrosshatchHexagon rotate: false - xy: 4, 1338 + xy: 4, 1340 size: 273, 236 orig: 273, 236 offset: 0, 0 index: -1 -TileSets/FantasyHex/Highlight +TileSets/FantasyHex/CrosshatchHexagon rotate: false - xy: 4, 1830 - size: 284, 212 - orig: 284, 212 + xy: 4, 1340 + size: 273, 236 + orig: 273, 236 + offset: 0, 0 + index: -1 +TileSets/Default/FalloutOverlay + rotate: false + xy: 397, 1650 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +TileSets/Default/Flood plainsOverlay + rotate: false + xy: 613, 1728 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +TileSets/Default/ForestOverlay + rotate: false + xy: 721, 1620 + size: 100, 100 + orig: 100, 100 offset: 0, 0 index: -1 TileSets/Default/Highlight rotate: false - xy: 4, 1830 + xy: 4, 1832 size: 284, 212 orig: 284, 212 offset: 0, 0 index: -1 +TileSets/FantasyHex/Highlight + rotate: false + xy: 4, 1832 + size: 284, 212 + orig: 284, 212 + offset: 0, 0 + index: -1 +TileSets/Default/HillOverlay + rotate: false + xy: 1369, 1728 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +TileSets/Default/IceOverlay + rotate: false + xy: 1585, 1728 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +TileSets/Default/JungleOverlay + rotate: false + xy: 937, 1512 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +TileSets/Default/LakesOverlay + rotate: false + xy: 1153, 1512 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +TileSets/Default/MarshOverlay + rotate: false + xy: 717, 1404 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +TileSets/Default/MountainOverlay + rotate: false + xy: 1581, 1404 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +TileSets/Default/NaturalWonderOverlay + rotate: false + xy: 1797, 1404 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +TileSets/Default/OasisOverlay + rotate: false + xy: 220, 1056 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +TileSets/Default/Railroad + rotate: false + xy: 406, 1296 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +ImprovementIcons/Railroad + rotate: false + xy: 406, 1296 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +TileSets/Default/Road + rotate: false + xy: 404, 1847 + size: 61, 11 + orig: 61, 11 + offset: 0, 0 + index: -1 +TileSets/Default/Tiles/River-Bottom + rotate: false + xy: 1846, 1029 + size: 32, 28 + orig: 32, 28 + offset: 0, 0 + index: -1 +TileSets/Default/Tiles/River-BottomLeft + rotate: false + xy: 1926, 994 + size: 32, 28 + orig: 32, 28 + offset: 0, 0 + index: -1 +TileSets/Default/Tiles/River-BottomRight + rotate: false + xy: 2006, 960 + size: 32, 28 + orig: 32, 28 + offset: 0, 0 + index: -1 TileSets/FantasyHex/Railroad rotate: false - xy: 1300, 1254 + xy: 436, 284 size: 60, 32 orig: 60, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Road rotate: false - xy: 436, 322 + xy: 544, 432 size: 60, 32 orig: 60, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Academy rotate: false - xy: 736, 393 + xy: 844, 503 size: 32, 36 orig: 32, 36 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Academy-Snow rotate: false - xy: 736, 350 + xy: 2010, 2009 size: 32, 35 orig: 32, 35 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Aluminum rotate: false - xy: 1994, 1848 + xy: 1994, 1850 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Ancient ruins rotate: false - xy: 984, 795 + xy: 1092, 905 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Ancient ruins-Jungle rotate: false - xy: 620, 281 + xy: 1308, 1117 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Ancient ruins-Sand rotate: false - xy: 2010, 1977 + xy: 1366, 1179 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Ancient ruins-Snow rotate: false - xy: 660, 285 + xy: 728, 395 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Ancient ruins2 rotate: false - xy: 1042, 853 + xy: 1150, 963 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Atoll rotate: false - xy: 1162, 845 + xy: 874, 341 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Bananas rotate: false - xy: 1162, 809 + xy: 874, 305 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Barbarian encampment rotate: false - xy: 1202, 837 + xy: 914, 305 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Barbarian encampment-Snow rotate: false - xy: 1242, 836 + xy: 954, 332 size: 32, 29 orig: 32, 29 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Barringer Crater rotate: false - xy: 1282, 837 + xy: 994, 333 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Bison rotate: false - xy: 2006, 1222 + xy: 1074, 297 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Bison+Camp rotate: false - xy: 1996, 1186 + xy: 436, 16 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Cattle rotate: false - xy: 708, 141 + xy: 1446, 1144 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Cattle+Pasture rotate: false - xy: 708, 101 + xy: 1486, 1140 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Cerro de Potosi rotate: false - xy: 708, 29 + xy: 1566, 1144 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Citadel rotate: false - xy: 1000, 680 + xy: 1686, 1137 size: 32, 35 orig: 32, 35 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Citadel-Snow rotate: false - xy: 1000, 642 + xy: 1726, 1142 size: 32, 30 orig: 32, 30 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Citrus rotate: false - xy: 1996, 1150 + xy: 1766, 1144 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Citrus+Plantation rotate: false - xy: 1032, 781 + xy: 1806, 1144 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/City center rotate: false - xy: 1032, 738 + xy: 1846, 1137 size: 32, 35 orig: 32, 35 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/City center-Ancient era rotate: false - xy: 1072, 769 + xy: 1886, 1140 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/City center-Atomic era rotate: false - xy: 1112, 767 + xy: 1926, 1138 size: 32, 34 orig: 32, 34 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/City center-Classical era rotate: false - xy: 1152, 769 + xy: 1966, 1140 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/City center-Future era rotate: false - xy: 1072, 727 + xy: 1316, 1075 size: 32, 34 orig: 32, 34 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/City center-Industrial era rotate: false - xy: 1112, 726 + xy: 1316, 1034 size: 32, 33 orig: 32, 33 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/City center-Information era rotate: false - xy: 1152, 725 + xy: 1316, 990 size: 32, 36 orig: 32, 36 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/City center-Medieval era rotate: false - xy: 1192, 761 + xy: 1310, 950 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/City center-Modern era rotate: false - xy: 1192, 719 + xy: 1310, 908 size: 32, 34 orig: 32, 34 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/City center-Renaissance era rotate: false - xy: 1232, 760 + xy: 2006, 1148 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/City ruins rotate: false - xy: 1232, 724 + xy: 776, 243 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Coal rotate: false - xy: 1272, 728 + xy: 856, 269 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Coast rotate: false - xy: 1232, 688 + xy: 896, 269 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Cocoa rotate: false - xy: 1272, 692 + xy: 816, 233 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Cocoa+Plantation rotate: false - xy: 1312, 765 + xy: 856, 233 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Copper rotate: false - xy: 1308, 1160 + xy: 1310, 872 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Cotton rotate: false - xy: 1348, 1142 + xy: 1114, 333 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Crab rotate: false - xy: 1388, 1142 + xy: 1114, 297 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Customs house rotate: false - xy: 1468, 1135 + xy: 1016, 254 size: 32, 35 orig: 32, 35 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Deer rotate: false - xy: 1508, 1142 + xy: 1056, 261 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Deer+Camp rotate: false - xy: 1548, 1142 + xy: 1096, 261 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Desert rotate: false - xy: 1588, 1142 + xy: 1016, 218 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Desert+Farm rotate: false - xy: 1628, 1142 + xy: 1056, 225 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Desert+Flood plains+Farm rotate: false - xy: 1668, 1142 + xy: 1096, 225 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Dyes rotate: false - xy: 1788, 1142 + xy: 1108, 797 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Dyes+Plantation rotate: false - xy: 1828, 1142 + xy: 1108, 761 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/El Dorado rotate: false - xy: 1868, 1141 + xy: 1108, 724 size: 32, 29 orig: 32, 29 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Fallout rotate: false - xy: 1908, 1135 + xy: 1116, 681 size: 32, 35 orig: 32, 35 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Fish rotate: false - xy: 1948, 1142 + xy: 1116, 645 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Fishing Boats rotate: false - xy: 1348, 1106 + xy: 1116, 609 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Flood plains rotate: false - xy: 1388, 1106 + xy: 1116, 573 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Forest rotate: false - xy: 1468, 1095 + xy: 1116, 497 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Fort rotate: false - xy: 1508, 1101 + xy: 1136, 256 size: 32, 33 orig: 32, 33 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Fountain of Youth rotate: false - xy: 1548, 1102 + xy: 1136, 216 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Furs rotate: false - xy: 1628, 1106 + xy: 976, 190 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Furs+Camp rotate: false - xy: 1668, 1106 + xy: 1016, 182 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Gems rotate: false - xy: 1828, 1106 + xy: 2006, 1112 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Gold Ore rotate: false - xy: 1908, 1099 + xy: 2006, 1076 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Grand Mesa rotate: false - xy: 1948, 1102 + xy: 1134, 457 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Grassland rotate: false - xy: 1988, 1114 + xy: 1134, 421 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Grassland+Farm rotate: false - xy: 1988, 1078 + xy: 1134, 385 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Grassland+Forest+Camp rotate: false - xy: 1948, 1063 + xy: 1140, 887 size: 32, 31 orig: 32, 31 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Grassland+Forest+Deer+Camp rotate: false - xy: 1988, 1039 + xy: 1140, 848 size: 32, 31 orig: 32, 31 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Grassland+Forest+Furs+Camp rotate: false - xy: 1316, 1067 + xy: 1180, 880 size: 32, 31 orig: 32, 31 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Grassland+Forest+Lumber mill rotate: false - xy: 1356, 1067 + xy: 1180, 841 size: 32, 31 orig: 32, 31 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Grassland+Forest+Truffles+Camp rotate: false - xy: 1396, 1067 + xy: 1220, 874 size: 32, 31 orig: 32, 31 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Grassland+Hill+Farm rotate: false - xy: 1324, 1031 + xy: 1220, 838 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Grassland+Hill+Forest+Camp rotate: false - xy: 1324, 995 + xy: 1260, 847 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Grassland+Hill+Forest+Lumber mill rotate: false - xy: 1364, 1031 + xy: 1300, 836 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Grassland+Hill+Forest+Trading post rotate: false - xy: 1324, 959 + xy: 1260, 811 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Grassland+Jungle+Trading post rotate: false - xy: 1364, 991 + xy: 1300, 796 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/GrasslandForest rotate: false - xy: 1324, 920 + xy: 1340, 833 size: 32, 31 orig: 32, 31 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Great Barrier Reef rotate: false - xy: 1364, 916 + xy: 1096, 153 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Hill rotate: false - xy: 1352, 768 + xy: 1966, 1061 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/HillForest+Lumber mill rotate: false - xy: 1352, 732 + xy: 2006, 1040 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/HillMarbleQuarry rotate: false - xy: 1352, 696 + xy: 1886, 1032 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/HillMine rotate: false - xy: 1352, 660 + xy: 1926, 1030 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/HillStoneQuarry rotate: false - xy: 1508, 1065 + xy: 1966, 1025 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Holy site rotate: false - xy: 1548, 1058 + xy: 2006, 996 size: 32, 36 orig: 32, 36 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Horses rotate: false - xy: 1708, 1070 + xy: 552, 172 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Horses+Pasture rotate: false - xy: 1748, 1066 + xy: 552, 132 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Ice rotate: false - xy: 1868, 1066 + xy: 592, 262 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Incense rotate: false - xy: 1628, 1034 + xy: 592, 154 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Incense+Plantation rotate: false - xy: 1668, 1034 + xy: 592, 118 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Iron rotate: false - xy: 1788, 1033 + xy: 596, 46 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Ivory rotate: false - xy: 1868, 1030 + xy: 632, 223 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Ivory+Camp rotate: false - xy: 1908, 1027 + xy: 632, 187 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Jungle rotate: false - xy: 1392, 768 + xy: 632, 147 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Krakatoa rotate: false - xy: 1352, 622 + xy: 672, 149 size: 32, 30 orig: 32, 30 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Lakes rotate: false - xy: 1402, 808 + xy: 712, 151 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Landmark rotate: false - xy: 1432, 692 + xy: 752, 163 size: 32, 36 orig: 32, 36 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Manufactory rotate: false - xy: 1988, 956 + xy: 872, 185 size: 32, 39 orig: 32, 39 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Marble rotate: false - xy: 1908, 955 + xy: 752, 91 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Marsh rotate: false - xy: 1040, 690 + xy: 832, 88 size: 32, 29 orig: 32, 29 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Mine rotate: false - xy: 1080, 654 + xy: 752, 55 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Moai rotate: false - xy: 1120, 616 + xy: 872, 40 size: 32, 29 orig: 32, 29 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Mount Fuji rotate: false - xy: 1200, 650 + xy: 912, 185 size: 32, 30 orig: 32, 30 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Mount Kailash rotate: false - xy: 1200, 610 + xy: 912, 145 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Mount Sinai rotate: false - xy: 1442, 808 + xy: 912, 105 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Mountain rotate: false - xy: 1472, 764 + xy: 912, 61 size: 32, 36 orig: 32, 36 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Oasis rotate: false - xy: 1280, 619 + xy: 952, 82 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Ocean rotate: false - xy: 1280, 583 + xy: 952, 46 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Offshore Platform rotate: false - xy: 1320, 586 + xy: 992, 146 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Oil rotate: false - xy: 1360, 585 + xy: 992, 110 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Oil well rotate: false - xy: 1320, 550 + xy: 992, 74 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Old Faithful rotate: false - xy: 1360, 545 + xy: 992, 34 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Pasture rotate: false - xy: 1440, 580 + xy: 1032, 77 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Pearls rotate: false - xy: 1480, 584 + xy: 1072, 81 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Plains rotate: false - xy: 1480, 512 + xy: 1112, 36 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Plains+Farm rotate: false - xy: 1480, 476 + xy: 1152, 108 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Plains+Forest+Camp rotate: false - xy: 1988, 916 + xy: 1152, 68 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Plains+Forest+Lumber mill rotate: false - xy: 1444, 1025 + xy: 1152, 28 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Plains+Jungle+Trading post rotate: false - xy: 1444, 985 + xy: 1072, 5 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/PlainsForest rotate: false - xy: 1444, 945 + xy: 1350, 950 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/PlainsJungle rotate: false - xy: 1444, 905 + xy: 1350, 910 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Plantation rotate: false - xy: 1444, 869 + xy: 1032, 5 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Plantation+Bananas rotate: false - xy: 1484, 1029 + xy: 1350, 874 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Plantation+Cotton rotate: false - xy: 1484, 993 + xy: 1526, 1108 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Polder rotate: false - xy: 1484, 956 + xy: 636, 40 size: 32, 29 orig: 32, 29 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Quarry rotate: false - xy: 1484, 848 + xy: 1646, 1108 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Quarry+Marble rotate: false - xy: 1482, 812 + xy: 1686, 1101 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Quarry+Stone rotate: false - xy: 1524, 1022 + xy: 1726, 1070 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/River-Bottom rotate: false - xy: 1524, 914 + xy: 1886, 996 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/River-BottomLeft rotate: false - xy: 1524, 842 + xy: 1966, 989 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/River-BottomRight rotate: false - xy: 1512, 770 + xy: 1380, 838 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Rock of Gibraltar rotate: false - xy: 1512, 694 + xy: 1380, 798 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Salt rotate: false - xy: 1512, 622 + xy: 1406, 1108 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Sheep rotate: false - xy: 1564, 998 + xy: 1606, 1072 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Sheep+Pasture rotate: false - xy: 1564, 958 + xy: 1646, 1068 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Silk rotate: false - xy: 1564, 885 + xy: 1766, 1033 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Silk+Plantation rotate: false - xy: 1644, 998 + xy: 1806, 1000 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Silver rotate: false - xy: 1604, 962 + xy: 1846, 993 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Snow rotate: false - xy: 1644, 962 + xy: 1156, 616 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Snow+Farm rotate: false - xy: 1644, 926 + xy: 1156, 580 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Spices rotate: false - xy: 1684, 962 + xy: 1156, 508 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Spices+Plantation rotate: false - xy: 1684, 926 + xy: 1174, 472 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Sri Pada rotate: false - xy: 1604, 848 + xy: 1174, 432 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Stone rotate: false - xy: 1644, 890 + xy: 1174, 396 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Sugar rotate: false - xy: 1684, 890 + xy: 1174, 360 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Sugar+Plantation rotate: false - xy: 1644, 854 + xy: 1154, 324 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Terrace farm rotate: false - xy: 1008, 500 + xy: 1176, 216 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Trading post rotate: false - xy: 1008, 428 + xy: 1176, 144 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Truffles rotate: false - xy: 1048, 546 + xy: 1192, 36 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Truffles+Camp rotate: false - xy: 1048, 510 + xy: 1216, 288 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Tundra rotate: false - xy: 1048, 474 + xy: 1216, 252 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Tundra+Farm rotate: false - xy: 1048, 438 + xy: 1216, 216 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Tundra+Forest+Camp rotate: false - xy: 1048, 398 + xy: 1216, 176 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Tundra+Forest+Camp+Furs rotate: false - xy: 1008, 352 + xy: 1606, 1032 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Tundra+Forest+Deer+Camp rotate: false - xy: 1048, 358 + xy: 1646, 1028 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Tundra+Forest+Lumber mill rotate: false - xy: 1724, 990 + xy: 1686, 1024 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Tundra+Forest+Truffles+Camp rotate: false - xy: 1724, 950 + xy: 1726, 994 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/TundraForest rotate: false - xy: 1724, 910 + xy: 1766, 993 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Uluru rotate: false - xy: 1724, 834 + xy: 1846, 953 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Uranium rotate: false - xy: 1764, 961 + xy: 1886, 960 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Whales rotate: false - xy: 1804, 926 + xy: 1966, 917 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Whales+Fishing Boats rotate: false - xy: 1804, 890 + xy: 2006, 924 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Wheat rotate: false - xy: 1804, 854 + xy: 2006, 888 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Wine rotate: false - xy: 1804, 818 + xy: 1356, 1107 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Tiles/Wine+Plantation rotate: false - xy: 1844, 922 + xy: 1356, 1071 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/TopBorder rotate: false - xy: 1008, 464 + xy: 1176, 180 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/African Forest Elephant rotate: false - xy: 2010, 2013 + xy: 504, 287 size: 32, 29 orig: 32, 29 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Anti-Aircraft Gun rotate: false - xy: 776, 347 + xy: 776, 279 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Anti-Tank Gun rotate: false - xy: 816, 347 + xy: 2010, 1973 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Archaeologist rotate: false - xy: 700, 285 + xy: 1996, 1260 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Archer rotate: false - xy: 1042, 817 + xy: 1996, 1224 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Artillery rotate: false - xy: 1082, 845 + xy: 1996, 1188 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Atlatlist rotate: false - xy: 1122, 845 + xy: 834, 341 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Axe Thrower rotate: false - xy: 1082, 809 + xy: 914, 341 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Ballista rotate: false - xy: 1122, 809 + xy: 834, 305 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Battering Ram rotate: false - xy: 1202, 801 + xy: 1034, 333 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Battleship rotate: false - xy: 1242, 800 + xy: 1074, 333 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Bazooka rotate: false - xy: 1282, 801 + xy: 954, 296 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Berber Cavalry rotate: false - xy: 462, 1798 + xy: 994, 297 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Berserker rotate: false - xy: 2006, 1258 + xy: 1034, 297 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Bowman rotate: false - xy: 668, 249 + xy: 476, 16 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Brute rotate: false - xy: 668, 213 + xy: 516, 16 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Camel Archer rotate: false - xy: 668, 176 + xy: 1150, 926 size: 32, 29 orig: 32, 29 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Cannon rotate: false - xy: 668, 140 + xy: 1190, 955 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Caravan rotate: false - xy: 462, 1756 + xy: 1230, 949 size: 32, 34 orig: 32, 34 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Caravel rotate: false - xy: 668, 104 + xy: 1270, 955 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Cargo Ship rotate: false - xy: 668, 68 + xy: 1190, 919 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Carolean rotate: false - xy: 668, 32 + xy: 1230, 913 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Carrier rotate: false - xy: 708, 249 + xy: 1270, 919 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Cataphract rotate: false - xy: 708, 213 + xy: 1366, 1143 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Catapult rotate: false - xy: 708, 177 + xy: 1406, 1144 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Cavalry rotate: false - xy: 708, 65 + xy: 1526, 1144 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Chariot Archer rotate: false - xy: 992, 759 + xy: 1606, 1144 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Chu-Ko-Nu rotate: false - xy: 992, 723 + xy: 1646, 1144 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/CivilianLandUnit rotate: false - xy: 1272, 764 + xy: 816, 269 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Comanche Rider rotate: false - xy: 1312, 728 + xy: 896, 232 size: 32, 29 orig: 32, 29 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Companion Cavalry rotate: false - xy: 1312, 691 + xy: 936, 259 size: 32, 29 orig: 32, 29 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Composite Bowman rotate: false - xy: 1272, 656 + xy: 936, 223 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Conquistador rotate: false - xy: 1312, 655 + xy: 1270, 883 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Cossack rotate: false - xy: 1308, 1124 + xy: 462, 1800 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Crossbowman rotate: false - xy: 1428, 1142 + xy: 976, 260 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Cruiser rotate: false - xy: 2010, 1943 + xy: 976, 226 size: 32, 26 orig: 32, 26 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Destroyer rotate: false - xy: 1708, 1142 + xy: 1100, 869 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Dromon rotate: false - xy: 1748, 1142 + xy: 1100, 833 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Foreign Legion rotate: false - xy: 1428, 1106 + xy: 1116, 537 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Frigate rotate: false - xy: 1588, 1106 + xy: 462, 1764 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Galleass rotate: false - xy: 1708, 1106 + xy: 1056, 189 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Galley rotate: false - xy: 1748, 1106 + xy: 1096, 189 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Gatling Gun rotate: false - xy: 1788, 1106 + xy: 1136, 180 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Giant Death Robot rotate: false - xy: 1868, 1102 + xy: 1966, 1101 size: 32, 31 orig: 32, 31 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Great Admiral rotate: false - xy: 1364, 952 + xy: 1340, 794 size: 32, 31 orig: 32, 31 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Great Artist rotate: false - xy: 1324, 884 + xy: 1056, 153 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Great Engineer rotate: false - xy: 1364, 880 + xy: 1136, 144 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Great Galleass rotate: false - xy: 1404, 1031 + xy: 1726, 1106 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Great General rotate: false - xy: 1404, 992 + xy: 1766, 1105 size: 32, 31 orig: 32, 31 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Great Merchant rotate: false - xy: 1404, 956 + xy: 1806, 1108 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Great Musician rotate: false - xy: 1404, 920 + xy: 1846, 1101 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Great Prophet rotate: false - xy: 1404, 884 + xy: 1886, 1104 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Great Scientist rotate: false - xy: 1324, 848 + xy: 1926, 1102 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Great War Infantry rotate: false - xy: 1322, 812 + xy: 1806, 1072 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Great Writer rotate: false - xy: 1364, 844 + xy: 1846, 1065 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Hakkapeliitta rotate: false - xy: 1404, 848 + xy: 1886, 1068 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Helicopter Gunship rotate: false - xy: 1362, 808 + xy: 1926, 1066 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Hoplite rotate: false - xy: 1588, 1070 + xy: 552, 280 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Horse Archer rotate: false - xy: 1628, 1070 + xy: 552, 244 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Horseman rotate: false - xy: 1668, 1070 + xy: 552, 208 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Hussar rotate: false - xy: 1788, 1069 + xy: 552, 95 size: 32, 29 orig: 32, 29 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Hwach'a rotate: false - xy: 1828, 1070 + xy: 552, 59 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Immortal rotate: false - xy: 1908, 1063 + xy: 592, 226 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Impi rotate: false - xy: 1588, 1034 + xy: 592, 190 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Infantry rotate: false - xy: 1708, 1034 + xy: 592, 82 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Inquisitor rotate: false - xy: 1748, 1030 + xy: 556, 23 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Ironclad rotate: false - xy: 1828, 1034 + xy: 596, 10 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Jaguar rotate: false - xy: 1948, 1027 + xy: 672, 223 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Janissary rotate: false - xy: 1988, 1003 + xy: 672, 187 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Keshik rotate: false - xy: 1392, 732 + xy: 712, 223 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Khan rotate: false - xy: 1392, 693 + xy: 632, 108 size: 32, 31 orig: 32, 31 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Knight rotate: false - xy: 1392, 657 + xy: 712, 187 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Kris Swordsman rotate: false - xy: 1392, 621 + xy: 672, 113 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Lancer rotate: false - xy: 1432, 772 + xy: 712, 115 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/LandUnit rotate: false - xy: 1432, 736 + xy: 752, 207 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Landship rotate: false - xy: 1432, 656 + xy: 752, 127 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Landsknecht rotate: false - xy: 1432, 620 + xy: 792, 197 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Legion rotate: false - xy: 1828, 998 + xy: 832, 197 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Longbowman rotate: false - xy: 1788, 997 + xy: 792, 161 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Longswordsman rotate: false - xy: 1868, 994 + xy: 832, 161 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Machine Gun rotate: false - xy: 1908, 991 + xy: 792, 125 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Mandekalu Cavalry rotate: false - xy: 1948, 991 + xy: 832, 125 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Maori Warrior rotate: false - xy: 1828, 962 + xy: 872, 149 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Marauder rotate: false - xy: 1868, 958 + xy: 872, 113 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Marine rotate: false - xy: 1948, 955 + xy: 792, 89 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Mechanized Infantry rotate: false - xy: 1040, 654 + xy: 712, 79 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Mehal Sefari rotate: false - xy: 1040, 618 + xy: 672, 77 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Merchant Of Venice rotate: false - xy: 1080, 690 + xy: 872, 77 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Minuteman rotate: false - xy: 1080, 618 + xy: 792, 53 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Missile Cruiser rotate: false - xy: 1120, 689 + xy: 832, 52 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Missionary rotate: false - xy: 1120, 653 + xy: 712, 43 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Mobile SAM rotate: false - xy: 1160, 683 + xy: 636, 4 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Modern Armor rotate: false - xy: 1160, 647 + xy: 676, 4 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Mohawk Warrior rotate: false - xy: 1160, 611 + xy: 716, 4 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Musketeer rotate: false - xy: 1472, 728 + xy: 756, 4 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Musketman rotate: false - xy: 1472, 692 + xy: 796, 4 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Naresuan's Elephant rotate: false - xy: 1472, 656 + xy: 836, 4 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Nau rotate: false - xy: 1472, 620 + xy: 876, 4 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Norwegian Ski Infantry rotate: false - xy: 1240, 620 + xy: 952, 154 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Nuclear Submarine rotate: false - xy: 1240, 584 + xy: 952, 118 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Panzer rotate: false - xy: 1400, 584 + xy: 1032, 117 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Paratrooper rotate: false - xy: 1400, 548 + xy: 1072, 117 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Pathfinder rotate: false - xy: 1440, 544 + xy: 1032, 41 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Persian Immortal rotate: false - xy: 1480, 548 + xy: 1072, 45 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Pictish Warrior rotate: false - xy: 1400, 512 + xy: 1112, 108 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Pikeman rotate: false - xy: 1440, 508 + xy: 1112, 72 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Pracinha rotate: false - xy: 1484, 920 + xy: 1566, 1108 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Privateer rotate: false - xy: 1484, 884 + xy: 1606, 1108 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Quinquereme rotate: false - xy: 1524, 986 + xy: 1766, 1069 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Rifleman rotate: false - xy: 1524, 950 + xy: 1806, 1036 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Rocket Artillery rotate: false - xy: 1512, 658 + xy: 1380, 762 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Samurai rotate: false - xy: 1520, 586 + xy: 1446, 1108 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Scout rotate: false - xy: 1520, 550 + xy: 1486, 1104 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Sea Beggar rotate: false - xy: 1520, 514 + xy: 1526, 1072 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Settler rotate: false - xy: 1520, 477 + xy: 1566, 1071 size: 32, 29 orig: 32, 29 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Ship of the Line rotate: false - xy: 1564, 921 + xy: 1686, 1064 size: 32, 29 orig: 32, 29 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Siege Tower rotate: false - xy: 1604, 998 + xy: 1726, 1034 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Sipahi rotate: false - xy: 1604, 924 + xy: 1148, 724 size: 32, 30 orig: 32, 30 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Skirmisher rotate: false - xy: 1564, 849 + xy: 1156, 688 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Slinger rotate: false - xy: 1684, 998 + xy: 1156, 652 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Spearman rotate: false - xy: 1604, 888 + xy: 1156, 544 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Submarine rotate: false - xy: 1000, 608 + xy: 1148, 762 size: 32, 26 orig: 32, 26 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Swordsman rotate: false - xy: 1684, 854 + xy: 1194, 324 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Tank rotate: false - xy: 1008, 572 + xy: 1176, 288 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Tercio rotate: false - xy: 1008, 536 + xy: 1176, 252 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Trebuchet rotate: false - xy: 1008, 392 + xy: 1192, 108 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Trireme rotate: false - xy: 1048, 582 + xy: 1192, 72 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Turtle Ship rotate: false - xy: 1724, 874 + xy: 1806, 964 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/War Chariot rotate: false - xy: 1764, 925 + xy: 1926, 958 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/War Elephant rotate: false - xy: 1764, 889 + xy: 1966, 953 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Warrior rotate: false - xy: 1764, 853 + xy: 1886, 924 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/WaterUnit rotate: false - xy: 1764, 819 + xy: 1926, 924 size: 32, 26 orig: 32, 26 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Winged Hussar rotate: false - xy: 1844, 886 + xy: 1356, 1035 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Work Boats rotate: false - xy: 1844, 850 + xy: 1356, 999 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 TileSets/FantasyHex/Units/Worker rotate: false - xy: 1844, 814 + xy: 1396, 1072 size: 32, 28 orig: 32, 28 offset: 0, 0 index: -1 UnitPromotionIcons/Accuracy rotate: false - xy: 1994, 1884 + xy: 1994, 1886 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Air Repair rotate: false - xy: 652, 611 + xy: 760, 721 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Air Targeting rotate: false - xy: 868, 781 + xy: 976, 891 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Targeting rotate: false - xy: 868, 781 + xy: 976, 891 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Ambush rotate: false - xy: 1084, 997 + xy: 1192, 1107 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Anti-Armor rotate: false - xy: 1084, 997 + xy: 1192, 1107 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Amphibious rotate: false - xy: 1192, 1105 + xy: 1300, 1215 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Landing Party rotate: false - xy: 1192, 1105 + xy: 1300, 1215 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Armor Plating rotate: false - xy: 1300, 1196 + xy: 436, 226 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Barrage rotate: false - xy: 436, 206 + xy: 436, 168 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Besiege rotate: false - xy: 544, 381 + xy: 652, 491 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Siege rotate: false - xy: 544, 381 + xy: 652, 491 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Blitz rotate: false - xy: 436, 148 + xy: 436, 110 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Boarding Party rotate: false - xy: 436, 90 + xy: 436, 52 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Bombardment rotate: false - xy: 436, 32 + xy: 544, 316 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Charge rotate: false - xy: 1368, 1236 + xy: 868, 783 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Coastal Raider rotate: false - xy: 1600, 1236 + xy: 876, 725 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Cover rotate: false - xy: 1832, 1236 + xy: 934, 667 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 PolicyIcons/Discipline rotate: false - xy: 1832, 1236 + xy: 934, 667 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Drill rotate: false - xy: 652, 553 + xy: 1358, 1215 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Evasion rotate: false - xy: 710, 553 + xy: 1474, 1238 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Extended Range rotate: false - xy: 768, 615 + xy: 1532, 1238 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Operational Range rotate: false - xy: 768, 615 + xy: 1532, 1238 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Flight Deck rotate: false - xy: 826, 615 + xy: 1706, 1238 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Formation rotate: false - xy: 926, 781 + xy: 1822, 1238 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Great Generals rotate: false - xy: 1416, 1178 + xy: 1532, 1180 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Quick Study rotate: false - xy: 1416, 1178 + xy: 1532, 1180 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Haka War Dance rotate: false - xy: 1474, 1178 + xy: 1590, 1180 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Heal Instantly rotate: false - xy: 1590, 1178 + xy: 1706, 1180 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Home Sweet Home rotate: false - xy: 1648, 1178 + xy: 1764, 1180 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Ignore terrain cost rotate: false - xy: 1585, 1618 + xy: 1585, 1620 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 UnitPromotionIcons/Indirect Fire rotate: false - xy: 1822, 1178 + xy: 1938, 1180 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Interception rotate: false - xy: 1938, 1178 + xy: 602, 356 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Logistics rotate: false - xy: 494, 130 + xy: 660, 317 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/March rotate: false - xy: 494, 14 + xy: 718, 317 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Medic rotate: false - xy: 562, 323 + xy: 718, 259 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Mobility rotate: false - xy: 610, 149 + xy: 1200, 1049 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Morale rotate: false - xy: 610, 33 + xy: 1258, 1049 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Pictish Courage rotate: false - xy: 602, 495 + xy: 826, 547 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Rejuvenation rotate: false - xy: 984, 831 + xy: 1050, 717 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Scouting rotate: false - xy: 942, 607 + xy: 1058, 543 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Sentry rotate: false - xy: 942, 607 + xy: 1058, 543 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Shock rotate: false - xy: 1208, 931 + xy: 942, 493 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Slinger Withdraw rotate: false - xy: 1266, 989 + xy: 1000, 485 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Sortie rotate: false - xy: 1208, 873 + xy: 728, 489 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Supply rotate: false - xy: 892, 491 + xy: 786, 431 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Survivalism rotate: false - xy: 950, 549 + xy: 844, 435 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Volley rotate: false - xy: 620, 379 + xy: 1018, 369 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Wolfpack rotate: false - xy: 620, 321 + xy: 776, 373 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 UnitPromotionIcons/Woodsman rotate: false - xy: 678, 321 + xy: 776, 315 size: 50, 50 orig: 50, 50 offset: 0, 0 diff --git a/android/assets/game.png b/android/assets/game.png index 79675df173..ab00b50f32 100644 Binary files a/android/assets/game.png and b/android/assets/game.png differ diff --git a/android/assets/jsons/Civ V - Gods & Kings/TileImprovements.json b/android/assets/jsons/Civ V - Gods & Kings/TileImprovements.json index f03e63ea19..79a5331775 100644 --- a/android/assets/jsons/Civ V - Gods & Kings/TileImprovements.json +++ b/android/assets/jsons/Civ V - Gods & Kings/TileImprovements.json @@ -44,22 +44,27 @@ "name": "Camp", "turnsToBuild": 7, "techRequired": "Trapping", - "uniques": ["Does not need removal of [Forest]","Does not need removal of [Jungle]","[+1 Gold] "], + "uniques": ["Does not need removal of [Forest]","Does not need removal of [Jungle]","[+1 Gold] ", "Can only be built to improve a resource"], "shortcutKey": "C" }, { "name": "Oil well", - "terrainsCanBeBuiltOn": ["Coast"], "turnsToBuild": 9, "techRequired": "Biology", - "uniques": ["Cannot be built on [Coast] tiles "], + "uniques": ["Can only be built to improve a resource", "Cannot be built on [Water] tiles"], "shortcutKey": "W" }, + { + "name": "Offshore Platform", + "techRequired": "Refrigeration", + "uniques": ["Can only be built to improve a resource", "Can only be built on [Water] tiles"], + "shortcutKey": "P" + }, { "name": "Pasture", "turnsToBuild": 8, "techRequired": "Animal Husbandry", - "uniques": ["[+1 Food] "], + "uniques": ["[+1 Food] ", "Can only be built to improve a resource"], "shortcutKey": "P" }, { @@ -67,14 +72,14 @@ "turnsToBuild": 6, "gold": 1, "techRequired": "Calendar", - "uniques": ["[+1 Food] "], + "uniques": ["[+1 Food] ", "Can only be built to improve a resource"], "shortcutKey": "P" }, { "name": "Quarry", "turnsToBuild": 8, "techRequired": "Masonry", - "uniques": ["[+1 Production] "], + "uniques": ["[+1 Production] ", "Can only be built to improve a resource"], "shortcutKey": "Q" }, { @@ -82,7 +87,8 @@ "terrainsCanBeBuiltOn": ["Coast"], "food": 1, "techRequired": "Sailing", - "uniques": ["[+1 Gold] "] + "uniques": ["[+1 Gold] ", "Can only be built to improve a resource"], + "shortcutKey": "F" }, // Military improvement @@ -98,6 +104,7 @@ // Transportation { "name": "Road", + "terrainsCanBeBuiltOn": ["Land"], "turnsToBuild": 4, "techRequired": "The Wheel", // "Costs [1] gold per turn when in your territory" does nothing and is only to inform the user @@ -111,6 +118,7 @@ }, { "name": "Railroad", + "terrainsCanBeBuiltOn": ["Land"], "turnsToBuild": 4, "techRequired": "Railroads", "uniques": ["Can be built outside your borders", "Costs [2] gold per turn when in your territory"], @@ -119,10 +127,11 @@ }, // Removals + // Any improvement that starts with 'Remove ' is automatically changed into + // the improvement that removes the terrainfeature after it. { "name": "Remove Forest", "turnsToBuild": 4, - "terrainsCanBeBuiltOn": ["Forest"], "techRequired": "Mining", "uniques": ["Can be built outside your borders"], "shortcutKey": "X", @@ -131,7 +140,6 @@ { "name": "Remove Jungle", "turnsToBuild": 7, - "terrainsCanBeBuiltOn": ["Jungle"], "techRequired": "Bronze Working", "uniques": ["Can be built outside your borders"], "shortcutKey": "X" @@ -139,15 +147,13 @@ { "name": "Remove Fallout", "turnsToBuild": 2, - "terrainsCanBeBuiltOn": ["Fallout"], - // Has no tile improvements as it can always be built + // Has no tech requirements as it can always be built "uniques": ["Can be built outside your borders"], "shortcutKey": "X" }, { "name": "Remove Marsh", "turnsToBuild": 6, - "terrainsCanBeBuiltOn": ["Marsh"], "techRequired": "Masonry", "uniques": ["Can be built outside your borders"], "shortcutKey": "X" @@ -173,43 +179,51 @@ // Great Person improvements { "name": "Academy", + "terrainsCanBeBuiltOn": ["Land"], "science": 8, "uniques": ["Great Improvement", "[+2 Science] ", "[+2 Science] "] }, { "name": "Landmark", + "terrainsCanBeBuiltOn": ["Land"], "culture": 6, "uniques": ["Great Improvement"] }, { "name": "Manufactory", + "terrainsCanBeBuiltOn": ["Land"], "production": 4, "uniques": ["Great Improvement", "[+1 Production] "] }, { "name": "Customs house", + "terrainsCanBeBuiltOn": ["Land"], "gold": 4, "uniques": ["Great Improvement", "[+1 Gold] "] }, { "name": "Holy site", + "terrainsCanBeBuiltOn": ["Land"], "faith": 6, "uniques": ["Great Improvement"] }, { "name": "Citadel", + "terrainsCanBeBuiltOn": ["Land"], "uniques": [ "Great Improvement", "Gives a defensive bonus of [100]%", "Adjacent enemy units ending their turn take [30] damage", "Can be built just outside your borders", - "Constructing it will take over the tiles around it and assign them to your closest city"] + "Constructing it will take over the tiles around it and assign them to your closest city" + ] }, //Civilization unique improvements { "name": "Moai", "uniqueTo": "Polynesia", + "terrainsCanBeBuiltOn": ["Land"], "culture": 1, "turnsToBuild": 4, "uniques": ["Can only be built on [Coastal] tiles", "[+1 Culture] for each adjacent [Moai]", "[+1 Gold] "], @@ -240,26 +254,31 @@ "shortcutKey": "F" }, + // Unbuildable improvements { - "name": "Ancient ruins", - "uniques": ["Unpillagable", "Provides a random bonus when entered"] + "name": "Ancient ruins", + "terrainsCanBeBuiltOn": ["Land"], + "uniques": ["Unpillagable", "Provides a random bonus when entered", "Unbuildable"] }, { - "name": "City ruins", - "uniques": ["Unpillagable"], + "name": "City ruins", + "terrainsCanBeBuiltOn": ["Land"], + "uniques": ["Unpillagable", "Unbuildable"], "civilopediaText": [{"text":"A bleak reminder of the destruction wreaked by War"}] }, { - "name": "City center", - "uniques": ["Unpillagable", "Indestructible"], + "name": "City center", + "terrainsCanBeBuiltOn": ["Land"], + "uniques": ["Unpillagable", "Irremovable", "Unbuildable"], "civilopediaText": [ {"text":"Marks the center of a city"}, {"text":"Appearance changes with the technological era of the owning civilization"} ] }, { - "name": "Barbarian encampment", - "uniques": ["Unpillagable"], + "name": "Barbarian encampment", + "terrainsCanBeBuiltOn": ["Land"], + "uniques": ["Unpillagable", "Unbuildable"], "civilopediaText": [{"text":"Home to uncivilized barbarians, will spawn a hostile unit from time to time"}] } ] diff --git a/android/assets/jsons/Civ V - Gods & Kings/TileResources.json b/android/assets/jsons/Civ V - Gods & Kings/TileResources.json index db7e4285e0..5b22cae1eb 100644 --- a/android/assets/jsons/Civ V - Gods & Kings/TileResources.json +++ b/android/assets/jsons/Civ V - Gods & Kings/TileResources.json @@ -157,7 +157,7 @@ "revealedBy": "Biology", "terrainsCanBeFoundOn": ["Desert","Coast","Tundra","Snow","Marsh","Jungle"], "production": 1, - "improvement": "Oil well", + "improvedBy": ["Oil well", "Offshore Platform"], "improvementStats": {"production": 3}, "uniques": ["Deposits in [Coast] tiles always provide [4] resources", "Guaranteed with Strategic Balance resource option", diff --git a/android/assets/jsons/Civ V - Vanilla/TileImprovements.json b/android/assets/jsons/Civ V - Vanilla/TileImprovements.json index 35f69d1e1f..d5880e5982 100644 --- a/android/assets/jsons/Civ V - Vanilla/TileImprovements.json +++ b/android/assets/jsons/Civ V - Vanilla/TileImprovements.json @@ -44,22 +44,27 @@ "name": "Camp", "turnsToBuild": 7, "techRequired": "Trapping", - "uniques": ["Does not need removal of [Forest]","Does not need removal of [Jungle]","[+1 Gold] "], + "uniques": ["Does not need removal of [Forest]","Does not need removal of [Jungle]","[+1 Gold] ", "Can only be built to improve a resource"], "shortcutKey": "C" }, { "name": "Oil well", - "terrainsCanBeBuiltOn": ["Coast"], "turnsToBuild": 9, "techRequired": "Biology", - "uniques": ["Cannot be built on [Coast] tiles "], + "uniques": ["Can only be built to improve a resource", "Cannot be built on [Water] tiles"], "shortcutKey": "W" }, + { + "name": "Offshore Platform", + "techRequired": "Refrigeration", + "uniques": ["Can only be built to improve a resource", "Can only be built on [Water] tiles"], + "shortcutKey": "P" + }, { "name": "Pasture", "turnsToBuild": 8, "techRequired": "Animal Husbandry", - "uniques": ["[+1 Food] "], + "uniques": ["[+1 Food] ", "Can only be built to improve a resource"], "shortcutKey": "P" }, { @@ -67,14 +72,14 @@ "turnsToBuild": 6, "gold": 1, "techRequired": "Calendar", - "uniques": ["[+1 Food] "], + "uniques": ["[+1 Food] ", "Can only be built to improve a resource"], "shortcutKey": "P" }, { "name": "Quarry", "turnsToBuild": 8, "techRequired": "Masonry", - "uniques": ["[+1 Production] "], + "uniques": ["[+1 Production] ", "Can only be built to improve a resource"], "shortcutKey": "Q" }, { @@ -82,7 +87,8 @@ "terrainsCanBeBuiltOn": ["Coast"], "food": 1, "techRequired": "Sailing", - "uniques": ["[+1 Gold] "] + "uniques": ["[+1 Gold] ", "Can only be built to improve a resource"], + "shortcutKey": "F" }, // Military improvement @@ -98,6 +104,7 @@ // Transportation { "name": "Road", + "terrainsCanBeBuiltOn": ["Land"], "turnsToBuild": 4, "techRequired": "The Wheel", // "Costs [1] gold per turn when in your territory" does nothing and is only to inform the user @@ -111,6 +118,7 @@ }, { "name": "Railroad", + "terrainsCanBeBuiltOn": ["Land"], "turnsToBuild": 4, "techRequired": "Railroads", "uniques": ["Can be built outside your borders", "Costs [2] gold per turn when in your territory"], @@ -119,10 +127,11 @@ }, // Removals + // Any improvement that starts with 'Remove ' is automatically changed into + // the improvement that removes the terrainfeature after it. { "name": "Remove Forest", "turnsToBuild": 4, - "terrainsCanBeBuiltOn": ["Forest"], "techRequired": "Mining", "uniques": ["Can be built outside your borders"], "shortcutKey": "X", @@ -131,7 +140,6 @@ { "name": "Remove Jungle", "turnsToBuild": 7, - "terrainsCanBeBuiltOn": ["Jungle"], "techRequired": "Bronze Working", "uniques": ["Can be built outside your borders"], "shortcutKey": "X" @@ -139,15 +147,13 @@ { "name": "Remove Fallout", "turnsToBuild": 2, - "terrainsCanBeBuiltOn": ["Fallout"], - // Has no tile improvements as it can always be built + // Has no tech requirements as it can always be built "uniques": ["Can be built outside your borders"], "shortcutKey": "X" }, { "name": "Remove Marsh", "turnsToBuild": 6, - "terrainsCanBeBuiltOn": ["Marsh"], "techRequired": "Masonry", "uniques": ["Can be built outside your borders"], "shortcutKey": "X" @@ -173,43 +179,51 @@ // Great Person improvements { "name": "Academy", + "terrainsCanBeBuiltOn": ["Land"], "science": 8, "uniques": ["Great Improvement", "[+2 Science] "] }, { "name": "Landmark", + "terrainsCanBeBuiltOn": ["Land"], "culture": 6, "uniques": ["Great Improvement"] }, { "name": "Manufactory", + "terrainsCanBeBuiltOn": ["Land"], "production": 4, "uniques": ["Great Improvement", "[+1 Production] "] }, { "name": "Customs house", + "terrainsCanBeBuiltOn": ["Land"], "gold": 4, "uniques": ["Great Improvement", "[+1 Gold] "] }, { "name": "Holy site", + "terrainsCanBeBuiltOn": ["Land"], "faith": 6, "uniques": ["Great Improvement"] }, { "name": "Citadel", + "terrainsCanBeBuiltOn": ["Land"], "uniques": [ "Great Improvement", "Gives a defensive bonus of [100]%", "Adjacent enemy units ending their turn take [30] damage", "Can be built just outside your borders", - "Constructing it will take over the tiles around it and assign them to your closest city"] + "Constructing it will take over the tiles around it and assign them to your closest city" + ] }, //Civilization unique improvements { "name": "Moai", "uniqueTo": "Polynesia", + "terrainsCanBeBuiltOn": ["Land"], "culture": 1, "turnsToBuild": 4, "uniques": ["Can only be built on [Coastal] tiles", "[+1 Culture] for each adjacent [Moai]", "[+1 Gold] "], @@ -230,26 +244,31 @@ "shortcutKey": "F" }, + // Unbuildable improvements { - "name": "Ancient ruins", - "uniques": ["Unpillagable", "Provides a random bonus when entered"] + "name": "Ancient ruins", + "terrainsCanBeBuiltOn": ["Land"], + "uniques": ["Unpillagable", "Provides a random bonus when entered", "Unbuildable"] }, { - "name": "City ruins", - "uniques": ["Unpillagable"], + "name": "City ruins", + "terrainsCanBeBuiltOn": ["Land"], + "uniques": ["Unpillagable", "Unbuildable"], "civilopediaText": [{"text":"A bleak reminder of the destruction wreaked by War"}] }, { - "name": "City center", - "uniques": ["Unpillagable", "Indestructible"], + "name": "City center", + "terrainsCanBeBuiltOn": ["Land"], + "uniques": ["Unpillagable", "Irremovable", "Unbuildable"], "civilopediaText": [ {"text":"Marks the center of a city"}, {"text":"Appearance changes with the technological era of the owning civilization"} ] }, { - "name": "Barbarian encampment", - "uniques": ["Unpillagable"], + "name": "Barbarian encampment", + "terrainsCanBeBuiltOn": ["Land"], + "uniques": ["Unpillagable", "Unbuildable"], "civilopediaText": [{"text":"Home to uncivilized barbarians, will spawn a hostile unit from time to time"}] } ] diff --git a/android/assets/jsons/Civ V - Vanilla/TileResources.json b/android/assets/jsons/Civ V - Vanilla/TileResources.json index 21b86620bb..2d958eb7f3 100644 --- a/android/assets/jsons/Civ V - Vanilla/TileResources.json +++ b/android/assets/jsons/Civ V - Vanilla/TileResources.json @@ -160,7 +160,7 @@ "revealedBy": "Biology", "terrainsCanBeFoundOn": ["Desert","Coast","Tundra","Snow","Marsh","Jungle"], "production": 1, - "improvement": "Oil well", + "improvedBy": ["Oil well", "Offshore Platform"], "improvementStats": {"production": 3}, "uniques": ["Deposits in [Coast] tiles always provide [4] resources", "Guaranteed with Strategic Balance resource option", diff --git a/core/src/com/unciv/Constants.kt b/core/src/com/unciv/Constants.kt index 251db39827..6ac20c8ddc 100644 --- a/core/src/com/unciv/Constants.kt +++ b/core/src/com/unciv/Constants.kt @@ -30,6 +30,7 @@ object Constants { val vegetation = arrayOf(forest, jungle) // Note the difference in case. **Not** interchangeable! + // TODO this is very opaque behaviour to modders /** The "Fresh water" terrain _unique_ */ const val freshWater = "Fresh water" /** The "Fresh Water" terrain _filter_ */ diff --git a/core/src/com/unciv/logic/BarbarianManager.kt b/core/src/com/unciv/logic/BarbarianManager.kt index 3f8bf475a2..5b84715e12 100644 --- a/core/src/com/unciv/logic/BarbarianManager.kt +++ b/core/src/com/unciv/logic/BarbarianManager.kt @@ -236,7 +236,7 @@ class Encampment() { || it.isCityCenter() || it.getFirstUnit() != null || (it.isWater && !canSpawnBoats) - || (it.hasUnique(UniqueType.FreshWater) && it.isWater) // No Lakes + || (it.terrainHasUnique(UniqueType.FreshWater) && it.isWater) // No Lakes } if (validTiles.isEmpty()) return false diff --git a/core/src/com/unciv/logic/automation/ConstructionAutomation.kt b/core/src/com/unciv/logic/automation/ConstructionAutomation.kt index 6a5b1c10a5..0b1c878b88 100644 --- a/core/src/com/unciv/logic/automation/ConstructionAutomation.kt +++ b/core/src/com/unciv/logic/automation/ConstructionAutomation.kt @@ -162,10 +162,12 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){ } for (i in 1..10) bfs.nextStep() if (!bfs.getReachedTiles() - .any { it.hasViewableResource(civInfo) && it.improvement == null && it.getOwner() == civInfo - && it.tileResource.improvement != null - && it.canBuildImprovement(it.ruleset.tileImprovements[it.tileResource.improvement]!!, civInfo) + .any { tile -> + tile.hasViewableResource(civInfo) && tile.improvement == null && tile.getOwner() == civInfo + && tile.tileResource.getImprovements().any { + tile.canBuildImprovement(tile.ruleset.tileImprovements[it]!!, civInfo) } + } ) return addChoice( diff --git a/core/src/com/unciv/logic/automation/SpecificUnitAutomation.kt b/core/src/com/unciv/logic/automation/SpecificUnitAutomation.kt index 22cb191d67..18884ed0d2 100644 --- a/core/src/com/unciv/logic/automation/SpecificUnitAutomation.kt +++ b/core/src/com/unciv/logic/automation/SpecificUnitAutomation.kt @@ -38,8 +38,8 @@ object SpecificUnitAutomation { unit.movement.headTowards(closestReachableResource) // could be either fishing boats or oil well - val improvement = closestReachableResource.tileResource.improvement - if (unit.currentTile == closestReachableResource && improvement != null) + val isImprovable = closestReachableResource.tileResource.getImprovements().any() + if (isImprovable && unit.currentTile == closestReachableResource) UnitActions.getWaterImprovementAction(unit)?.action?.invoke() } } diff --git a/core/src/com/unciv/logic/automation/WorkerAutomation.kt b/core/src/com/unciv/logic/automation/WorkerAutomation.kt index 70dd44cc72..59a2eb1704 100644 --- a/core/src/com/unciv/logic/automation/WorkerAutomation.kt +++ b/core/src/com/unciv/logic/automation/WorkerAutomation.kt @@ -299,7 +299,7 @@ class WorkerAutomation( if (chosenImprovement != null && tile.canBuildImprovement(chosenImprovement, civInfo) && unit.canBuildImprovement(chosenImprovement, tile)) return true } else if (!tile.containsGreatImprovement() && tile.hasViewableResource(civInfo) - && tile.tileResource.improvement != tile.improvement + && tile.tileResource.isImprovedBy(tile.improvement!!) && (chooseImprovement(unit, tile) // if the chosen improvement is not null and buildable .let { it != null && tile.canBuildImprovement(it, civInfo) && unit.canBuildImprovement(it, tile)})) return true @@ -354,17 +354,14 @@ class WorkerAutomation( tile.terrainFeatures.isNotEmpty() && isUnbuildableAndRemovable(lastTerrain) && !isResourceImprovementAllowedOnFeature(tile) -> Constants.remove + lastTerrain.name - else -> tile.tileResource.improvement + else -> tile.tileResource.getImprovements().firstOrNull { it in potentialTileImprovements } } val improvementString = when { tile.improvementInProgress != null -> tile.improvementInProgress!! - improvementStringForResource != null -> { - if (potentialTileImprovements.containsKey(improvementStringForResource)) - improvementStringForResource - // if this is a resource that HAS an improvement, but this unit can't build it, don't waste your time - else return null - } + improvementStringForResource != null -> improvementStringForResource + // if this is a resource that HAS an improvement, but this unit can't build it, don't waste your time + tile.resource != null && tile.tileResource.getImprovements().any() -> return null tile.containsGreatImprovement() -> return null tile.containsUnfinishedGreatImprovement() -> return null @@ -392,11 +389,10 @@ class WorkerAutomation( * Assumes the caller ensured that terrainFeature and resource are both present! */ private fun isResourceImprovementAllowedOnFeature(tile: TileInfo): Boolean { - val resourceImprovementName = tile.tileResource.improvement - ?: return false - val resourceImprovement = ruleSet.tileImprovements[resourceImprovementName] - ?: return false - return tile.terrainFeatures.any { resourceImprovement.isAllowedOnFeature(it) } + return tile.tileResource.getImprovements().any { resourceImprovementName -> + val resourceImprovement = ruleSet.tileImprovements[resourceImprovementName] ?: return false + tile.terrainFeatures.any { resourceImprovement.isAllowedOnFeature(it) } + } } /** diff --git a/core/src/com/unciv/logic/battle/Battle.kt b/core/src/com/unciv/logic/battle/Battle.kt index 8ec8da15db..dfe9613cd2 100644 --- a/core/src/com/unciv/logic/battle/Battle.kt +++ b/core/src/com/unciv/logic/battle/Battle.kt @@ -732,7 +732,7 @@ object Battle { } // Pillage improvements, remove roads, add fallout - if (tile.improvement != null && !tile.getTileImprovement()!!.hasUnique(UniqueType.Indestructible)) { + if (tile.improvement != null && !tile.getTileImprovement()!!.hasUnique(UniqueType.Irremovable)) { if (tile.getTileImprovement()!!.hasUnique(UniqueType.Unpillagable)) { tile.improvement = null } else { @@ -741,29 +741,28 @@ object Battle { } tile.roadStatus = RoadStatus.None if (tile.isLand && !tile.isImpassible() && !tile.isCityCenter()) { - if (tile.hasUnique(UniqueType.DestroyableByNukesChance)) { + if (tile.terrainHasUnique(UniqueType.DestroyableByNukesChance)) { for (terrainFeature in tile.terrainFeatureObjects) { for (unique in terrainFeature.getMatchingUniques(UniqueType.DestroyableByNukesChance)) { if (Random().nextFloat() >= unique.params[0].toFloat() / 100f) continue tile.removeTerrainFeature(terrainFeature.name) - if (!tile.terrainFeatures.contains("Fallout") && !tile.hasUnique(UniqueType.Indestructible)) + if (!tile.terrainFeatures.contains("Fallout")) tile.addTerrainFeature("Fallout") } } - } else if (Random().nextFloat() < 0.5f && !tile.terrainFeatures.contains("Fallout") && !tile.hasUnique(UniqueType.Indestructible)) { + } else if (Random().nextFloat() < 0.5f && !tile.terrainFeatures.contains("Fallout")) { tile.addTerrainFeature("Fallout") } - if (!tile.hasUnique(UniqueType.DestroyableByNukes)) return - + if (!tile.terrainHasUnique(UniqueType.DestroyableByNukes)) return + // Deprecated as of 3.19.19 -- If removed, the two successive `if`s above should be merged - val destructionChance = if (tile.hasUnique(UniqueType.ResistsNukes)) 0.25f + val destructionChance = if (tile.terrainHasUnique(UniqueType.ResistsNukes)) 0.25f else 0.5f if (Random().nextFloat() < destructionChance) { for (terrainFeature in tile.terrainFeatureObjects) if (terrainFeature.hasUnique(UniqueType.DestroyableByNukes)) tile.removeTerrainFeature(terrainFeature.name) - if (!tile.hasUnique(UniqueType.Indestructible)) - tile.addTerrainFeature("Fallout") + tile.addTerrainFeature("Fallout") } // } diff --git a/core/src/com/unciv/logic/city/CityInfo.kt b/core/src/com/unciv/logic/city/CityInfo.kt index 760fec3026..c4ccddcc6e 100644 --- a/core/src/com/unciv/logic/city/CityInfo.kt +++ b/core/src/com/unciv/logic/city/CityInfo.kt @@ -410,12 +410,14 @@ class CityInfo { if (resource.revealedBy != null && !civInfo.tech.isResearched(resource.revealedBy!!)) return 0 // Even if the improvement exists (we conquered an enemy city or somesuch) or we have a city on it, we won't get the resource until the correct tech is researched - if (resource.improvement != null) { - val improvement = getRuleset().tileImprovements[resource.improvement!!]!! - if (improvement.techRequired != null && !civInfo.tech.isResearched(improvement.techRequired!!)) return 0 + if (resource.getImprovements().any()) { + if (!resource.getImprovements().any { improvementString -> + val improvement = getRuleset().tileImprovements[improvementString]!! + improvement.techRequired == null || civInfo.tech.isResearched(improvement.techRequired!!) + }) return 0 } - if (resource.improvement == tileInfo.improvement || tileInfo.isCityCenter() + if ((tileInfo.improvement != null && resource.isImprovedBy(tileInfo.improvement!!)) || tileInfo.isCityCenter() // Per https://gaming.stackexchange.com/questions/53155/do-manufactories-and-customs-houses-sacrifice-the-strategic-or-luxury-resources || resource.resourceType == ResourceType.Strategic && tileInfo.containsGreatImprovement() ) { diff --git a/core/src/com/unciv/logic/city/CityStats.kt b/core/src/com/unciv/logic/city/CityStats.kt index 8385d065ba..161ddb859d 100644 --- a/core/src/com/unciv/logic/city/CityStats.kt +++ b/core/src/com/unciv/logic/city/CityStats.kt @@ -378,7 +378,7 @@ class CityStats(val cityInfo: CityInfo) { || cityInfo.isWorked(it) || it.owningCity == cityInfo && (it.getTileImprovement() ?.hasUnique(UniqueType.TileProvidesYieldWithoutPopulation) == true - || it.hasUnique(UniqueType.TileProvidesYieldWithoutPopulation)) + || it.terrainHasUnique(UniqueType.TileProvidesYieldWithoutPopulation)) }) stats.add(cell.getTileStats(cityInfo, cityInfo.civInfo, localUniqueCache)) statsFromTiles = stats diff --git a/core/src/com/unciv/logic/civilization/CivInfoTransientUpdater.kt b/core/src/com/unciv/logic/civilization/CivInfoTransientUpdater.kt index de09626579..afc0f551d4 100644 --- a/core/src/com/unciv/logic/civilization/CivInfoTransientUpdater.kt +++ b/core/src/com/unciv/logic/civilization/CivInfoTransientUpdater.kt @@ -122,7 +122,7 @@ class CivInfoTransientUpdater(val civInfo: CivilizationInfo) { var goldGained = 0 val discoveredNaturalWonders = civInfo.gameInfo.civilizations.filter { it != civInfo && it.isMajorCiv() } .flatMap { it.naturalWonders } - if (tile.hasUnique(UniqueType.GrantsGoldToFirstToDiscover) + if (tile.terrainHasUnique(UniqueType.GrantsGoldToFirstToDiscover) && !discoveredNaturalWonders.contains(tile.naturalWonder!!)) { goldGained += 500 } diff --git a/core/src/com/unciv/logic/map/MapUnit.kt b/core/src/com/unciv/logic/map/MapUnit.kt index 5ee443a852..a6f7a7db9b 100644 --- a/core/src/com/unciv/logic/map/MapUnit.kt +++ b/core/src/com/unciv/logic/map/MapUnit.kt @@ -20,8 +20,10 @@ import com.unciv.models.ruleset.tile.TileImprovement import com.unciv.models.ruleset.unique.* import com.unciv.models.ruleset.unit.BaseUnit import com.unciv.models.ruleset.unit.UnitType +import com.unciv.models.stats.Stats import com.unciv.ui.utils.filterAndLogic import com.unciv.ui.utils.toPercent +import com.unciv.ui.worldscreen.unit.UnitActions import java.text.DecimalFormat import kotlin.math.pow @@ -661,10 +663,11 @@ class MapUnit { tile.improvementInProgress == RoadStatus.Road.name -> tile.roadStatus = RoadStatus.Road tile.improvementInProgress == RoadStatus.Railroad.name -> tile.roadStatus = RoadStatus.Railroad else -> { - tile.improvement = tile.improvementInProgress - if (tile.resource != null) civInfo.updateDetailedCivResources() + val improvement = civInfo.gameInfo.ruleSet.tileImprovements[tile.improvementInProgress]!! + improvement.handleImprovementCompletion(this) } } + tile.improvementInProgress = null } @@ -851,6 +854,30 @@ class MapUnit { assignOwner(recipient) recipient.updateViewableTiles() } + + /** Destroys the unit and gives stats if its a great person */ + fun consume() { + addStatsPerGreatPersonUsage() + destroy() + } + + private fun addStatsPerGreatPersonUsage() { + if (!isGreatPerson()) return + + val gainedStats = Stats() + for (unique in civInfo.getMatchingUniques(UniqueType.ProvidesGoldWheneverGreatPersonExpended)) { + gainedStats.gold += (100 * civInfo.gameInfo.gameParameters.gameSpeed.modifier).toInt() + } + for (unique in civInfo.getMatchingUniques(UniqueType.ProvidesStatsWheneverGreatPersonExpended)) { + gainedStats.add(unique.stats) + } + + if (gainedStats.isEmpty()) return + + for (stat in gainedStats) + civInfo.addStat(stat.key, stat.value.toInt()) + civInfo.addNotification("By expending your [$name] you gained [${gainedStats}]!", getTile().position, name) + } fun removeFromTile() = currentTile.removeUnit(this) diff --git a/core/src/com/unciv/logic/map/TileInfo.kt b/core/src/com/unciv/logic/map/TileInfo.kt index e54b1f6786..f4a5ab1846 100644 --- a/core/src/com/unciv/logic/map/TileInfo.kt +++ b/core/src/com/unciv/logic/map/TileInfo.kt @@ -243,11 +243,19 @@ open class TileInfo { fun isRoughTerrain() = getAllTerrains().any{ it.isRough() } - fun hasUnique(uniqueType: UniqueType) = getAllTerrains().any { it.hasUnique(uniqueType) } - fun getMatchingUniques(uniqueType: UniqueType, stateForConditionals: StateForConditionals = StateForConditionals(tile=this) ): Sequence { + /** Checks whether any of the TERRAINS of this tile has a certain unqiue */ + fun terrainHasUnique(uniqueType: UniqueType) = getAllTerrains().any { it.hasUnique(uniqueType) } + /** Get all uniques of this type that any TERRAIN on this tile has */ + fun getTerrainMatchingUniques(uniqueType: UniqueType, stateForConditionals: StateForConditionals = StateForConditionals(tile=this) ): Sequence { return getAllTerrains().flatMap { it.getMatchingUniques(uniqueType, stateForConditionals) } } - + + /** Get all uniques of this type that any part of this tile has: terrains, improvement, resource */ + fun getMatchingUniques(uniqueType: UniqueType, stateForConditionals: StateForConditionals = StateForConditionals(tile=this)) = + getTerrainMatchingUniques(uniqueType, stateForConditionals) + + (getTileImprovement()?.getMatchingUniques(uniqueType, stateForConditionals) ?: sequenceOf()) + + if (resource == null) sequenceOf() else tileResource.getMatchingUniques(uniqueType, stateForConditionals) + fun getWorkingCity(): CityInfo? { val civInfo = getOwner() ?: return null return civInfo.cities.firstOrNull { it.isWorked(this) } @@ -256,7 +264,7 @@ open class TileInfo { fun isWorked(): Boolean = getWorkingCity() != null fun providesYield() = getCity() != null && (isCityCenter() || isWorked() || getTileImprovement()?.hasUnique(UniqueType.TileProvidesYieldWithoutPopulation) == true - || hasUnique(UniqueType.TileProvidesYieldWithoutPopulation)) + || terrainHasUnique(UniqueType.TileProvidesYieldWithoutPopulation)) fun isLocked(): Boolean { val workingCity = getWorkingCity() @@ -405,7 +413,7 @@ open class TileInfo { fun getImprovementStats(improvement: TileImprovement, observingCiv: CivilizationInfo, city: CityInfo?): Stats { val stats = improvement.cloneStats() - if (hasViewableResource(observingCiv) && tileResource.improvement == improvement.name + if (hasViewableResource(observingCiv) && tileResource.isImprovedBy(improvement.name) && tileResource.improvementStats != null ) stats.add(tileResource.improvementStats!!.clone()) // resource-specific improvement @@ -463,40 +471,6 @@ open class TileInfo { return stats } - /** Returns true if the [improvement] can be built on this [TileInfo] */ - fun canBuildImprovement(improvement: TileImprovement, civInfo: CivilizationInfo): Boolean { - return when { - improvement.uniqueTo != null && improvement.uniqueTo != civInfo.civName -> false - improvement.techRequired != null && !civInfo.tech.isResearched(improvement.techRequired!!) -> false - getOwner() != civInfo && !( - improvement.hasUnique(UniqueType.CanBuildOutsideBorders) - || ( // citadel can be built only next to or within own borders - improvement.hasUnique(UniqueType.CanBuildJustOutsideBorders) - && neighbors.any { it.getOwner() == civInfo } - ) - ) -> false - improvement.getMatchingUniques(UniqueType.OnlyAvailableWhen, StateForConditionals.IgnoreConditionals).any { - !it.conditionalsApply(StateForConditionals(civInfo, tile=this)) - } -> false - improvement.getMatchingUniques(UniqueType.ObsoleteWith).any { - civInfo.tech.isResearched(it.params[0]) - } -> return false - improvement.getMatchingUniques(UniqueType.CannotBuildOnTile, StateForConditionals(civInfo=civInfo, tile=this)).any { - matchesTerrainFilter(it.params[0], civInfo) - } -> false - improvement.getMatchingUniques(UniqueType.ConsumesResources).any { - civInfo.getCivResourcesByName()[it.params[1]]!! < it.params[0].toInt() - } -> false - // Calling this function does double the check for 'cannot be build on tile', but this is unavoidable. - // Only in this function do we have the civInfo of the civ, so only here we can check whether - // conditionals apply. Additionally, the function below is also called when determining if - // an improvement can be on the tile in the given ruleset, in which case we do want to - // assume that all conditionals apply, which is done automatically when we don't include - // any state for conditionals. Therefore, duplicating the check is the easiest option. - else -> canImprovementBeBuiltHere(improvement, hasViewableResource(civInfo)) - } - } - // This should be the only adjacency function fun isAdjacentTo(terrainFilter:String): Boolean { // Rivers are odd, as they aren't technically part of any specific tile but still count towards adjacency @@ -505,47 +479,103 @@ open class TileInfo { return (neighbors + this).any { neighbor -> neighbor.matchesFilter(terrainFilter) } } + /** Returns true if the [improvement] can be built on this [TileInfo] */ + fun canBuildImprovement(improvement: TileImprovement, civInfo: CivilizationInfo): Boolean { + val stateForConditionals = StateForConditionals(civInfo, tile=this) + return when { + improvement.uniqueTo != null && improvement.uniqueTo != civInfo.civName -> false + improvement.techRequired != null && !civInfo.tech.isResearched(improvement.techRequired!!) -> false + getOwner() != civInfo && !( + improvement.hasUnique(UniqueType.CanBuildOutsideBorders, stateForConditionals) + || ( // citadel can be built only next to or within own borders + improvement.hasUnique(UniqueType.CanBuildJustOutsideBorders, stateForConditionals) + && neighbors.any { it.getOwner() == civInfo } + ) + ) -> false + improvement.getMatchingUniques(UniqueType.OnlyAvailableWhen, StateForConditionals.IgnoreConditionals).any { + !it.conditionalsApply(stateForConditionals) + } -> false + improvement.getMatchingUniques(UniqueType.ObsoleteWith, stateForConditionals).any { + civInfo.tech.isResearched(it.params[0]) + } -> false + improvement.getMatchingUniques(UniqueType.ConsumesResources, stateForConditionals).any { + civInfo.getCivResourcesByName()[it.params[1]]!! < it.params[0].toInt() + } -> false + improvement.hasUnique(UniqueType.Unbuildable, stateForConditionals) -> false + else -> canImprovementBeBuiltHere(improvement, hasViewableResource(civInfo), stateForConditionals) + } + } + /** Without regards to what CivInfo it is, a lot of the checks are just for the improvement on the tile. * Doubles as a check for the map editor. */ - fun canImprovementBeBuiltHere(improvement: TileImprovement, resourceIsVisible: Boolean = resource != null): Boolean { + private fun canImprovementBeBuiltHere( + improvement: TileImprovement, + resourceIsVisible: Boolean = resource != null, + stateForConditionals: StateForConditionals = StateForConditionals(tile=this) + ): Boolean { val topTerrain = getLastTerrain() return when { improvement.name == this.improvement -> false isCityCenter() -> false - improvement.getMatchingUniques(UniqueType.CannotBuildOnTile, StateForConditionals(tile = this)).any { + // First we handle a few special improvements + // Can only cancel if there is actually an improvement being built + improvement.name == Constants.cancelImprovementOrder -> (this.improvementInProgress != null) + // Can only remove if the feature is actually there + improvement.name.startsWith(Constants.remove) -> terrainFeatures.any { it == improvement.name.removePrefix(Constants.remove) } + // Can only build roads if on land and they are better than the current road + RoadStatus.values().any { it.name == improvement.name } -> !isWater && RoadStatus.valueOf(improvement.name) > roadStatus + // Can always build road removal improvements + improvement.name == roadStatus.removeAction -> true + + // Then we check if there is any reason to not allow this improvement to be build + + // Can't build if there is already an irremovable improvement here + this.improvement != null && getTileImprovement()!!.hasUnique(UniqueType.Irremovable, stateForConditionals) -> false + + // Can't build if any terrain specifically prevents building this improvement + getTerrainMatchingUniques(UniqueType.RestrictedBuildableImprovements, stateForConditionals).any { + unique -> !improvement.matchesFilter(unique.params[0]) + } -> false + + // Can't build if the improvement specifically prevents building on some present feature + improvement.getMatchingUniques(UniqueType.CannotBuildOnTile, stateForConditionals).any { unique -> matchesTerrainFilter(unique.params[0]) } -> false - // Road improvements can change on tiles with irremovable improvements - nothing else can, though. - RoadStatus.values().none { it.name == improvement.name || it.removeAction == improvement.name } - && getTileImprovement().let { it != null && it.hasUnique( UniqueType.Irremovable) } -> false - // Terrain blocks BUILDING improvements - removing things (such as fallout) is fine - !improvement.name.startsWith(Constants.remove) && - getAllTerrains().any { it.getMatchingUniques(UniqueType.RestrictedBuildableImprovements) - .any { unique -> !improvement.matchesFilter(unique.params[0]) } } -> false - - // Decide cancelImprovementOrder earlier, otherwise next check breaks it - improvement.name == Constants.cancelImprovementOrder -> (this.improvementInProgress != null) - // Tiles with no terrains, and no turns to build, are like great improvements - they're placeable - improvement.terrainsCanBeBuiltOn.isEmpty() && improvement.turnsToBuild == 0 && isLand -> true - improvement.terrainsCanBeBuiltOn.contains(topTerrain.name) -> true - improvement.getMatchingUniques(UniqueType.MustBeNextTo).any { + // Can't build if an improvement is only allowed to be built on specific tiles and this is not one of them + // If multiple uniques of this type exists, we want all to match (e.g. Hill _and_ Forest would be meaningful) + improvement.getMatchingUniques(UniqueType.CanOnlyBeBuiltOnTile, stateForConditionals).let { + it.any() && it.any { unique -> !matchesTerrainFilter(unique.params[0]) } + } -> false + + // Can't build if the improvement requires an adjacent terrain that is not present + improvement.getMatchingUniques(UniqueType.MustBeNextTo, stateForConditionals).any { !isAdjacentTo(it.params[0]) } -> false - !isWater && RoadStatus.values().any { it.name == improvement.name && it > roadStatus } -> true - improvement.name == roadStatus.removeAction -> true + + // Can't build on unbuildable terrains - EXCEPT when specifically allowed to topTerrain.unbuildable && !improvement.isAllowedOnFeature(topTerrain.name) -> false + + // Can't build it if it is only allowed to improve resources and it doesn't improve this reousrce + improvement.hasUnique(UniqueType.CanOnlyImproveResource, stateForConditionals) && ( + !resourceIsVisible || !tileResource.isImprovedBy(improvement.name) + ) -> false + + // At this point we know this is a normal improvement and that there is no reason not to allow it to be built. + // Lastly we check if the improvement may be built on this terrain or resource + improvement.canBeBuiltOn(topTerrain.name) -> true + isLand && improvement.canBeBuiltOn("Land") -> true + isWater && improvement.canBeBuiltOn("Water") -> true // DO NOT reverse this &&. isAdjacentToFreshwater() is a lazy which calls a function, and reversing it breaks the tests. - improvement.hasUnique(UniqueType.ImprovementBuildableByFreshWater) && isAdjacentTo(Constants.freshWater) -> true - - // If an unique of this type exists, we want all to match (e.g. Hill _and_ Forest would be meaningful). - improvement.getMatchingUniques(UniqueType.CanOnlyBeBuiltOnTile).let { - it.any() && it.all { unique -> matchesTerrainFilter(unique.params[0]) } - } -> true - - else -> resourceIsVisible && tileResource.improvement == improvement.name + improvement.hasUnique(UniqueType.ImprovementBuildableByFreshWater, stateForConditionals) + && isAdjacentTo(Constants.freshWater) -> true + // I don't particularly like this check, but it is required to build mines on non-hill resources + resourceIsVisible && tileResource.isImprovedBy(improvement.name) -> true + // DEPRECATED since 4.0.14, REMOVE SOON: + isLand && improvement.terrainsCanBeBuiltOn.isEmpty() && !improvement.hasUnique(UniqueType.CanOnlyImproveResource) -> true + else -> false } } @@ -739,7 +769,8 @@ open class TileInfo { else FormattedLine(resource!!, link="Resource/$resource") if (resource != null && viewingCiv != null && hasViewableResource(viewingCiv)) { - val tileImprovement = ruleset.tileImprovements[tileResource.improvement] + val resourceImprovement = tileResource.getImprovements().firstOrNull { canBuildImprovement(ruleset.tileImprovements[it]!!, viewingCiv) } + val tileImprovement = ruleset.tileImprovements[resourceImprovement] if (tileImprovement?.techRequired != null && !viewingCiv.tech.isResearched(tileImprovement.techRequired!!)) { lineList += FormattedLine( @@ -1005,11 +1036,7 @@ open class TileInfo { return } improvement = null // Unset, and check if it can be reset. If so, do it, if not, invalid. - if (canImprovementBeBuiltHere(improvementObject) - // Allow building 'other' improvements like city ruins, barb encampments, Great Improvements etc - || (improvementObject.terrainsCanBeBuiltOn.isEmpty() - && ruleset.tileResources.values.none { it.improvement == improvementObject.name } - && !isImpassible() && isLand)) + if (canImprovementBeBuiltHere(improvementObject, stateForConditionals = StateForConditionals.IgnoreConditionals)) improvement = improvementObject.name } diff --git a/core/src/com/unciv/logic/map/TileMap.kt b/core/src/com/unciv/logic/map/TileMap.kt index 56d21eccc2..d8b6c84c23 100644 --- a/core/src/com/unciv/logic/map/TileMap.kt +++ b/core/src/com/unciv/logic/map/TileMap.kt @@ -360,7 +360,7 @@ class TileMap { || cTileHeight > bNeighborHeight // c>b || ( currentTileHeight == bNeighborHeight // a==b - && !bNeighbor.hasUnique(UniqueType.BlocksLineOfSightAtSameElevation) + && !bNeighbor.terrainHasUnique(UniqueType.BlocksLineOfSightAtSameElevation) ) ) } diff --git a/core/src/com/unciv/models/ruleset/Building.kt b/core/src/com/unciv/models/ruleset/Building.kt index d06f1449b9..b2eeb04a13 100644 --- a/core/src/com/unciv/models/ruleset/Building.kt +++ b/core/src/com/unciv/models/ruleset/Building.kt @@ -660,7 +660,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction { it.resource != null && requiredNearbyImprovedResources!!.contains(it.resource!!) && it.getOwner() == civInfo - && (it.tileResource.improvement == it.improvement || it.isCityCenter() + && ((it.improvement != null && it.tileResource.isImprovedBy(it.improvement!!)) || it.isCityCenter() || (it.getTileImprovement()?.isGreatImprovement() == true && it.tileResource.resourceType == ResourceType.Strategic) ) } diff --git a/core/src/com/unciv/models/ruleset/Ruleset.kt b/core/src/com/unciv/models/ruleset/Ruleset.kt index 6680478bbb..93fa8d913e 100644 --- a/core/src/com/unciv/models/ruleset/Ruleset.kt +++ b/core/src/com/unciv/models/ruleset/Ruleset.kt @@ -9,6 +9,7 @@ import com.unciv.json.json import com.unciv.logic.BackwardCompatibility.updateDeprecations import com.unciv.logic.UncivShowableException import com.unciv.logic.map.MapParameters +import com.unciv.logic.map.RoadStatus import com.unciv.models.Counter import com.unciv.models.ModConstants import com.unciv.models.metadata.BaseRuleset @@ -665,6 +666,9 @@ class Ruleset { lines += "${resource.name} revealed by tech ${resource.revealedBy} which does not exist!" if (resource.improvement != null && !tileImprovements.containsKey(resource.improvement!!)) lines += "${resource.name} improved by improvement ${resource.improvement} which does not exist!" + for (improvement in resource.improvedBy) + if (!tileImprovements.containsKey(improvement)) + lines += "${resource.name} improved by improvement $improvement which does not exist!" for (terrain in resource.terrainsCanBeFoundOn) if (!terrains.containsKey(terrain)) lines += "${resource.name} can be found on terrain $terrain which does not exist!" @@ -675,8 +679,20 @@ class Ruleset { if (improvement.techRequired != null && !technologies.containsKey(improvement.techRequired!!)) lines += "${improvement.name} requires tech ${improvement.techRequired} which does not exist!" for (terrain in improvement.terrainsCanBeBuiltOn) - if (!terrains.containsKey(terrain)) + if (!terrains.containsKey(terrain) && terrain != "Land" && terrain != "Water") lines += "${improvement.name} can be built on terrain $terrain which does not exist!" + if (improvement.terrainsCanBeBuiltOn.isEmpty() + && !improvement.hasUnique(UniqueType.CanOnlyImproveResource) + && !improvement.hasUnique(UniqueType.Unbuildable) + && !improvement.name.startsWith(Constants.remove) + && improvement.name !in RoadStatus.values().map { it.removeAction } + && improvement.name != Constants.cancelImprovementOrder + ) { + lines.add( + "${improvement.name} has an empty `terrainsCanBeBuiltOn`, isn't allowed to only improve resources and isn't unbuildable! Support for this will soon end. Either give this the unique \"Unbuildable\", \"Can only be built to improve a resource\" or add \"Land\", \"Water\" or any other value to `terrainsCanBeBuiltOn`.", + RulesetErrorSeverity.Warning + ) + } checkUniques(improvement, lines, rulesetSpecific, forOptionsPopup) } diff --git a/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt b/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt index 1d6f48156d..39d5b684ea 100644 --- a/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt +++ b/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt @@ -13,6 +13,7 @@ import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.translations.tr import com.unciv.ui.civilopedia.FormattedLine import com.unciv.ui.utils.toPercent +import com.unciv.ui.worldscreen.unit.UnitActions import java.util.* import kotlin.math.roundToInt @@ -23,16 +24,17 @@ class TileImprovement : RulesetStatsObject() { var uniqueTo:String? = null override fun getUniqueTarget() = UniqueTarget.Improvement val shortcutKey: Char? = null - val turnsToBuild: Int = 0 // This is the base cost. + // This is the base cost. A cost of 0 means created instead of buildable. + val turnsToBuild: Int = 0 - fun getTurnsToBuild(civInfo: CivilizationInfo, unit: MapUnit?): Int { + fun getTurnsToBuild(civInfo: CivilizationInfo, unit: MapUnit): Int { val state = StateForConditionals(civInfo, unit = unit) - val uniques = civInfo.getMatchingUniques(UniqueType.TileImprovementTime, state) + - (unit?.getMatchingUniques(UniqueType.TileImprovementTime, state) ?: sequenceOf()) - return uniques.fold(turnsToBuild.toFloat() * civInfo.gameInfo.gameParameters.gameSpeed.modifier) { - it, unique -> it * unique.params[0].toPercent() - }.roundToInt().coerceAtLeast(1) + return unit.getMatchingUniques(UniqueType.TileImprovementTime, state, checkCivInfoUniques = true) + .fold(turnsToBuild.toFloat() * civInfo.gameInfo.gameParameters.gameSpeed.modifier) { it, unique -> + it * unique.params[0].toPercent() + }.roundToInt() + .coerceAtLeast(1) // In some weird cases it was possible for something to take 0 turns, leading to it instead never finishing } @@ -48,7 +50,7 @@ class TileImprovement : RulesetStatsObject() { } lines += "Can be built on".tr() + terrainsCanBeBuiltOnString.joinToString(", ", " ") //language can be changed when setting changes. } - for (resource: TileResource in ruleset.tileResources.values.filter { it.improvement == name }) { + for (resource: TileResource in ruleset.tileResources.values.filter { it.isImprovedBy(name) }) { if (resource.improvementStats == null) continue val statsString = resource.improvementStats.toString() lines += "[${statsString}] ".tr() @@ -65,6 +67,22 @@ class TileImprovement : RulesetStatsObject() { fun isRoad() = RoadStatus.values().any { it != RoadStatus.None && it.name == this.name } fun isAncientRuinsEquivalent() = hasUnique(UniqueType.IsAncientRuinsEquivalent) + fun canBeBuiltOn(terrain: String): Boolean { + return terrain in terrainsCanBeBuiltOn + } + + fun handleImprovementCompletion(builder: MapUnit) { + if (hasUnique(UniqueType.TakesOverAdjacentTiles)) + UnitActions.takeOverTilesAround(builder) + if (builder.getTile().resource != null) { + val city = builder.getTile().getCity() + if (city != null) { + city.cityStats.update() + city.civInfo.updateDetailedCivResources() + } + } + } + /** * Check: Is this improvement allowed on a [given][name] terrain feature? * @@ -75,7 +93,7 @@ class TileImprovement : RulesetStatsObject() { * so this check is done in conjunction - for the user, success means he does not need to remove * a terrain feature, thus the unique name. */ - fun isAllowedOnFeature(name: String) = getMatchingUniques(UniqueType.NoFeatureRemovalNeeded).any { it.params[0] == name } + fun isAllowedOnFeature(name: String) = terrainsCanBeBuiltOn.contains(name) || getMatchingUniques(UniqueType.NoFeatureRemovalNeeded).any { it.params[0] == name } /** Implements [UniqueParameterType.ImprovementFilter][com.unciv.models.ruleset.unique.UniqueParameterType.ImprovementFilter] */ fun matchesFilter(filter: String): Boolean { @@ -117,7 +135,7 @@ class TileImprovement : RulesetStatsObject() { } var addedLineBeforeResourceBonus = false - for (resource in ruleset.tileResources.values.filter { it.improvement == name }) { + for (resource in ruleset.tileResources.values.filter { it.isImprovedBy(name) }) { if (resource.improvementStats == null) continue if (!addedLineBeforeResourceBonus) { addedLineBeforeResourceBonus = true diff --git a/core/src/com/unciv/models/ruleset/tile/TileResource.kt b/core/src/com/unciv/models/ruleset/tile/TileResource.kt index b26eec8cbf..8e73fb120b 100644 --- a/core/src/com/unciv/models/ruleset/tile/TileResource.kt +++ b/core/src/com/unciv/models/ruleset/tile/TileResource.kt @@ -1,5 +1,7 @@ package com.unciv.models.ruleset.tile +import com.unciv.logic.civilization.CivilizationInfo +import com.unciv.logic.map.TileInfo import com.unciv.models.ruleset.Belief import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.RulesetStatsObject @@ -15,12 +17,21 @@ class TileResource : RulesetStatsObject() { var improvement: String? = null var improvementStats: Stats? = null var revealedBy: String? = null + var improvedBy: List = listOf() var majorDepositAmount: DepositAmount = DepositAmount() var minorDepositAmount: DepositAmount = DepositAmount() + val _allImprovements by lazy { + if (improvement == null) improvedBy + else improvedBy + improvement!! + } + + fun getImprovements(): List { + return _allImprovements + } + override fun getUniqueTarget() = UniqueTarget.Resource - - + override fun makeLink() = "Resource/$name" override fun getCivilopediaTextLines(ruleset: Ruleset): List { @@ -45,7 +56,7 @@ class TileResource : RulesetStatsObject() { } } - if (improvement != null) { + for (improvement in getImprovements()) { textList += FormattedLine() textList += FormattedLine("Improved by [$improvement]", link = "Improvement/$improvement") if (improvementStats != null && !improvementStats!!.isEmpty()) @@ -114,6 +125,16 @@ class TileResource : RulesetStatsObject() { return textList } + fun isImprovedBy(improvementName: String): Boolean { + return getImprovements().contains(improvementName) + } + + fun getImprovingImprovement(tile: TileInfo, civInfo: CivilizationInfo): String? { + return getImprovements().firstOrNull { + tile.canBuildImprovement(civInfo.gameInfo.ruleSet.tileImprovements[it]!!, civInfo) + } + } + class DepositAmount { var sparse: Int = 1 var default: Int = 2 diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt index 205b82df3b..b49cc2c2ed 100644 --- a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt +++ b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt @@ -316,7 +316,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: ///////////////////////////////////////// region CONSTRUCTION UNIQUES ///////////////////////////////////////// - Unbuildable("Unbuildable", UniqueTarget.Building, UniqueTarget.Unit), + Unbuildable("Unbuildable", UniqueTarget.Building, UniqueTarget.Unit, UniqueTarget.Improvement), CannotBePurchased("Cannot be purchased", UniqueTarget.Building, UniqueTarget.Unit), CanBePurchasedWithStat("Can be purchased with [stat] [cityFilter]", UniqueTarget.Building, UniqueTarget.Unit), CanBePurchasedForAmountStat("Can be purchased for [amount] [stat] [cityFilter]", UniqueTarget.Building, UniqueTarget.Unit), @@ -437,6 +437,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: NoDefensiveTerrainPenalty("No defensive terrain penalty", UniqueTarget.Unit, UniqueTarget.Global), NoDamagePenalty("Damage is ignored when determining unit Strength", UniqueTarget.Unit, UniqueTarget.Global), Uncapturable("Uncapturable", UniqueTarget.Unit), + // Replace with "Withdraws before melee combat "? MayWithdraw("May withdraw before melee ([amount]%)", UniqueTarget.Unit), CannotCaptureCities("Unable to capture cities", UniqueTarget.Unit), @@ -614,6 +615,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: CanOnlyBeBuiltOnTile("Can only be built on [tileFilter] tiles", UniqueTarget.Improvement), CannotBuildOnTile("Cannot be built on [tileFilter] tiles", UniqueTarget.Improvement), NoFeatureRemovalNeeded("Does not need removal of [tileFilter]", UniqueTarget.Improvement), + CanOnlyImproveResource("Can only be built to improve a resource", UniqueTarget.Improvement), DefensiveBonus("Gives a defensive bonus of [relativeAmount]%", UniqueTarget.Improvement), ImprovementMaintenance("Costs [amount] gold per turn when in your territory", UniqueTarget.Improvement), // Unused @@ -622,9 +624,9 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: GreatImprovement("Great Improvement", UniqueTarget.Improvement), IsAncientRuinsEquivalent("Provides a random bonus when entered", UniqueTarget.Improvement), + TakesOverAdjacentTiles("Constructing it will take over the tiles around it and assign them to your closest city", UniqueTarget.Improvement), Unpillagable("Unpillagable", UniqueTarget.Improvement), - Indestructible("Indestructible", UniqueTarget.Improvement), Irremovable("Irremovable", UniqueTarget.Improvement), //endregion @@ -751,6 +753,9 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: // region DEPRECATED AND REMOVED + @Deprecated("as of 4.0.15", ReplaceWith("Irremovable"), DeprecationLevel.ERROR) + Indestructible("Indestructible", UniqueTarget.Improvement), + @Deprecated("as of 3.19.1", ReplaceWith("[stats] from every [Wonder]"), DeprecationLevel.ERROR) StatsFromWondersDeprecated("[stats] from every Wonder", UniqueTarget.Global, UniqueTarget.FollowerBelief), @Deprecated("as of 3.19.3", ReplaceWith("[stats] from every [buildingFilter] "), DeprecationLevel.ERROR) diff --git a/core/src/com/unciv/ui/overviewscreen/ResourcesOverviewTable.kt b/core/src/com/unciv/ui/overviewscreen/ResourcesOverviewTable.kt index b19386b1f1..90a7a2c135 100644 --- a/core/src/com/unciv/ui/overviewscreen/ResourcesOverviewTable.kt +++ b/core/src/com/unciv/ui/overviewscreen/ResourcesOverviewTable.kt @@ -229,7 +229,7 @@ class ResourcesOverviewTab( if (!tile.hasViewableResource(viewingPlayer)) continue val tileResource = tile.tileResource if (tileResource.resourceType == ResourceType.Bonus) continue - if (tile.improvement == tileResource.improvement) continue + if (tile.improvement != null && tileResource.isImprovedBy(tile.improvement!!)) continue if (tileResource.resourceType == ResourceType.Strategic && tile.getTileImprovement()?.isGreatImprovement() == true) continue resourceSupplyList.add(tileResource, 1, ExtraInfoOrigin.Unimproved.name) } diff --git a/core/src/com/unciv/ui/pickerscreens/ImprovementPickerScreen.kt b/core/src/com/unciv/ui/pickerscreens/ImprovementPickerScreen.kt index 21cc4600f9..c3f67aad64 100644 --- a/core/src/com/unciv/ui/pickerscreens/ImprovementPickerScreen.kt +++ b/core/src/com/unciv/ui/pickerscreens/ImprovementPickerScreen.kt @@ -20,7 +20,7 @@ import kotlin.math.roundToInt class ImprovementPickerScreen( private val tileInfo: TileInfo, private val unit: MapUnit, - private val onAccept: ()->Unit + private val onAccept: ()->Unit, ) : PickerScreen() { private var selectedImprovement: TileImprovement? = null private val gameInfo = tileInfo.tileMap.gameInfo @@ -98,12 +98,12 @@ class ImprovementPickerScreen( var labelText = improvement.name.tr() val turnsToBuild = if (tileInfo.improvementInProgress == improvement.name) tileInfo.turnsToImprovement - else improvement.getTurnsToBuild(currentPlayerCiv, unit) + else improvement.getTurnsToBuild(currentPlayerCiv, unit) + if (turnsToBuild > 0) labelText += " - $turnsToBuild${Fonts.turn}" - val provideResource = tileInfo.hasViewableResource(currentPlayerCiv) && tileInfo.tileResource.improvement == improvement.name + val provideResource = tileInfo.hasViewableResource(currentPlayerCiv) && tileInfo.tileResource.isImprovedBy(improvement.name) if (provideResource) labelText += "\n" + "Provides [${tileInfo.resource}]".tr() - val removeImprovement = (improvement.name != RoadStatus.Road.name - && improvement.name != RoadStatus.Railroad.name + val removeImprovement = (improvement.isRoad() && !improvement.name.startsWith(Constants.remove) && improvement.name != Constants.cancelImprovementOrder) if (tileInfo.improvement != null && removeImprovement) labelText += "\n" + "Replaces [${tileInfo.improvement}]".tr() @@ -162,7 +162,7 @@ class ImprovementPickerScreen( statIcons.add(ImageGetter.getResourceImage(tileInfo.resource.toString(), 30f)).pad(3f) // icon for removing the resource by replacing improvement - if (removeImprovement && tileInfo.hasViewableResource(currentPlayerCiv) && tileInfo.tileResource.improvement == tileInfo.improvement) { + if (removeImprovement && tileInfo.hasViewableResource(currentPlayerCiv) && tileInfo.improvement != null && tileInfo.tileResource.isImprovedBy(tileInfo.improvement!!)) { val resourceIcon = ImageGetter.getResourceImage(tileInfo.resource!!, 30f) statIcons.add(ImageGetter.getCrossedImage(resourceIcon, 30f)) } diff --git a/core/src/com/unciv/ui/trade/DiplomacyScreen.kt b/core/src/com/unciv/ui/trade/DiplomacyScreen.kt index 18e9196c70..7e6bdc56dd 100644 --- a/core/src/com/unciv/ui/trade/DiplomacyScreen.kt +++ b/core/src/com/unciv/ui/trade/DiplomacyScreen.kt @@ -425,10 +425,8 @@ class DiplomacyScreen( for (improvableTile in improvableResourceTiles) for (tileImprovement in improvements.values) - if (improvableTile.canBuildImprovement( - tileImprovement, - otherCiv - ) && improvableTile.tileResource.improvement == tileImprovement.name + if (improvableTile.tileResource.isImprovedBy(tileImprovement.name) + && improvableTile.canBuildImprovement(tileImprovement, otherCiv) ) needsImprovements = true @@ -490,9 +488,11 @@ class DiplomacyScreen( return diplomacyTable } - fun getImprovableResourceTiles(otherCiv:CivilizationInfo) = otherCiv.getCapital().getTiles() - .filter { it.hasViewableResource(otherCiv) && it.tileResource.resourceType!=ResourceType.Bonus - && it.tileResource.improvement != it.improvement } + fun getImprovableResourceTiles(otherCiv:CivilizationInfo) = otherCiv.getCapital().getTiles().filter { + it.hasViewableResource(otherCiv) + && it.tileResource.resourceType != ResourceType.Bonus + && (it.improvement == null || !it.tileResource.isImprovedBy(it.improvement!!)) + } private fun getImprovementGiftTable(otherCiv: CivilizationInfo): Table { val improvementGiftTable = getCityStateDiplomacyTableHeader(otherCiv) @@ -504,7 +504,7 @@ class DiplomacyScreen( for (improvableTile in improvableResourceTiles) { for (tileImprovement in tileImprovements.values) { - if (improvableTile.tileResource.improvement == tileImprovement.name + if (improvableTile.tileResource.isImprovedBy(tileImprovement.name) && improvableTile.canBuildImprovement(tileImprovement, otherCiv) ) { val improveTileButton = diff --git a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt index 8e71473364..ec248fefe2 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt @@ -545,7 +545,7 @@ class WorldScreen(val gameInfo: GameInfo, val viewingCiv:CivilizationInfo) : Bas displayTutorial(Tutorial.Workers) { gameInfo.getCurrentPlayerCivilization().getCivUnits().any { - it.hasUniqueToBuildImprovements && it.isCivilian() + it.hasUniqueToBuildImprovements && it.isCivilian() && !it.isGreatPerson() } } } diff --git a/core/src/com/unciv/ui/worldscreen/mainmenu/OptionsPopup.kt b/core/src/com/unciv/ui/worldscreen/mainmenu/OptionsPopup.kt index 2f7b4b9f35..8af456d898 100644 --- a/core/src/com/unciv/ui/worldscreen/mainmenu/OptionsPopup.kt +++ b/core/src/com/unciv/ui/worldscreen/mainmenu/OptionsPopup.kt @@ -624,7 +624,9 @@ class OptionsPopup( for ((tile, resource) in ownedTiles zip resourceTypes) { tile.resource = resource.name tile.resourceAmount = 999 - tile.improvement = resource.improvement + // Debug option, so if it crashes on this that's relatively fine + // If this becomes a problem, check if such an improvement exists and otherwise plop down a great improvement or so + tile.improvement = resource.getImprovements().first() } game.gameInfo.getCurrentPlayerCivilization().updateSightAndResources() game.worldScreen.shouldUpdate = true diff --git a/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt b/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt index 0db6697a2b..084836cd21 100644 --- a/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt +++ b/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt @@ -19,7 +19,6 @@ import com.unciv.models.ruleset.Building import com.unciv.models.ruleset.unique.UniqueTriggerActivation import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.stats.Stat -import com.unciv.models.stats.Stats import com.unciv.models.translations.tr import com.unciv.ui.pickerscreens.ImprovementPickerScreen import com.unciv.ui.pickerscreens.PromotionPickerScreen @@ -135,7 +134,7 @@ object UnitActions { val tile = unit.currentTile if (!tile.isWater || !unit.hasUnique(UniqueType.CreateWaterImprovements) || tile.resource == null) return null - val improvementName = tile.tileResource.improvement ?: return null + val improvementName = tile.tileResource.getImprovingImprovement(tile, unit.civInfo) ?: return null val improvement = tile.ruleset.tileImprovements[improvementName] ?: return null if (!tile.canBuildImprovement(improvement, unit.civInfo)) return null @@ -439,7 +438,6 @@ object UnitActions { actionList += getAddInCapitalAction(unit, tile) } - private fun addGreatPersonActions(unit: MapUnit, actionList: ArrayList, tile: TileInfo) { if (unit.currentMovement > 0) for (unique in unit.getUniques()) when (unique.placeholderText) { @@ -447,8 +445,7 @@ object UnitActions { actionList += UnitAction(UnitActionType.HurryResearch, action = { unit.civInfo.tech.addScience(unit.civInfo.tech.getScienceFromGreatScientist()) - addStatsPerGreatPersonUsage(unit) - unit.destroy() + unit.consume() }.takeIf { unit.civInfo.tech.currentTechnologyName() != null } ) } @@ -457,8 +454,7 @@ object UnitActions { actionList += UnitAction(UnitActionType.StartGoldenAge, action = { unit.civInfo.goldenAges.enterGoldenAge(turnsToGoldenAge) - addStatsPerGreatPersonUsage(unit) - unit.destroy() + unit.consume() }.takeIf { unit.currentTile.getOwner() != null && unit.currentTile.getOwner() == unit.civInfo } ) } @@ -476,8 +472,7 @@ object UnitActions { constructIfEnough() } - addStatsPerGreatPersonUsage(unit) - unit.destroy() + unit.consume() }.takeIf { canHurryWonder } ) } @@ -507,8 +502,7 @@ object UnitActions { constructIfEnough() } - addStatsPerGreatPersonUsage(unit) - unit.destroy() + unit.consume() }.takeIf { canHurryConstruction } ) } @@ -526,8 +520,7 @@ object UnitActions { tile.owningCity!!.civInfo.getDiplomacyManager(unit.civInfo).addInfluence(influenceEarned) unit.civInfo.addNotification("Your trade mission to [${tile.owningCity!!.civInfo}] has earned you [${goldEarned}] gold and [$influenceEarned] influence!", tile.owningCity!!.civInfo.civName, NotificationIcon.Gold, NotificationIcon.Culture) - addStatsPerGreatPersonUsage(unit) - unit.destroy() + unit.consume() }.takeIf { canConductTradeMission } ) } @@ -544,9 +537,8 @@ object UnitActions { fun getFoundReligionAction(unit: MapUnit): () -> Unit { return { - addStatsPerGreatPersonUsage(unit) unit.civInfo.religionManager.useProphetForFoundingReligion(unit) - unit.destroy() + unit.consume() } } @@ -561,9 +553,8 @@ object UnitActions { fun getEnhanceReligionAction(unit: MapUnit): () -> Unit { return { - addStatsPerGreatPersonUsage(unit) unit.civInfo.religionManager.useProphetForEnhancingReligion(unit) - unit.destroy() + unit.consume() } } @@ -586,8 +577,7 @@ object UnitActions { private fun useActionWithLimitedUses(unit: MapUnit, action: String) { unit.abilityUsesLeft[action] = unit.abilityUsesLeft[action]!! - 1 if (unit.abilityUsesLeft[action]!! <= 0) { - addStatsPerGreatPersonUsage(unit) - unit.destroy() + unit.consume() } } @@ -665,16 +655,8 @@ object UnitActions { unitTile.removeCreatesOneImprovementMarker() unitTile.improvement = improvementName unitTile.stopWorkingOnImprovement() - if (improvement.hasUnique(UniqueType.TakeOverTilesAroundWhenBuilt)) - takeOverTilesAround(unit) - val city = unitTile.getCity() - if (city != null) { - city.cityStats.update() - city.civInfo.updateDetailedCivResources() - } - if (unit.isGreatPerson()) - addStatsPerGreatPersonUsage(unit) - unit.destroy() + improvement.handleImprovementCompletion(unit) + unit.consume() }.takeIf { resourcesAvailable && unit.currentMovement > 0f @@ -688,7 +670,7 @@ object UnitActions { return finalActions } - private fun takeOverTilesAround(unit: MapUnit) { + fun takeOverTilesAround(unit: MapUnit) { // This method should only be called for a citadel - therefore one of the neighbour tile // must belong to unit's civ, so minByOrNull in the nearestCity formula should be never `null`. // That is, unless a mod does not specify the proper unique - then fallbackNearestCity will take over. @@ -732,26 +714,6 @@ object UnitActions { otherCiv.addNotification("[${unit.civInfo}] has stolen your territory!", unit.currentTile.position, unit.civInfo.civName, NotificationIcon.War) } - private fun addStatsPerGreatPersonUsage(unit: MapUnit) { - if (!unit.isGreatPerson()) return - - val civInfo = unit.civInfo - - val gainedStats = Stats() - for (unique in civInfo.getMatchingUniques(UniqueType.ProvidesGoldWheneverGreatPersonExpended)) { - gainedStats.gold += (100 * civInfo.gameInfo.gameParameters.gameSpeed.modifier).toInt() - } - for (unique in civInfo.getMatchingUniques(UniqueType.ProvidesStatsWheneverGreatPersonExpended)) { - gainedStats.add(unique.stats) - } - - if (gainedStats.isEmpty()) return - - for (stat in gainedStats) - civInfo.addStat(stat.key, stat.value.toInt()) - civInfo.addNotification("By expending your [${unit.name}] you gained [${gainedStats}]!", unit.getTile().position, unit.name) - } - private fun addFortifyActions(actionList: ArrayList, unit: MapUnit, showingAdditionalActions: Boolean) { if (unit.isFortified() && !showingAdditionalActions) { actionList += UnitAction( @@ -860,8 +822,7 @@ object UnitActions { if (!unique.conditionals.any { it.type == UniqueType.ConditionalConsumeUnit }) continue val unitAction = UnitAction(type = UnitActionType.TriggerUnique, unique.text){ UniqueTriggerActivation.triggerCivwideUnique(unique, unit.civInfo) - addStatsPerGreatPersonUsage(unit) - unit.destroy() + unit.consume() } actionList += unitAction } diff --git a/docs/Credits.md b/docs/Credits.md index ee46f6e16f..68c910a642 100644 --- a/docs/Credits.md +++ b/docs/Credits.md @@ -212,6 +212,7 @@ Unless otherwise specified, all the following are from [the Noun Project](https: - [Citadel](https://thenounproject.com/term/fort/1697646/) By Adrien Coquet - [Village](https://thenounproject.com/search/?q=city+center&i=476338) by Andrey Vasiliev - [pumping station](https://thenounproject.com/search/?q=dike&i=555172) by Peter van Driel for Polder +- [Oil Platform](https://thenounproject.com/icon/oil-platform-1364795/) by Georgiana Ionescu for Offshore Platform ### Buildings diff --git a/docs/Modders/uniques.md b/docs/Modders/uniques.md index edc878bc98..8cc2177a3b 100644 --- a/docs/Modders/uniques.md +++ b/docs/Modders/uniques.md @@ -829,7 +829,7 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl Applicable to: Building, Improvement ??? example "Unbuildable" - Applicable to: Building, Unit + Applicable to: Building, Unit, Improvement ??? example "Cannot be purchased" Applicable to: Building, Unit @@ -1396,6 +1396,9 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl Applicable to: Improvement +??? example "Can only be built to improve a resource" + Applicable to: Improvement + ??? example "Gives a defensive bonus of [relativeAmount]%" Example: "Gives a defensive bonus of [+20]%" @@ -1420,10 +1423,10 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl ??? example "Provides a random bonus when entered" Applicable to: Improvement -??? example "Unpillagable" +??? example "Constructing it will take over the tiles around it and assign them to your closest city" Applicable to: Improvement -??? example "Indestructible" +??? example "Unpillagable" Applicable to: Improvement ??? example "Irremovable" diff --git a/tests/src/com/unciv/logic/map/TileImprovementConstructionTests.kt b/tests/src/com/unciv/logic/map/TileImprovementConstructionTests.kt index 80f3b7bc29..cb6ce1a5f6 100644 --- a/tests/src/com/unciv/logic/map/TileImprovementConstructionTests.kt +++ b/tests/src/com/unciv/logic/map/TileImprovementConstructionTests.kt @@ -6,6 +6,9 @@ import com.unciv.logic.city.CityInfo import com.unciv.logic.civilization.CivilizationInfo import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.RulesetCache +import com.unciv.models.ruleset.tile.TerrainType +import com.unciv.models.ruleset.unique.StateForConditionals +import com.unciv.models.ruleset.unique.UniqueType import com.unciv.testing.GdxTestRunner import org.junit.Assert import org.junit.Before @@ -42,11 +45,23 @@ class TileImprovementConstructionTests { fun allTerrainSpecificImprovementsCanBeBuilt() { for (improvement in ruleSet.tileImprovements.values) { - val terrain = improvement.terrainsCanBeBuiltOn.firstOrNull() ?: continue + var terrain = improvement.terrainsCanBeBuiltOn.firstOrNull() ?: continue + if (terrain == "Land") terrain = ruleSet.terrains.values.first { it.type == TerrainType.Land }.name + if (terrain == "Water") terrain = ruleSet.terrains.values.first { it.type == TerrainType.Water }.name + // If this improvement requires additional conditions to be true, + // its too complex to handle all of them, so just skip it and hope its fine + // I would like some comments on whether this approach is fine or if it's better if I handle every single unique here as well + if (improvement.hasUnique(UniqueType.CanOnlyBeBuiltOnTile, StateForConditionals.IgnoreConditionals)) continue + if (improvement.hasUnique(UniqueType.Unbuildable, StateForConditionals.IgnoreConditionals)) continue + val tile = getTile() tile.baseTerrain = terrain + if (improvement.hasUnique(UniqueType.CanOnlyImproveResource, StateForConditionals.IgnoreConditionals)) { + tile.resource = ruleSet.tileResources.values.firstOrNull { it.isImprovedBy(improvement.name) }?.name ?: continue + } tile.setTransients() if (improvement.uniqueTo != null) civInfo.civName = improvement.uniqueTo!! + val canBeBuilt = tile.canBuildImprovement(improvement, civInfo) Assert.assertTrue(improvement.name, canBeBuilt) } @@ -57,8 +72,12 @@ class TileImprovementConstructionTests { for (improvement in ruleSet.tileImprovements.values) { val tile = getTile() tile.resource = ruleSet.tileResources.values - .firstOrNull { it.improvement == improvement.name }?.name + .firstOrNull { it.isImprovedBy(improvement.name) }?.name if (tile.resource == null) continue + // If this improvement requires additional conditions to be true, + // its too complex to handle all of them, so just skip it and hope its fine + if (improvement.hasUnique(UniqueType.CanOnlyBeBuiltOnTile, StateForConditionals.IgnoreConditionals)) continue + tile.setTransients() val canBeBuilt = tile.canBuildImprovement(improvement, civInfo) Assert.assertTrue(improvement.name, canBeBuilt) @@ -116,11 +135,11 @@ class TileImprovementConstructionTests { civInfo.civName = "OtherCiv" for (resource in ruleSet.tileResources.values) { - if (resource.improvement == null) continue - val improvement = ruleSet.tileImprovements[resource.improvement]!! - if (improvement.terrainsCanBeBuiltOn.isNotEmpty()) continue + if (resource.getImprovements().isEmpty()) continue + val improvement = ruleSet.tileImprovements[resource.getImprovements().first()]!! + if (!improvement.hasUnique(UniqueType.CanOnlyImproveResource)) continue val wrongResource = ruleSet.tileResources.values.firstOrNull { - it != resource && it.improvement != improvement.name + it != resource && !it.isImprovedBy(improvement.name) } ?: continue val tile = getTile() tile.baseTerrain = "Plains"