diff --git a/PolyPlus.csproj b/PolyPlus.csproj
index a8f4563..8e00ef8 100644
--- a/PolyPlus.csproj
+++ b/PolyPlus.csproj
@@ -13,7 +13,7 @@
-
+
diff --git a/PolyPlus/body_tint_treant__.png b/PolyPlus/body_tint_treant__.png
new file mode 100644
index 0000000..8a6fcea
Binary files /dev/null and b/PolyPlus/body_tint_treant__.png differ
diff --git a/PolyPlus/body_treant__.png b/PolyPlus/body_treant__.png
new file mode 100644
index 0000000..14397c3
Binary files /dev/null and b/PolyPlus/body_treant__.png differ
diff --git a/PolyPlus/body_treant_darkelf_.png b/PolyPlus/body_treant_darkelf_.png
new file mode 100644
index 0000000..94732fc
Binary files /dev/null and b/PolyPlus/body_treant_darkelf_.png differ
diff --git a/PolyPlus/body_treant_outline__.png b/PolyPlus/body_treant_outline__.png
new file mode 100644
index 0000000..8133aed
Binary files /dev/null and b/PolyPlus/body_treant_outline__.png differ
diff --git a/PolyPlus/field_aquarion_.png b/PolyPlus/field_aquarion_.png
new file mode 100644
index 0000000..bbc933f
Binary files /dev/null and b/PolyPlus/field_aquarion_.png differ
diff --git a/PolyPlus/field_swamp_.png b/PolyPlus/field_swamp_.png
new file mode 100644
index 0000000..7b5f680
Binary files /dev/null and b/PolyPlus/field_swamp_.png differ
diff --git a/PolyPlus/fungi__4.png b/PolyPlus/fungi__4.png
new file mode 100644
index 0000000..4c47ed8
Binary files /dev/null and b/PolyPlus/fungi__4.png differ
diff --git a/PolyPlus/localization.json b/PolyPlus/localization.json
index 5592e54..c7e0f3a 100644
--- a/PolyPlus/localization.json
+++ b/PolyPlus/localization.json
@@ -336,5 +336,61 @@
"tooltip_ability_revolt": {
"English": "This unit can enter enemy cities to incite revolts.",
"Russian": "Этот отряд может заходить во вражеские города и устраивать восстания."
+ },
+ "technology_names_elyforestry": {
+ "English": "Forestry",
+ "Russian": "Лесное хозяйство"
+ },
+ "player_abilities_treehouse": {
+ "English": "Tree Houses",
+ "Russian": "Домики на Деревьях"
+ },
+ "tooltip_ability_treehouse": {
+ "English": "Land improvements can be built on forests.",
+ "Russian": "Строения для суши можно строить на лесах."
+ },
+ "technology_names_naturalharmony": {
+ "English": "Natural Harmony",
+ "Russian": "Природная гармония"
+ },
+ "unit_names_treant": {
+ "English": "Sylvan Warden",
+ "Russian": "Хранитель Чащи"
+ },
+ "unit_names_treant__darkelf": {
+ "English": "Thorn Demon",
+ "Russian": "Терновый Демон"
+ },
+ "unit_abilities_foreststealth": {
+ "English": "Forest Stealth",
+ "Russian": "Скрытность в лесу"
+ },
+ "tooltip_ability_foreststealth": {
+ "English": "Unit turns invisible in forests.",
+ "Russian": "Отряд становится невидимым в лесах."
+ },
+ "unit_abilities_absorb": {
+ "English": "ABSORB",
+ "Russian": "ПОГЛОЩЕНИЕ"
+ },
+ "tooltip_ability_absorb": {
+ "English": "This unit restores health equal to the damage it dealt to the opponent.",
+ "Russian": "Этот отряд восстанавливает количество здоровья, равное урону, нанесённому противнику."
+ },
+ "building_names_enchantforest": {
+ "English": "Enchant Forest",
+ "Russian": "Зачаровать лес"
+ },
+ "building_names_enchantforest__darkelf": {
+ "English": "Curse Forest",
+ "Russian": "Проклясть лес"
+ },
+ "unit_abilities_autoheal": {
+ "English": "AUTOHEAL",
+ "Russian": "АВТОЛЕЧЕНИЕ"
+ },
+ "tooltip_ability_autoheal": {
+ "English": "This unit heals itself and other allied units around when moving.",
+ "Russian": "Этот отряд лечит себя и союзнические отряды вокруг когда передвигается."
}
}
diff --git a/PolyPlus/manifest.json b/PolyPlus/manifest.json
index 5cbbb75..55ce8a1 100644
--- a/PolyPlus/manifest.json
+++ b/PolyPlus/manifest.json
@@ -1,12 +1,12 @@
{
"id": "polyplus",
- "version": "1.4.0",
- "authors": ["Coding by JohnKlipi, Balance by MCompany, Sprites by Rastrapies and Jam's Son"],
+ "version": "1.5.0",
+ "authors": ["Coding by JohnKlipi, Balance by MCompany, Sprites by Rastrapies, Jam's Son and Bananique"],
"dependencies": [
{
"id": "polytopia",
- "min": "2.15.1",
- "max": "2.15.2"
+ "min": "2.16.3",
+ "max": "2.16.4"
}
]
}
\ No newline at end of file
diff --git a/PolyPlus/mountain_aquarion_.png b/PolyPlus/mountain_aquarion_.png
new file mode 100644
index 0000000..aea64d9
Binary files /dev/null and b/PolyPlus/mountain_aquarion_.png differ
diff --git a/PolyPlus/mountain_swamp_.png b/PolyPlus/mountain_swamp_.png
new file mode 100644
index 0000000..96f11cc
Binary files /dev/null and b/PolyPlus/mountain_swamp_.png differ
diff --git a/PolyPlus/patch.json b/PolyPlus/patch.json
deleted file mode 100644
index 13cdad9..0000000
--- a/PolyPlus/patch.json
+++ /dev/null
@@ -1,1025 +0,0 @@
-{
- "tribeData": {
- "aimo": {
- "startingUnit": "mindbender",
- "startingStars": 5,
- "startingTech": [
- "basic",
- "meditation"
- ]
- },
- "aquarion": {
- "techOverrides": {
- "navigation": "aquanavigation",
- "embarquatism": "aquatism",
- "embarksailing": "marinelife"
- },
- "resourceModifier": {
- "aquacrop": 1.5
- },
- "improvementOverrides": {
- "fertilize": "aquafertilize",
- "port": "none",
- "customshouse": "none"
- },
- "startingStars": 5
- },
- "bardur": {
- "terrainModifier": {
- "forest": 1.5
- },
- "startingStars": 3
- },
- "elyrion": {
- "startingStars": 5
- },
- "hoodrick": {
- "startingStars": 5
- },
- "imperius": {
- "startingStars": 3
- },
- "kickoo": {
- "startingTech": [
- "basic",
- "fishingplus"
- ],
- "startingStars": 3
- },
- "luxidoor": {
- "startingResource": [],
- "bonus": 0,
- "tribeAbilities": [
- "citypark"
- ],
- "startingStars": 5
- },
- "oumaji": {
- "terrainModifier": {
- "forest": 0.2,
- "mountain":0.5,
- "water": 0.5
- },
- "resourceModifier": {
- "game": 1,
- "crop": 0.5,
- "fruit": 1.2
- },
- "startingStars": 5
- },
- "quetzali": {
- "startingStars": 5
- },
- "vengir": {
- "startingStars": 5
- },
- "xinxi": {
- "startingStars": 5
- },
- "yadakk": {
- "startingStars": 5
- },
- "zebasi": {
- "startingStars": 3
- },
- "polaris": {
- "improvementOverrides": {
- "customshouse": "none"
- },
- "techOverrides": {
- "embarksailing": "frostwork",
- "navigation": "polarwarfare",
- "embarquatism": "polarism",
- "aquaculture" : "sledding"
- },
- "preview": [
- {
- "x": 0,
- "y": -2,
- "terrainType": "ice",
- "unitType": "yuukwi"
- }
- ],
- "startingStars": 5
- },
- "cymanti": {
- "startingTech": [
- "+cymbase"
- ],
- "unitOverrides": {
- "mindbender": "mindbender",
- "rammership": "raychi"
- },
- "improvementOverrides": {
- "market": "market",
- "port": "algae",
- "customshouse": "clathrus"
- },
- "techOverrides": {
- "roads": "cymroads",
- "construction": "recycling",
- "chivalry": "shock",
- "embarksailing": "cymsailing",
- "meditation": "meditation",
- "embarquatism": "aquatism"
- },
- "startingUnit": "warrior",
- "preview": [
- {
- "x": -1,
- "y": -2,
- "unitType": "raychi",
- "terrainType": "water"
- },
- {
- "x": 2,
- "y": -1,
- "unitType": "boomchi",
- "terrainType": "water"
- }
- ],
- "startingStars": 5
- }
- },
- "techData": {
- "cymbase": {
- "improvementUnlocks": [
- "makebloom"
- ],
- "cost": 0,
- "idx": -1
- },
- "recycling": {
- "abilityUnlocks": [
- "-microbes"
- ],
- "improvementUnlocks": [
- "+mycogrove"
- ]
- },
- "basic": {
- "techUnlocks": [
- "organization",
- "climbing",
- "fishingplus",
- "hunting",
- "freespirit"
- ],
- "taskUnlocks": [
- "+wealth",
- "+genius"
- ],
- "improvementUnlocks": [
- "+instantembark"
- ],
- "movementUnlocks": {
- "water": 1
- }
- },
- "riding": {
- "techUnlocks": [
- "chivalry"
- ],
- "cost": 2
- },
- "freespirit": {
- "improvementUnlocks": [
- "+guild"
- ],
- "techUnlocks": [
- "roads",
- "shields"
- ],
- "cost": 1
- },
- "organization": {
- "techUnlocks": [
- "-shields",
- "+riding"
- ]
- },
- "meditation": {
- "improvementUnlocks": [
- "-mountaintemple"
- ],
- "unitUnlocks": [
- "+mindbender"
- ],
- "abilityUnlocks": [
- "+discipline"
- ]
- },
- "philosophy": {
- "unitUnlocks": [
- "-mindbender"
- ],
- "taskUnlocks": [
- "-genius"
- ]
- },
- "aquatism": {
- "improvementUnlocks": [
- "customshouse"
- ]
- },
- "embarquatism": {
- "improvementUnlocks": [
- "customshouse"
- ],
- "abilityUnlocks": [
- "dashembark"
- ],
- "cost": 3,
- "idx": -1
- },
- "spiritualism": {
- "improvementUnlocks": [
- "-foresttemple"
- ]
- },
- "construction": {
- "improvementUnlocks": [
- "-burnforest",
- "+fertilize"
- ]
- },
- "navigation": {
- "unitUnlocks": [
- "bombership",
- "rammership"
- ],
- "movementUnlocks": {
- "ocean": 1
- },
- "improvementUnlocks": [
- "-starfishing",
- "-watertemple"
- ],
- "cost": 3
- },
- "fishing": {
- "improvementUnlocks": [
- "-port"
- ],
- "movementUnlocks": {}
- },
- "aquaculture": {
- "techUnlocks": [
- "embarquatism"
- ],
- "improvementUnlocks": [
- "harvestaquacrop",
- "port"
- ],
- "unitUnlocks": [
- "-rammership"
- ],
- "cost": 2
- },
- "embarksailing": {
- "techUnlocks": [
- "navigation"
- ],
- "abilityUnlocks": [
- "waterembark"
- ],
- "unitUnlocks": [
- "scoutship"
- ],
- "cost": 2,
- "idx": -1
- },
- "riding2": {
- "techUnlocks": [
- "spearing"
- ],
- "cost": 2
- },
- "freediving": {
- "techUnlocks": [
- "roads",
- "shields"
- ],
- "improvementUnlocks": [
- "temple"
- ],
- "abilityUnlocks": [
- "disband"
- ],
- "movementUnlocks": {
- "ocean": 0
- },
- "cost": 1
- },
- "cymroads": {
- "techUnlocks": [
- "trade"
- ],
- "unitUnlocks": [
- "shaman"
- ],
- "improvementUnlocks": [
- "mycelium"
- ],
- "cost": 2,
- "idx": -1
- },
- "spearing": {
- "abilityUnlocks": [
- "destroy"
- ],
- "unitUnlocks": [
- "tridention"
- ],
- "cost": 3
- },
- "sledding": {
- "techUnlocks": [
- "polarism"
- ],
- "unitUnlocks": [
- "battlesled"
- ],
- "improvementUnlocks": [
- "harvestaquacrop"
- ],
- "cost": 2
- },
- "frostwork": {
- "techUnlocks": [
- "navigation"
- ],
- "unitUnlocks": [
- "mooni"
- ],
- "improvementUnlocks": [
- "outpost"
- ],
- "cost": 2
- },
- "polarwarfare": {
- "unitUnlocks": [
- "icefortress",
- "yuukwi"
- ],
- "improvementUnlocks": []
- },
- "polarism": {
- "improvementUnlocks": []
- },
- "hydrology": {
- "techUnlocks": [
- "aquatism"
- ],
- "improvementUnlocks":[
- "+harvestaquacrop"
- ],
- "unitUnlocks": [
- "-boomchi"
- ]
- },
- "fishingplus": {
- "techUnlocks": [
- "embarksailing",
- "aquaculture"
- ],
- "improvementUnlocks": [
- "fishing"
- ],
- "cost": 1,
- "idx": -1
- },
- "cymsailing": {
- "unitUnlocks": [
- "boomchi"
- ],
- "techUnlocks": [
- "navigation"
- ],
- "movementUnlocks": {
- "water": 1
- },
- "cost": 2,
- "idx": -1
- },
- "marinelife": {
- "movementUnlocks": {
- "ocean": 2
- }
- },
- "aquanavigation": {
- "unitUnlocks": [
- "bombership"
- ],
- "cost": 3,
- "idx": -1
- },
- "waterways": {
- "improvementUnlocks": [
- "canal",
- "atoll"
- ]
- },
- "trade": {
- "taskUnlocks": []
- }
- },
- "unitData": {
- "scout": {
- "cost": 5,
- "unitAbilities": [
- "+staticplus"
- ]
- },
- "knight": {
- "health":100,
- "attack": 35,
- "defence": 10,
- "movement": 3,
- "range": 1,
- "cost": 8,
- "unitAbilities": [
- "-fortify",
- "+staticplus"
- ]
- },
- "mindbender": {
- "health": 100,
- "defence": 10,
- "movement": 1,
- "range": 1,
- "attack": 0,
- "cost": 5,
- "weapon": 4,
- "promotionLimit": 3
- },
- "giant": {
- "unitAbilities": [
- "-static",
- "+staticplus"
- ]
- },
- "polytaur": {
- "cost": 3,
- "unitAbilities": [
- "-static",
- "+staticplus"
- ]
- },
- "dragonegg": {
- "unitAbilities": [
- "-static",
- "+staticplus"
- ]
- },
- "babydragon": {
- "unitAbilities": [
- "-static",
- "+staticplus"
- ]
- },
- "firedragon": {
- "unitAbilities": [
- "-static",
- "+staticplus"
- ]
- },
- "crab": {
- "unitAbilities": [
- "-static",
- "+staticplus"
- ]
- },
- "mooni": {
- "health": 100,
- "defence": 20,
- "movement": 1,
- "range": 1,
- "attack": 0,
- "cost": 3,
- "unitAbilities": [
- "-autofreeze",
- "+staticplus",
- "+freezearea",
- "-skate",
- "+slide"
- ]
- },
- "gaami": {
- "unitAbilities": [
- "-static",
- "+staticplus",
- "+slide"
- ]
- },
- "yuukwi": {
- "health": 100,
- "defence": 0,
- "movement": 2,
- "range": 1,
- "attack": 0,
- "cost": 8,
- "unitAbilities": [
- "skate",
- "freezearea",
- "autofreeze",
- "stiff",
- "staticplus"
- ],
- "weapon": 7,
- "promotionLimit": 3,
- "prefab": "yuukwi",
- "idx": -1
- },
- "icefortress": {
- "health": 200,
- "defence": 30,
- "movement": 1,
- "range": 2,
- "attack": 40,
- "cost": 10,
- "unitAbilities": [
- "-escape",
- "-static",
- "+staticplus",
- "+dash"
- ]
- },
- "hexapod": {
- "unitAbilities": [
- "-sneak"
- ]
- },
- "doomux": {
- "unitAbilities": [
- "+sneak",
- "-static"
- ]
- },
- "centipede": {
- "unitAbilities": [
- "-static",
- "+staticplus"
- ]
- },
- "segment": {
- "unitAbilities": [
- "-static",
- "+staticplus"
- ]
- },
- "shaman": {
- "health": 100,
- "defence": 10,
- "attack": 30,
- "promotionLimit": 3,
- "unitAbilities": [
- "-convert",
- "-static"
- ]
- },
- "cloak": {
- "unitAbilities": [
- "+staticplus",
- "-infiltrate",
- "+revolt",
- "+kamikadze",
- "+surprise"
- ],
- "rebelUnit": "dagger",
- "cost": 5
- },
- "cloak_boat": {
- "unitAbilities": [
- "-static",
- "+staticplus",
- "-infiltrate",
- "+revolt",
- "+kamikadze",
- "+surprise"
- ],
- "rebelUnit": "dagger"
- },
- "dagger": {
- "unitAbilities": [
- "-static",
- "+staticplus"
- ],
- "embarksTo": "pirate"
- },
- "pirate": {
- "unitAbilities": [
- "-static",
- "+staticplus"
- ]
- },
- "mermaidcloak": {
- "unitAbilities": [
- "+staticplus",
- "-infiltrate",
- "+revolt",
- "+kamikadze",
- "+surprise"
- ],
- "rebelUnit": "mermaiddagger",
- "cost": 5
- },
- "mermaiddagger": {
- "unitAbilities": [
- "-static",
- "+staticplus"
- ]
- },
- "moth": {
- "health": 50,
- "unitAbilities": [
- "+hide",
- "-infiltrate",
- "+revolt",
- "+kamikadze",
- "+surprise"
- ],
- "rebelUnit": "bugegg"
- },
- "bugegg": {
- "movement": 1,
- "unitAbilities": [
- "+land"
- ]
- },
- "bombership": {
- "defence": 20,
- "movement": 2,
- "range": 3,
- "attack": 40,
- "cost": 10,
- "hidden": true,
- "upgradesFrom": "transportship",
- "unitAbilities": [
- "-splash",
- "-static",
- "+staticplus"
- ]
- },
- "scoutship": {
- "cost": 3,
- "unitAbilities": [
- "-static",
- "+staticplus"
- ]
- },
- "transportship": {
- "unitAbilities": [
- "-static",
- "+staticplus"
- ]
- },
- "rammership": {
- "unitAbilities": [
- "-static",
- "+staticplus"
- ]
- },
- "juggernaut": {
- "unitAbilities": [
- "-stiff",
- "-static",
- "+staticplus"
- ]
- },
- "raychi": {
- "unitAbilities": [
- "-water",
- "+amphibious"
- ]
- },
- "island": {
- "cost": 15
- },
- "phychi": {
- "attack": 10
- }
- },
- "improvementData": {
- "port": {
- "cost": 5,
- "improvementAbilities": []
- },
- "temple": {
- "terrainRequirements": []
- },
- "fertilize": {
- "cost": 5,
- "terrainRequirements": [
- {
- "terrain": "field"
- }
- ],
- "creates": [
- {
- "resource": "crop"
- }
- ],
- "improvementAbilities": [
- "consumed"
- ],
- "maxLevel": 0
- },
- "aquafertilize": {
- "cost": 5,
- "terrainRequirements": [
- {
- "terrain": "field"
- },
- {
- "effect": "flooded"
- }
- ],
- "creates": [
- {
- "resource": "crop"
- }
- ],
- "improvementAbilities": [
- "consumed"
- ],
- "maxLevel": 0,
- "idx": -1
- },
- "fungi": {
- "cost": 7,
- "terrainRequirements": [
- {
- "resource": "crop"
- },
- {
- "resource": "spores"
- }
- ],
- "maxLevel": 2
- },
- "customshouse": {
- "hidden": false,
- "cost": 10,
- "work": 1,
- "terrainRequirements": [
- {
- "terrain": "field"
- }
- ],
- "adjacencyRequirements": [
- {
- "improvement": "port"
- }
- ],
- "adjacencyImprovements": [
- {
- "improvement": "port"
- }
- ],
- "improvementAbilities": [
- "limited"
- ],
- "maxLevel": 8,
- "idx": 4
- },
- "harvestaquacrop": {
- "idx": -1,
- "cost": 5,
- "terrainRequirements": [
- {
- "resource": "aquacrop"
- }
- ],
- "improvementAbilities": [
- "consumed"
- ],
- "maxLevel": 0,
- "rewards": [
- {
- "population": 2
- }
- ],
- "shouldSuggestUnlock": true
- },
- "enchantanimal": {
- "cost": 3
- },
- "market": {
- "improvementAbilities": [
- "limited",
- "halved"
- ]
- },
- "guild": {
- "cost": 7,
- "rewards": [
- {
- "population": 2
- }
- ],
- "terrainRequirements": [
- {
- "terrain": "field"
- },
- {
- "terrain": "forest"
- },
- {
- "terrain": "mountain"
- }
- ],
- "improvementAbilities": [
- "limited"
- ],
- "maxLevel": 0,
- "idx": -1
- },
- "instantembark": {
- "idx": -1,
- "cost": 0,
- "terrainRequirements": [
- {
- "effect": "flooded"
- }
- ],
- "improvementAbilities": [
- "discrete",
- "embarkmanual",
- "manual",
- "freelance"
- ]
- },
- "windmill": {
- "terrainRequirements": [
- {
- "terrain": "field"
- },
- {
- "terrain": "mountain"
- }
- ]
- },
- "sawmill": {
- "terrainRequirements": [
- {
- "terrain": "field"
- },
- {
- "terrain": "mountain"
- }
- ]
- },
- "forge": {
- "terrainRequirements": [
- {
- "terrain": "field"
- },
- {
- "terrain": "mountain"
- }
- ]
- },
- "algae": {
- "cost": 3,
- "creates": [
- {
- "effect": "algae"
- }
- ]
- },
- "clathrus": {
- "terrainRequirements": [
- {
- "terrain": "water"
- },
- {
- "terrain": "ocean"
- }
- ],
- "adjacencyRequirements": [
- {
- "effect": "algae"
- }
- ],
- "adjacencyImprovements": [
- {
- "effect": "algae"
- }
- ],
- "improvementAbilities": [
- "poison",
- "limited"
- ]
- },
- "makebloom": {
- "idx": -1,
- "maxLevel": 0,
- "cost": 2,
- "terrainRequirements": [
- {
- "effect": "algae"
- }
- ],
- "creates": [
- {
- "effect": "blooming"
- }
- ],
- "rewards": [
- {
- "population": 1
- }
- ],
- "improvementAbilities": [
- "discrete"
- ]
- },
- "mycogrove": {
- "idx": -1,
- "maxLevel": 0,
- "cost": 2,
- "improvementAbilities": [
- "progresser"
- ],
- "rewards": [
- {
- "population": 4
- }
- ],
- "terrainRequirements": [
- {
- "improvement": "fungi"
- }
- ]
- },
- "mycelium": {
- "improvementAbilities": [
- "-limited",
- "-heal",
- "+healplus"
- ]
- }
- },
- "resourceData": {
- "aquacrop": {
- "idx": 9,
- "resourceTerrainRequirements": [
- "water",
- "ocean"
- ]
- }
- },
- "diplomacyData":{
- "embassyIncome": 1
- },
- "improvementAbility": {
- "halved": {
- "idx": -1
- },
- "embarkmanual": {
- "idx": -1
- },
- "healplus": {
- "idx": -1
- },
- "progresser": {
- "idx": -1
- }
- },
- "playerAbility": {
- "waterembark": {
- "idx": -1
- },
- "dashembark": {
- "idx": -1
- }
- },
- "unitAbility": {
- "staticplus": {
- "idx": -1
- },
- "slide": {
- "idx": -1
- },
- "revolt": {
- "idx": -1
- },
- "kamikadze": {
- "idx": -1
- }
- },
- "tribeAbility": {
- "citypark": {
- "idx": -1
- }
- },
- "tileEffect": {
- "blooming": {
- "idx": -1
- },
- "rebellion": {
- "idx": -1
- }
- }
-}
diff --git a/PolyPlus/patch_effects.json b/PolyPlus/patch_effects.json
new file mode 100644
index 0000000..5dd562a
--- /dev/null
+++ b/PolyPlus/patch_effects.json
@@ -0,0 +1,21 @@
+{
+ "tileEffect": {
+ "blooming": {
+ "idx": -1
+ },
+ "rebellion": {
+ "idx": -1
+ },
+ "overcap": {
+ "idx": -1
+ }
+ },
+ "unitEffect": {
+ "enablemovement": {
+ "idx": -1
+ },
+ "enableattack": {
+ "idx": -1
+ }
+ }
+}
diff --git a/PolyPlus/patch_improvements.json b/PolyPlus/patch_improvements.json
new file mode 100644
index 0000000..da2ab80
--- /dev/null
+++ b/PolyPlus/patch_improvements.json
@@ -0,0 +1,315 @@
+{
+ "improvementData": {
+ "port": {
+ "cost": 5,
+ "improvementAbilities": []
+ },
+ "temple": {
+ "terrainRequirements": []
+ },
+ "road": {
+ "improvementAbilities":[
+ "+strictreq"
+ ]
+ },
+ "fertilize": {
+ "cost": 5,
+ "terrainRequirements": [
+ {
+ "terrain": "field"
+ }
+ ],
+ "creates": [
+ {
+ "resource": "crop"
+ }
+ ],
+ "improvementAbilities": [
+ "consumed",
+ "strictreq"
+ ],
+ "maxLevel": 0
+ },
+ "aquafertilize": {
+ "cost": 5,
+ "terrainRequirements": [
+ {
+ "terrain": "field"
+ },
+ {
+ "effect": "flooded"
+ }
+ ],
+ "creates": [
+ {
+ "resource": "crop"
+ }
+ ],
+ "improvementAbilities": [
+ "consumed",
+ "strictreq"
+ ],
+ "maxLevel": 0,
+ "idx": -1
+ },
+ "fungi": {
+ "cost": 7,
+ "terrainRequirements": [
+ {
+ "resource": "crop"
+ },
+ {
+ "resource": "spores"
+ }
+ ],
+ "maxLevel": 2
+ },
+ "customshouse": {
+ "hidden": false,
+ "cost": 10,
+ "work": 1,
+ "terrainRequirements": [
+ {
+ "terrain": "field"
+ }
+ ],
+ "adjacencyRequirements": [
+ {
+ "improvement": "port"
+ }
+ ],
+ "adjacencyImprovements": [
+ {
+ "improvement": "port"
+ }
+ ],
+ "improvementAbilities": [
+ "limited"
+ ],
+ "maxLevel": 8,
+ "idx": 4
+ },
+ "harvestaquacrop": {
+ "idx": -1,
+ "cost": 5,
+ "terrainRequirements": [
+ {
+ "resource": "aquacrop"
+ }
+ ],
+ "improvementAbilities": [
+ "consumed"
+ ],
+ "maxLevel": 0,
+ "rewards": [
+ {
+ "population": 2
+ }
+ ],
+ "shouldSuggestUnlock": true
+ },
+ "enchantanimal": {
+ "cost": 3
+ },
+ "market": {
+ "improvementAbilities": [
+ "limited",
+ "halved"
+ ]
+ },
+ "guild": {
+ "cost": 7,
+ "rewards": [
+ {
+ "population": 2
+ }
+ ],
+ "terrainRequirements": [
+ {
+ "terrain": "field"
+ },
+ {
+ "terrain": "forest"
+ },
+ {
+ "terrain": "mountain"
+ }
+ ],
+ "improvementAbilities": [
+ "limited"
+ ],
+ "maxLevel": 0,
+ "idx": -1
+ },
+ "instantembark": {
+ "idx": -1,
+ "cost": 0,
+ "terrainRequirements": [
+ {
+ "effect": "flooded"
+ }
+ ],
+ "improvementAbilities": [
+ "discrete",
+ "embarkmanual",
+ "manual",
+ "freelance"
+ ]
+ },
+ "windmill": {
+ "terrainRequirements": [
+ {
+ "terrain": "field"
+ },
+ {
+ "terrain": "mountain"
+ }
+ ]
+ },
+ "sawmill": {
+ "terrainRequirements": [
+ {
+ "terrain": "field"
+ },
+ {
+ "terrain": "mountain"
+ }
+ ]
+ },
+ "forge": {
+ "terrainRequirements": [
+ {
+ "terrain": "field"
+ },
+ {
+ "terrain": "mountain"
+ }
+ ]
+ },
+ "algae": {
+ "cost": 3,
+ "creates": [
+ {
+ "effect": "algae"
+ }
+ ]
+ },
+ "clathrus": {
+ "terrainRequirements": [
+ {
+ "terrain": "water"
+ },
+ {
+ "terrain": "ocean"
+ }
+ ],
+ "adjacencyRequirements": [
+ {
+ "effect": "algae"
+ }
+ ],
+ "adjacencyImprovements": [
+ {
+ "effect": "algae"
+ }
+ ],
+ "improvementAbilities": [
+ "poison",
+ "limited"
+ ]
+ },
+ "makebloom": {
+ "idx": -1,
+ "maxLevel": 0,
+ "cost": 2,
+ "terrainRequirements": [
+ {
+ "effect": "algae"
+ }
+ ],
+ "creates": [
+ {
+ "effect": "blooming"
+ }
+ ],
+ "rewards": [
+ {
+ "population": 1
+ }
+ ],
+ "improvementAbilities": [
+ "discrete"
+ ]
+ },
+ "mycogrove": {
+ "idx": -1,
+ "maxLevel": 0,
+ "cost": 2,
+ "creates": [
+ {
+ "effect": "overcap"
+ }
+ ],
+ "rewards": [
+ {
+ "population": 1
+ }
+ ],
+ "improvementAbilities": [
+ "discrete",
+ "overcapper"
+ ],
+ "terrainRequirements": [
+ {
+ "improvement": "fungi"
+ }
+ ]
+ },
+ "mycelium": {
+ "improvementAbilities": [
+ "-limited",
+ "-heal",
+ "+healplus"
+ ]
+ },
+ "canal": {
+ "improvementAbilities": [
+ "+strictreq"
+ ]
+ },
+ "sanctuary": {
+ "work": 0,
+ "growthRewards": [
+ {
+ "population": 1
+ }
+ ],
+ "improvementAbilities": [
+ "attract",
+ "limited"
+ ],
+ "growthRate": 3
+ },
+ "enchantforest": {
+ "cost": 8,
+ "terrainRequirements": [
+ {
+ "terrain": "forest"
+ }
+ ],
+ "improvementAbilities": [
+ "consumed"
+ ],
+ "maxLevel": 0,
+ "creates": [
+ {
+ "unit": "treant"
+ },
+ {
+ "terrain": "field"
+ }
+ ],
+ "idx": -1
+ }
+ }
+}
diff --git a/PolyPlus/patch_others.json b/PolyPlus/patch_others.json
new file mode 100644
index 0000000..7966803
--- /dev/null
+++ b/PolyPlus/patch_others.json
@@ -0,0 +1,61 @@
+{
+ "resourceData": {
+ "aquacrop": {
+ "idx": 9,
+ "resourceTerrainRequirements": [
+ "water",
+ "ocean"
+ ]
+ }
+ },
+ "diplomacyData":{
+ "embassyIncome": 1
+ },
+ "improvementAbility": {
+ "halved": {
+ "idx": -1
+ },
+ "embarkmanual": {
+ "idx": -1
+ },
+ "healplus": {
+ "idx": -1
+ },
+ "overcapper": {
+ "idx": -1
+ },
+ "strictreq": {
+ "idx": -1
+ }
+ },
+ "playerAbility": {
+ "waterembark": {
+ "idx": -1
+ },
+ "dashembark": {
+ "idx": -1
+ }
+ },
+ "unitAbility": {
+ "staticplus": {
+ "idx": -1
+ },
+ "slide": {
+ "idx": -1
+ },
+ "revolt": {
+ "idx": -1
+ },
+ "kamikadze": {
+ "idx": -1
+ },
+ "absorb": {
+ "idx": -1
+ }
+ },
+ "tribeAbility": {
+ "citypark": {
+ "idx": -1
+ }
+ }
+}
diff --git a/PolyPlus/patch_techs.json b/PolyPlus/patch_techs.json
new file mode 100644
index 0000000..c7d93a3
--- /dev/null
+++ b/PolyPlus/patch_techs.json
@@ -0,0 +1,311 @@
+{
+ "techData": {
+ "cymbase": {
+ "improvementUnlocks": [
+ "makebloom"
+ ],
+ "cost": 0,
+ "idx": -1
+ },
+ "recycling": {
+ "abilityUnlocks": [
+ "-microbes",
+ "-decompose",
+ "+destroy"
+ ],
+ "improvementUnlocks": [
+ "+mycogrove"
+ ]
+ },
+ "basic": {
+ "techUnlocks": [
+ "organization",
+ "climbing",
+ "fishingplus",
+ "hunting",
+ "freespirit"
+ ],
+ "taskUnlocks": [
+ "+wealth",
+ "+genius"
+ ],
+ "improvementUnlocks": [
+ "+instantembark"
+ ],
+ "abilityUnlocks": [
+ "+disband"
+ ],
+ "movementUnlocks": {
+ "water": 1
+ }
+ },
+ "riding": {
+ "techUnlocks": [
+ "chivalry"
+ ],
+ "cost": 2
+ },
+ "freespirit": {
+ "improvementUnlocks": [
+ "+guild"
+ ],
+ "techUnlocks": [
+ "roads",
+ "shields"
+ ],
+ "abilityUnlocks": [
+ "-disband"
+ ],
+ "cost": 1
+ },
+ "organization": {
+ "techUnlocks": [
+ "-shields",
+ "+riding"
+ ]
+ },
+ "meditation": {
+ "improvementUnlocks": [
+ "-mountaintemple"
+ ],
+ "unitUnlocks": [
+ "+mindbender"
+ ],
+ "abilityUnlocks": [
+ "+discipline"
+ ]
+ },
+ "philosophy": {
+ "unitUnlocks": [
+ "-mindbender"
+ ],
+ "taskUnlocks": [
+ "-genius"
+ ]
+ },
+ "aquatism": {
+ "improvementUnlocks": [
+ "customshouse"
+ ]
+ },
+ "embarquatism": {
+ "improvementUnlocks": [
+ "customshouse"
+ ],
+ "abilityUnlocks": [
+ "dashembark"
+ ],
+ "cost": 3,
+ "idx": -1
+ },
+ "spiritualism": {
+ "improvementUnlocks": [
+ "-foresttemple"
+ ]
+ },
+ "construction": {
+ "improvementUnlocks": [
+ "-burnforest",
+ "+fertilize"
+ ]
+ },
+ "navigation": {
+ "unitUnlocks": [
+ "bombership",
+ "rammership"
+ ],
+ "movementUnlocks": {
+ "ocean": 1
+ },
+ "improvementUnlocks": [
+ "-starfishing",
+ "-watertemple"
+ ],
+ "cost": 3
+ },
+ "fishing": {
+ "improvementUnlocks": [
+ "-port"
+ ],
+ "movementUnlocks": {}
+ },
+ "aquaculture": {
+ "techUnlocks": [
+ "embarquatism"
+ ],
+ "improvementUnlocks": [
+ "harvestaquacrop",
+ "port"
+ ],
+ "unitUnlocks": [
+ "-rammership"
+ ],
+ "cost": 2
+ },
+ "embarksailing": {
+ "techUnlocks": [
+ "navigation"
+ ],
+ "abilityUnlocks": [
+ "waterembark"
+ ],
+ "unitUnlocks": [
+ "scoutship"
+ ],
+ "cost": 2,
+ "idx": -1
+ },
+ "riding2": {
+ "techUnlocks": [
+ "spearing"
+ ],
+ "cost": 2
+ },
+ "freediving": {
+ "techUnlocks": [
+ "roads",
+ "shields"
+ ],
+ "improvementUnlocks": [
+ "temple"
+ ],
+ "abilityUnlocks": [
+ "-disband"
+ ],
+ "movementUnlocks": {
+ "ocean": 0
+ },
+ "cost": 1
+ },
+ "cymroads": {
+ "techUnlocks": [
+ "trade"
+ ],
+ "unitUnlocks": [
+ "shaman"
+ ],
+ "improvementUnlocks": [
+ "mycelium"
+ ],
+ "cost": 2,
+ "idx": -1
+ },
+ "spearing": {
+ "abilityUnlocks": [
+ "destroy"
+ ],
+ "unitUnlocks": [
+ "tridention"
+ ],
+ "cost": 3
+ },
+ "sledding": {
+ "techUnlocks": [
+ "polarism"
+ ],
+ "unitUnlocks": [
+ "battlesled"
+ ],
+ "improvementUnlocks": [
+ "harvestaquacrop"
+ ],
+ "cost": 2
+ },
+ "frostwork": {
+ "techUnlocks": [
+ "navigation"
+ ],
+ "unitUnlocks": [
+ "mooni"
+ ],
+ "improvementUnlocks": [
+ "outpost"
+ ],
+ "cost": 2
+ },
+ "polarwarfare": {
+ "unitUnlocks": [
+ "icefortress",
+ "yuukwi"
+ ],
+ "improvementUnlocks": []
+ },
+ "polarism": {
+ "improvementUnlocks": []
+ },
+ "hydrology": {
+ "techUnlocks": [
+ "aquatism"
+ ],
+ "improvementUnlocks":[
+ "+harvestaquacrop"
+ ],
+ "unitUnlocks": [
+ "-boomchi"
+ ]
+ },
+ "fishingplus": {
+ "techUnlocks": [
+ "embarksailing",
+ "aquaculture"
+ ],
+ "improvementUnlocks": [
+ "fishing"
+ ],
+ "cost": 1,
+ "idx": -1
+ },
+ "cymsailing": {
+ "unitUnlocks": [
+ "boomchi"
+ ],
+ "techUnlocks": [
+ "navigation"
+ ],
+ "movementUnlocks": {
+ "water": 1
+ },
+ "cost": 2,
+ "idx": -1
+ },
+ "marinelife": {
+ "movementUnlocks": {
+ "ocean": 2
+ }
+ },
+ "aquanavigation": {
+ "unitUnlocks": [
+ "bombership"
+ ],
+ "cost": 3,
+ "idx": -1
+ },
+ "waterways": {
+ "improvementUnlocks": [
+ "atoll"
+ ]
+ },
+ "trade": {
+ "taskUnlocks": []
+ },
+ "aquabase": {
+ "improvementUnlocks": [
+ "canal"
+ ]
+ },
+ "elyforestry": {
+ "techUnlocks": [
+ "mathematics"
+ ],
+ "improvementUnlocks": [
+ "sanctuary",
+ "enchantforest"
+ ],
+ "abilityUnlocks": [
+ "treehouse"
+ ],
+ "cost": 2,
+ "idx": -1
+ }
+ }
+}
diff --git a/PolyPlus/patch_tribes.json b/PolyPlus/patch_tribes.json
new file mode 100644
index 0000000..6c00a4f
--- /dev/null
+++ b/PolyPlus/patch_tribes.json
@@ -0,0 +1,167 @@
+{
+ "tribeData": {
+ "aimo": {
+ "startingUnit": "mindbender",
+ "startingStars": 5,
+ "startingTech": [
+ "basic",
+ "meditation"
+ ]
+ },
+ "aquarion": {
+ "techOverrides": {
+ "navigation": "aquanavigation",
+ "embarquatism": "aquatism",
+ "embarksailing": "marinelife"
+ },
+ "resourceModifier": {
+ "aquacrop": 1.5
+ },
+ "improvementOverrides": {
+ "port": "none",
+ "customshouse": "none"
+ },
+ "tribeAbilities": [],
+ "startingStars": 5
+ },
+ "bardur": {
+ "terrainModifier": {
+ "forest": 1.5
+ },
+ "startingStars": 3
+ },
+ "elyrion": {
+ "startingStars": 5,
+ "techOverrides": {
+ "forestry": "elyforestry"
+ },
+ "tribeAbilities": [
+ "-rainbowvision"
+ ],
+ "improvementOverrides": {
+ "sawmill": "none"
+ },
+ "preview": [
+ {
+ "x": 0,
+ "y": 0,
+ "unitType": "treant",
+ "terrainType": "field"
+ },
+ {
+ "x": 0,
+ "y": 1,
+ "unitType": "polytaur",
+ "terrainType": "forest"
+ }
+ ]
+ },
+ "hoodrick": {
+ "startingStars": 5
+ },
+ "imperius": {
+ "startingStars": 3
+ },
+ "kickoo": {
+ "startingTech": [
+ "basic",
+ "fishingplus"
+ ],
+ "startingStars": 3
+ },
+ "luxidoor": {
+ "startingResource": [],
+ "bonus": 0,
+ "tribeAbilities": [
+ "citypark"
+ ],
+ "startingStars": 5
+ },
+ "oumaji": {
+ "terrainModifier": {
+ "forest": 0.2,
+ "mountain":0.5,
+ "water": 0.5
+ },
+ "resourceModifier": {
+ "game": 1,
+ "crop": 0.5,
+ "fruit": 1.2
+ },
+ "startingStars": 5
+ },
+ "quetzali": {
+ "startingStars": 5
+ },
+ "vengir": {
+ "startingStars": 5
+ },
+ "xinxi": {
+ "startingStars": 5
+ },
+ "yadakk": {
+ "startingStars": 5
+ },
+ "zebasi": {
+ "startingStars": 3
+ },
+ "polaris": {
+ "improvementOverrides": {
+ "customshouse": "none"
+ },
+ "techOverrides": {
+ "embarksailing": "frostwork",
+ "navigation": "polarwarfare",
+ "embarquatism": "polarism",
+ "aquaculture" : "sledding"
+ },
+ "preview": [
+ {
+ "x": 0,
+ "y": -2,
+ "terrainType": "ice",
+ "unitType": "yuukwi"
+ }
+ ],
+ "startingStars": 5
+ },
+ "cymanti": {
+ "startingTech": [
+ "+cymbase"
+ ],
+ "unitOverrides": {
+ "mindbender": "mindbender",
+ "rammership": "raychi"
+ },
+ "improvementOverrides": {
+ "market": "market",
+ "port": "algae",
+ "customshouse": "clathrus"
+ },
+ "techOverrides": {
+ "roads": "cymroads",
+ "construction": "recycling",
+ "chivalry": "shock",
+ "embarksailing": "cymsailing",
+ "meditation": "meditation",
+ "embarquatism": "aquatism"
+ },
+ "startingUnit": "warrior",
+ "preview": [
+ {
+ "x": -1,
+ "y": -2,
+ "unitType": "raychi",
+ "terrainType": "water"
+ },
+ {
+ "x": 2,
+ "y": -1,
+ "unitType": "boomchi",
+ "terrainType": "water"
+ }
+ ],
+ "startingStars": 5
+ }
+ }
+}
diff --git a/PolyPlus/patch_units.json b/PolyPlus/patch_units.json
new file mode 100644
index 0000000..8272bd5
--- /dev/null
+++ b/PolyPlus/patch_units.json
@@ -0,0 +1,296 @@
+{
+ "unitData": {
+ "scout": {
+ "cost": 5,
+ "unitAbilities": [
+ "+staticplus"
+ ]
+ },
+ "knight": {
+ "health":100,
+ "attack": 35,
+ "defence": 10,
+ "movement": 3,
+ "range": 1,
+ "cost": 8,
+ "unitAbilities": [
+ "-fortify",
+ "+staticplus"
+ ]
+ },
+ "mindbender": {
+ "health": 100,
+ "defence": 10,
+ "movement": 1,
+ "range": 1,
+ "attack": 0,
+ "cost": 5,
+ "weapon": 4,
+ "promotionLimit": 3
+ },
+ "giant": {
+ "unitAbilities": [
+ "-static",
+ "+staticplus"
+ ]
+ },
+ "polytaur": {
+ "cost": 3,
+ "unitAbilities": [
+ "-static",
+ "+staticplus"
+ ]
+ },
+ "dragonegg": {
+ "unitAbilities": [
+ "-static",
+ "+staticplus"
+ ]
+ },
+ "babydragon": {
+ "unitAbilities": [
+ "-static",
+ "+staticplus"
+ ]
+ },
+ "firedragon": {
+ "unitAbilities": [
+ "-static",
+ "+staticplus"
+ ]
+ },
+ "crab": {
+ "unitAbilities": [
+ "-static",
+ "+staticplus"
+ ]
+ },
+ "mooni": {
+ "health": 100,
+ "defence": 20,
+ "movement": 1,
+ "range": 1,
+ "attack": 0,
+ "cost": 3,
+ "unitAbilities": [
+ "-autofreeze",
+ "+staticplus",
+ "+freezearea",
+ "-skate",
+ "+slide"
+ ]
+ },
+ "gaami": {
+ "unitAbilities": [
+ "-static",
+ "+staticplus",
+ "+slide"
+ ]
+ },
+ "yuukwi": {
+ "health": 100,
+ "defence": 0,
+ "movement": 2,
+ "range": 1,
+ "attack": 0,
+ "cost": 8,
+ "unitAbilities": [
+ "skate",
+ "freezearea",
+ "autofreeze",
+ "stiff",
+ "staticplus"
+ ],
+ "weapon": 7,
+ "promotionLimit": 3,
+ "prefab": "yuukwi",
+ "idx": -1
+ },
+ "icefortress": {
+ "health": 200,
+ "defence": 30,
+ "movement": 1,
+ "range": 2,
+ "attack": 40,
+ "cost": 10,
+ "unitAbilities": [
+ "-escape",
+ "-static",
+ "+staticplus",
+ "+dash"
+ ]
+ },
+ "hexapod": {
+ "unitAbilities": [
+ "-sneak"
+ ]
+ },
+ "doomux": {
+ "unitAbilities": [
+ "+sneak",
+ "-static"
+ ]
+ },
+ "centipede": {
+ "unitAbilities": [
+ "-static",
+ "+staticplus"
+ ]
+ },
+ "segment": {
+ "unitAbilities": [
+ "-static",
+ "+staticplus"
+ ]
+ },
+ "shaman": {
+ "health": 100,
+ "defence": 10,
+ "attack": 30,
+ "promotionLimit": 3,
+ "unitAbilities": [
+ "-convert",
+ "-static"
+ ]
+ },
+ "cloak": {
+ "unitAbilities": [
+ "+staticplus",
+ "-infiltrate",
+ "+revolt",
+ "+kamikadze",
+ "+surprise"
+ ],
+ "rebelUnit": "dagger",
+ "cost": 5
+ },
+ "cloak_boat": {
+ "unitAbilities": [
+ "-static",
+ "+staticplus",
+ "-infiltrate",
+ "+revolt",
+ "+kamikadze",
+ "+surprise"
+ ],
+ "rebelUnit": "dagger"
+ },
+ "dagger": {
+ "unitAbilities": [
+ "-static",
+ "+staticplus"
+ ],
+ "embarksTo": "pirate"
+ },
+ "pirate": {
+ "unitAbilities": [
+ "-static",
+ "+staticplus"
+ ]
+ },
+ "mermaidcloak": {
+ "unitAbilities": [
+ "+staticplus",
+ "-infiltrate",
+ "+revolt",
+ "+kamikadze",
+ "+surprise"
+ ],
+ "rebelUnit": "mermaiddagger",
+ "cost": 5
+ },
+ "mermaiddagger": {
+ "unitAbilities": [
+ "-static",
+ "+staticplus"
+ ]
+ },
+ "moth": {
+ "health": 50,
+ "unitAbilities": [
+ "+hide",
+ "-infiltrate",
+ "+revolt",
+ "+kamikadze",
+ "+surprise"
+ ],
+ "rebelUnit": "bugegg"
+ },
+ "bugegg": {
+ "movement": 1,
+ "unitAbilities": [
+ "+land"
+ ]
+ },
+ "bombership": {
+ "defence": 20,
+ "movement": 2,
+ "range": 3,
+ "attack": 40,
+ "cost": 10,
+ "hidden": true,
+ "upgradesFrom": "transportship",
+ "unitAbilities": [
+ "-splash",
+ "-static",
+ "+staticplus"
+ ]
+ },
+ "scoutship": {
+ "cost": 3,
+ "unitAbilities": [
+ "-static",
+ "+staticplus"
+ ]
+ },
+ "transportship": {
+ "unitAbilities": [
+ "-static",
+ "+staticplus"
+ ]
+ },
+ "rammership": {
+ "unitAbilities": [
+ "-static",
+ "+staticplus"
+ ]
+ },
+ "juggernaut": {
+ "unitAbilities": [
+ "-stiff",
+ "-static",
+ "+staticplus"
+ ]
+ },
+ "raychi": {
+ "unitAbilities": [
+ "-water",
+ "+amphibious"
+ ]
+ },
+ "island": {
+ "cost": 15
+ },
+ "phychi": {
+ "attack": 10
+ },
+ "treant": {
+ "health": 200,
+ "defence": 20,
+ "movement": 1,
+ "range": 1,
+ "attack": 20,
+ "cost": 8,
+ "unitAbilities": [
+ "dash",
+ "autoheal",
+ "independent",
+ "static"
+ ],
+ "hidden": true,
+ "weapon": 7,
+ "prefab": "treant",
+ "idx": -1
+ }
+ }
+}
diff --git a/PolyPlus/prefab_treant.json b/PolyPlus/prefab_treant.json
new file mode 100644
index 0000000..81f0ea8
--- /dev/null
+++ b/PolyPlus/prefab_treant.json
@@ -0,0 +1,22 @@
+{
+ "type": 0,
+ "name": "Treant",
+ "visualParts": [
+ {
+ "gameObjectName": "Body",
+ "baseName": "body",
+ "coordinates": [0, 0.2],
+ "rotation": 0,
+ "scale": [1, 1],
+ "tintable": false
+ },
+ {
+ "gameObjectName": "Body_Tint",
+ "baseName": "body_tint",
+ "coordinates": [0, 0.2],
+ "rotation": 0,
+ "scale": [1, 1],
+ "tintable": true
+ }
+ ]
+}
\ No newline at end of file
diff --git a/PolyPlus/sprites.json b/PolyPlus/sprites.json
index 53ee544..dbee70d 100644
--- a/PolyPlus/sprites.json
+++ b/PolyPlus/sprites.json
@@ -29,12 +29,48 @@
"pixelsPerUnit":1950,
"pivot": [0.5, 0.5]
},
+ "field_aquarion_": {
+ "pixelsPerUnit": 265,
+ "pivot": [0.5, 0]
+ },
+ "mountain_aquarion_": {
+ "pixelsPerUnit": 239,
+ "pivot": [0.6, -0.6]
+ },
+ "field_swamp_": {
+ "pixelsPerUnit": 265,
+ "pivot": [0.5, 0]
+ },
+ "mountain_swamp_": {
+ "pixelsPerUnit": 239,
+ "pivot": [0.6, -0.6]
+ },
"algae_blooming__": {
"pixelsPerUnit":264,
"pivot": [0.5, 0.5]
},
+ "fungi__4": {
+ "pixelsPerUnit": 976,
+ "pivot": [0.5, 0.5]
+ },
"mycogrove__": {
"pixelsPerUnit": 976,
- "pivot": [0.5, 0.3]
+ "pivot": [0.5, 0.5]
+ },
+ "body_treant__": {
+ "pixelsPerUnit": 1690,
+ "pivot": [0.5, 0.5]
+ },
+ "body_treant_darkelf_": {
+ "pixelsPerUnit": 1760,
+ "pivot": [0.5, 0.5]
+ },
+ "body_tint_treant__": {
+ "pixelsPerUnit": 1760,
+ "pivot": [0.5, 0.5]
+ },
+ "body_treant_outline__": {
+ "pixelsPerUnit": 1496,
+ "pivot": [0.5, 0.5]
}
}
\ No newline at end of file
diff --git a/PolyPlus/treehouse__.png b/PolyPlus/treehouse__.png
new file mode 100644
index 0000000..cd8ebd7
Binary files /dev/null and b/PolyPlus/treehouse__.png differ
diff --git a/src/ApiHandler.cs b/src/ApiHandler.cs
index 0733c5d..8eb8eed 100644
--- a/src/ApiHandler.cs
+++ b/src/ApiHandler.cs
@@ -11,10 +11,10 @@ public static class ApiHandler
[HarmonyPatch(typeof(GameLogicData), nameof(GameLogicData.MeetsRequirement))]
public static bool MeetsRequirement(ref bool __result, GameLogicData __instance, TileData tile, ImprovementData improvement, PlayerState playerState, GameState gameState)
{
- bool hasResourceRequirement = false;
+ bool hasTerrainRequirement = false;
bool meetsTerrainRequirement = false;
- bool hasTerrainRequirement = false;
+ bool hasResourceRequirement = false;
bool meetsResourceRequirement = false;
bool hasImprovementRequirement = false;
@@ -49,11 +49,21 @@ public static bool MeetsRequirement(ref bool __result, GameLogicData __instance,
}
else
{
- if (tile.IsWater && terrainRequirements.terrain.type == TerrainData.Type.Field && improvement.type != ImprovementData.Type.Road && playerState.HasAbility(PlayerAbility.Type.Pontoon, gameState))
+ if (
+ tile.IsWater &&
+ terrainRequirements.terrain.type == TerrainData.Type.Field &&
+ !improvement.HasAbility(EnumCache.GetType("strictreq")) &&
+ playerState.HasAbility(PlayerAbility.Type.Pontoon, gameState)
+ )
{
meetsTerrainRequirement = true;
}
- if (tile.terrain == TerrainData.Type.Forest && terrainRequirements.terrain.type == TerrainData.Type.Field && playerState.HasAbility(PlayerAbility.Type.Treehouse, gameState))
+ if (
+ tile.terrain == TerrainData.Type.Forest &&
+ terrainRequirements.terrain.type == TerrainData.Type.Field &&
+ !improvement.HasAbility(EnumCache.GetType("strictreq")) &&
+ playerState.HasAbility(PlayerAbility.Type.Treehouse, gameState)
+ )
{
meetsTerrainRequirement = true;
}
diff --git a/src/Data/UnitMovementType.cs b/src/Data/UnitMovementType.cs
new file mode 100644
index 0000000..12f32eb
--- /dev/null
+++ b/src/Data/UnitMovementType.cs
@@ -0,0 +1,14 @@
+using Polytopia.Data;
+
+namespace PolyPlus.Data
+{
+ public enum UnitMovementType
+ {
+ None,
+ Land,
+ Amphibious,
+ Water,
+ Air,
+ Sled
+ }
+}
\ No newline at end of file
diff --git a/src/Diplomacy.cs b/src/Diplomacy.cs
index 008a4f4..82372d8 100644
--- a/src/Diplomacy.cs
+++ b/src/Diplomacy.cs
@@ -64,7 +64,7 @@ private static void GetAttackOptionsAtPosition(
Il2CppSystem.Collections.Generic.List area = gameState.Map.GetArea(position, range, true, false);
- if (unitState.HasAbility(EnumCache.GetType("revolt"), gameState)
+ if (unitState.HasAbility(EnumCache.GetType("revolt"))
&& gameState.TryGetPlayer(playerId, out PlayerState playerState))
{
Il2CppSystem.Collections.Generic.List list = new Il2CppSystem.Collections.Generic.List();
@@ -85,7 +85,7 @@ private static void GetAttackOptionsAtPosition(
isInPeace = PlayerDiplomacyExtensions.HasPeaceWith(playerState, tileData.owner);
if (!isInPeace)
{
- isInPeace = PlayerDiplomacyExtensions.HasBrokenPeaceWith(playerState, tileData.owner);
+ isInPeace = PlayerDiplomacyExtensions.HasCoolDownWith(playerState, tileData.owner);
}
}
diff --git a/src/Generation.cs b/src/Generation.cs
index a2168db..ae56ca6 100644
--- a/src/Generation.cs
+++ b/src/Generation.cs
@@ -6,19 +6,42 @@ namespace PolyPlus
public class Generation
{
[HarmonyPostfix]
- [HarmonyPatch(typeof(MapGenerator), nameof(MapGenerator.SetTileAsCapital))]
- private static void MapGenerator_SetTileAsCapital(GameState gameState, PlayerState playerState, TileData tile)
+ [HarmonyPatch(typeof(MapGenerator), nameof(MapGenerator.GenerateInternal))]
+ private static void MapGenerator_AddLightHouseImprovements(int seed, GameState gameState, MapGeneratorSettings settings)
{
- TribeData tribeData;
- if (tile != null && gameState.GameLogicData.TryGetData(playerState.tribe, out tribeData))
+ WorldCoordinates[] corners = ExploreLightHouseTask.GetCorners(gameState);
+ for (int i = 0; i < corners.Length; i++)
{
- if (tribeData.HasAbility(EnumCache.GetType("citypark")))
+ TileData tile = gameState.Map.GetTile(corners[i]);
+ if(tile.HasImprovement(ImprovementData.Type.LightHouse))
{
- tile.improvement.production = 2;
- tile.improvement.baseScore += 250;
- tile.improvement.AddReward(CityReward.Park);
+ tile.improvement = null; // Yes, I know about AddLightHouseImprovements. It is simply not longer called. idk why
}
}
}
+
+ [HarmonyPostfix]
+ [HarmonyPatch(typeof(MapGenerator), nameof(MapGenerator.SetTileAsCapital))]
+ private static void MapGenerator_SetTileAsCapital(GameState gameState, PlayerState playerState, TileData tile)
+ {
+ if (tile == null || !gameState.GameLogicData.TryGetData(playerState.tribe, out TribeData tribeData)
+ || !tribeData.HasAbility(EnumCache.GetType("citypark")))
+ {
+ return;
+ }
+
+ tile.improvement.production = 2;
+ tile.improvement.baseScore += 250;
+ tile.improvement.AddReward(CityReward.Park);
+ }
+
+ [HarmonyPrefix]
+ [HarmonyPatch(typeof(ActionUtils), nameof(ActionUtils.OnRevealLighthouseTile))]
+ public static bool OnRevealLighthouseTile(GameState gameState, PlayerState playerState, WorldCoordinates tile)
+ {
+ gameState.CheckTask(playerState, TaskData.Type.ExploreLighthouses);
+ ActionUtils.EnableTask(gameState, playerState, TaskData.Type.ExploreLighthouses);
+ return false;
+ }
}
}
\ No newline at end of file
diff --git a/src/Main.cs b/src/Main.cs
index 3ab023c..9faaa21 100644
--- a/src/Main.cs
+++ b/src/Main.cs
@@ -1,7 +1,9 @@
-using HarmonyLib;
+using BepInEx.Logging;
+using HarmonyLib;
using Newtonsoft.Json.Linq;
using PolyPlus.Utils;
using Polytopia.Data;
+using PolytopiaBackendBase.Common;
using UnityEngine;
namespace PolyPlus
@@ -9,10 +11,12 @@ namespace PolyPlus
public static class Main
{
private static Color32 bloomColor = new Color32(255, 105, 225, 255);
-
- public static void Load()
+ internal static ManualLogSource? modLogger;
+ public static void Load(ManualLogSource logger)
{
+ modLogger = logger;
PolyMod.Loader.AddPatchDataType("tileEffect", typeof(TileData.EffectType));
+ PolyMod.Loader.AddPatchDataType("unitEffect", typeof(UnitEffect));
Harmony.CreateAndPatchAll(typeof(Main));
Harmony.CreateAndPatchAll(typeof(ApiHandler));
Harmony.CreateAndPatchAll(typeof(Diplomacy));
@@ -145,7 +149,7 @@ public static void EndTurnCommand_ExecuteDefault(EndTurnCommand __instance, Game
[HarmonyPatch(typeof(GameLogicData), nameof(GameLogicData.CanBuild))]
private static void GameLogicData_CanBuild(ref bool __result, GameLogicData __instance, GameState gameState, TileData tile, PlayerState playerState, ImprovementData improvement)
{
- if(improvement.HasAbility(EnumCache.GetType("progresser")) && tile.improvement != null)
+ if(improvement.HasAbility(EnumCache.GetType("overcapper")) && tile.improvement != null)
{
if(Parser.improvementTerrainReq.ContainsKey(improvement.type))
{
@@ -154,7 +158,8 @@ private static void GameLogicData_CanBuild(ref bool __result, GameLogicData __in
{
if(req.improvement != ImprovementData.Type.None && tile.HasImprovement(req.improvement) && __instance.TryGetData(req.improvement, out ImprovementData requirementData))
{
- if(tile.improvement.level == requirementData.MaxLevel(playerState, gameState))
+ if(tile.improvement.level == requirementData.MaxLevel(playerState, gameState) &&
+ !tile.HasEffect(EnumCache.GetType("overcap")))
{
__result = true;
}
@@ -198,25 +203,33 @@ private static void GameLogicData_CanBuild(ref bool __result, GameLogicData __in
}
}
}
-
- [HarmonyPostfix]
+ [HarmonyPrefix]
[HarmonyPatch(typeof(BuildAction), nameof(BuildAction.Execute))]
- private static void BuildAction_Execute(BuildAction __instance, GameState gameState)
+ private static bool BuildAction_Execute(BuildAction __instance, GameState gameState)
{
- if (gameState.GameLogicData.TryGetData(__instance.Type, out ImprovementData improvementData))
+ TileData tileData = gameState.Map.GetTile(__instance.Coordinates); // So, in order to enable movement for unit later I added an effect !
+ UnitState unit = tileData.unit;
+ if(unit != null && __instance.Type == ImprovementData.Type.Canal)
{
- if(improvementData.HasAbility(EnumCache.GetType("progresser")))
+ if(!unit.moved)
{
- TileData tile = gameState.Map.GetTile(__instance.Coordinates);
- TileData cityTile = gameState.Map.GetTile(tile.rulingCityCoordinates);
- if (cityTile.HasImprovement(ImprovementData.Type.City))
- {
- gameState.TryGetPlayer(cityTile.owner, out PlayerState playerState);
- ActionUtils.RemoveScore(playerState, ScoreSheet.cityXPScore * 3);
- cityTile.improvement.AddPopulation(-3);
- }
+ Console.Write("ADDDING ENABLE MOVEMENT");
+ unit.AddEffect(EnumCache.GetType("enablemovement"));
}
+ if(!unit.attacked)
+ {
+ unit.AddEffect(EnumCache.GetType("enableattack"));
+ }
+ }
+ return true;
+ }
+ [HarmonyPostfix]
+ [HarmonyPatch(typeof(BuildAction), nameof(BuildAction.Execute))]
+ private static void BuildAction_Execute_Postfix(BuildAction __instance, GameState gameState)
+ {
+ if (gameState.GameLogicData.TryGetData(__instance.Type, out ImprovementData improvementData))
+ {
if (improvementData.HasAbility(EnumCache.GetType("embarkmanual")))
{
gameState.ActionStack.Add(new EmbarkAction(__instance.PlayerId, __instance.Coordinates));
@@ -237,6 +250,35 @@ private static void BuildAction_Execute(BuildAction __instance, GameState gameSt
}
}
+
+ [HarmonyPostfix]
+ [HarmonyPatch(typeof(FloodCommand), nameof(FloodCommand.Execute))]
+ private static void FloodCommand_Execute(FloodCommand __instance, GameState state)
+ {
+ TileData tileData = state.Map.GetTile(__instance.Coordinates);
+ EnableUnit(tileData);
+ }
+
+ private static void EnableUnit(TileData tileData) // thats insane i know pls forgive (caused by polymod)
+ {
+ UnitState unit = tileData.unit;
+
+ if(unit == null)
+ {
+ return;
+ }
+ if(unit.HasEffect(EnumCache.GetType("enablemovement")))
+ {
+ unit.moved = false;
+ }
+ if(unit.HasEffect(EnumCache.GetType("enableattack")))
+ {
+ unit.attacked = false;
+ }
+ unit.RemoveEffect(EnumCache.GetType("enablemovement"));
+ unit.RemoveEffect(EnumCache.GetType("enableattack"));
+ }
+
[HarmonyPostfix]
[HarmonyPatch(typeof(CommandUtils), nameof(CommandUtils.GetUnitActions))]
private static void CommandUtils_GetUnitActions(ref Il2CppSystem.Collections.Generic.List __result, GameState gameState, PlayerState player, TileData tile, bool includeUnavailable)
@@ -269,6 +311,10 @@ private static void CommandUtils_GetUnitActions(ref Il2CppSystem.Collections.Gen
CommandUtils.AddCommand(gameState, __result, new BuildCommand(player.Id, improvementData.type, tile.coordinates), includeUnavailable);
}
}
+ if(improvementData.type == ImprovementData.Type.Canal && tile.isFloodable() && gameState.GameLogicData.CanBuild(gameState, tile, player, improvementData) && !unit.CanBuild()) // Canal building after moving
+ {
+ CommandUtils.AddCommand(gameState, __result, new BuildCommand(player.Id, improvementData.type, tile.coordinates), includeUnavailable);
+ }
}
}
@@ -290,41 +336,189 @@ private static void UnitDataExtensions_CanDisembark(ref bool __result, UnitState
}
}
+ private static void RemovePop(GameState gameState, TileData tile, byte playerId, int population)
+ {
+ tile.RemoveEffect(EnumCache.GetType("blooming"));
+ if(tile.owner == 0)
+ return;
+
+ TileData cityTile = gameState.Map.GetTile(tile.rulingCityCoordinates);
+ for (int i = 0; i < population; i++)
+ {
+ if(cityTile.HasImprovement(ImprovementData.Type.City))
+ gameState.ActionStack.Add(new DecreasePopulationAction(playerId, cityTile.coordinates, 200));
+ }
+ }
+
[HarmonyPostfix]
[HarmonyPatch(typeof(ClearTileEffectAction), nameof(ClearTileEffectAction.Execute))]
private static void ClearTileEffectAction_Execute(ClearTileEffectAction __instance, GameState gameState)
{
TileData tile = gameState.Map.GetTile(__instance.Target);
- if(__instance.Effect == TileData.EffectType.Algae && tile != null && tile.HasEffect(EnumCache.GetType("blooming")))
- {
+ if(tile == null) return;
+
+ bool hasBloomingAlgae = __instance.Effect == TileData.EffectType.Algae
+ && tile.HasEffect(EnumCache.GetType("blooming"));
+ bool hasOvercap = __instance.Effect == EnumCache.GetType("overcap");
+ if(hasBloomingAlgae)
tile.RemoveEffect(EnumCache.GetType("blooming"));
- if(tile.owner != 0)
+ if(hasBloomingAlgae || hasOvercap)
+ RemovePop(gameState, tile, __instance.PlayerId, 1);
+
+ // if(__instance.Effect == EnumCache.GetType("overcap")) // I tried to create more generic solution
+ // {
+ // Normally I would want to make so all overcap improvements get their pop reward from orig impr level up reward.
+ // if(tile.owner != 0) // && tile.improvement != null && gameState.GameLogicData.TryGetData(tile.improvement.type, out ImprovementData improvementData)
+ // {
+ // TileData city = gameState.Map.GetTile(tile.rulingCityCoordinates);
+ // if(city.HasImprovement(ImprovementData.Type.City))
+ // gameState.ActionStack.Add(new DecreasePopulationAction(__instance.PlayerId, city.coordinates, 200));
+ // int popReward = (int)improvementData.GetPopulationReward();
+ // foreach (var item in improvementData.growthRewards)
+ // {
+ // popReward += item.population;
+ // }
+ // for (int i = 0; i < popReward; i++)
+ // {
+ // gameState.ActionStack.Add(new DecreasePopulationAction(__instance.PlayerId, city.coordinates, 200));
+ // }
+ // }
+ // }
+ }
+
+ [HarmonyPostfix]
+ [HarmonyPatch(typeof(Tile), nameof(Tile.Render), typeof(MapRenderContext))]
+ private static void Tile_Render(Tile __instance, MapRenderContext mapRenderContext )
+ {
+ TileRender(__instance);
+ }
+
+ [HarmonyPostfix]
+ [HarmonyPatch(typeof(Tile), nameof(Tile.Render), typeof(MapRenderContext), typeof(SkinVisualsTransientData))]
+ private static void Tile_Render(Tile __instance, MapRenderContext ctx, SkinVisualsTransientData transientSkinningData)
+ {
+ TileRender(__instance);
+ }
+
+ private static void TileRender(Tile tile)
+ {
+ TileData tileData = tile.data;
+ if(tileData.HasEffect(EnumCache.GetType("blooming")))
+ {
+ if(tile.algaeRenderer != null)
{
- TileData city = gameState.Map.GetTile(tile.rulingCityCoordinates);
- if(city.HasImprovement(ImprovementData.Type.City))
+ tile.algaeRenderer.color = bloomColor;
+
+ if(tile.algaeRenderer.spriteRenderer != null)
{
- gameState.ActionStack.Add(new DecreasePopulationAction(__instance.PlayerId, city.coordinates, 200));
+ tile.algaeRenderer.spriteRenderer.color = bloomColor;
}
}
}
+
+ if(tileData.improvement != null && tileData.HasEffect(EnumCache.GetType("overcap")))
+ {
+ int newLevel = tileData.improvement.level + 2; // Visual level != Logic level. Aka, level 0 in Logic is 1 in Visual. So instead of increment i have to add 2.
+ Console.Write(newLevel);
+ Sprite? sprite = PolyMod.Registry.GetSprite(EnumCache.GetName(tileData.improvement.type), level: newLevel);
+ if (sprite != null)
+ {
+ tile.improvement.Sprite = sprite;
+ }
+ }
+ }
+
+ [HarmonyPrefix]
+ [HarmonyPatch(typeof(DestroyImprovementAction), nameof(DestroyImprovementAction.Execute))]
+ private static bool DestroyImprovementAction_Execute(DestroyImprovementAction __instance, GameState state)
+ {
+ TileData tile = state.Map.GetTile(__instance.Coordinates);
+ TileData.EffectType overcapEffect = EnumCache.GetType("overcap");
+ if(tile.HasEffect(overcapEffect))
+ {
+ __instance.AddSubAction(new ClearTileEffectAction(
+ __instance.PlayerId,
+ __instance.Coordinates,
+ overcapEffect,
+ false
+ ));
+ }
+ return true;
}
[HarmonyPostfix]
- [HarmonyPatch(typeof(Tile), nameof(Tile.Render))]
- private static void Tile_Render(Tile __instance)
+ [HarmonyPatch(typeof(StartMatchAction), nameof(StartMatchAction.ExecuteDefault))]
+ private static void StartMatchAction_ExecuteDefault(GameState gameState)
{
- if(__instance.data.HasEffect(EnumCache.GetType("blooming")))
+ if (gameState.PlayerStates != null && gameState.PlayerStates.Count > 0)
{
- if(__instance.algaeRenderer != null)
+ foreach (var playerState in gameState.PlayerStates)
{
- __instance.algaeRenderer.color = bloomColor;
-
- if(__instance.algaeRenderer.spriteRenderer != null)
+ if (playerState.tribe == TribeType.Aquarion && playerState.startTile != WorldCoordinates.NULL_COORDINATES)
{
- __instance.algaeRenderer.spriteRenderer.color = bloomColor;
+ TileData startingTile = gameState.Map.GetTile(playerState.startTile);
+ startingTile.AddEffect(TileData.EffectType.Flooded);
}
}
}
}
+
+ [HarmonyPostfix]
+ [HarmonyPatch(typeof(TerrainRenderer), nameof(TerrainRenderer.UpdateGraphics))]
+ private static void TerrainRenderer_UpdateGraphics(TerrainRenderer __instance, Tile tile)
+ {
+ TribeType tribe = GameManager.GameState.GameLogicData.GetTribeTypeFromStyle(tile.data.climate);
+ SkinType skinType = tile.data.Skin;
+
+ if (tribe == TribeType.Aquarion && tile.data.terrain == Polytopia.Data.TerrainData.Type.Mountain)
+ {
+ string style = skinType != SkinType.Default ? EnumCache.GetName(skinType) : EnumCache.GetName(tribe);
+ Sprite? sprite = PolyMod.Registry.GetSprite(EnumCache.GetName(Polytopia.Data.TerrainData.Type.Field), style);
+ if (sprite != null)
+ {
+ __instance.spriteRenderer.Sprite = sprite;
+ }
+ }
+ }
+
+ [HarmonyPostfix]
+ [HarmonyPatch(typeof(CaptureCityAction), nameof(CaptureCityAction.ExecuteDefault))]
+ private static void CaptureCityAction_ExecuteDefault(CaptureCityAction __instance, GameState gameState)
+ {
+ if (!gameState.TryGetPlayer(__instance.PlayerId, out PlayerState playerState))
+ return;
+ if (playerState.tribe == TribeType.Aquarion && playerState.startTile != WorldCoordinates.NULL_COORDINATES)
+ {
+ TileData tile = gameState.Map.GetTile(__instance.Coordinates);
+ tile.Flood(playerState);
+ }
+ }
+
+ [HarmonyPostfix]
+ [HarmonyPatch(typeof(AttackAction), nameof(AttackAction.Execute))]
+ private static void AttackAction_Execute(AttackAction __instance, GameState state) // It also heals on retal, so i need to handle ts.
+ {
+ WorldCoordinates healCoords = __instance.Origin;
+ // if(__instance.ShouldMoveToTarget)
+ // healCoords = __instance.Target;
+
+ TileData tile = state.Map.GetTile(healCoords);
+ if(tile.unit != null && tile.unit.HasAbility(EnumCache.GetType("absorb")))
+ {
+ state.ActionStack.Add(new HealAction(__instance.PlayerId, healCoords, (ushort)__instance.Damage));
+ }
+ }
+
+ [HarmonyPostfix]
+ [HarmonyPatch(typeof(HealOthersAction), nameof(HealOthersAction.Execute))]
+ private static void HealOthersAction_Execute(HealOthersAction __instance, GameState state)
+ {
+ TileData tileData = state.Map.GetTile(__instance.Coordinates);
+ if (tileData.unit == null || tileData.unit.owner != __instance.PlayerId || (!tileData.unit.IsDamaged(state) && !tileData.unit.HasEffect(UnitEffect.Poisoned)))
+ {
+ return;
+ }
+ state.ActionStack.Add(new HealAction(__instance.PlayerId, tileData.coordinates, 40));
+ }
}
}
diff --git a/src/Movement.cs b/src/Movement.cs
index 6dc104f..9d0995d 100644
--- a/src/Movement.cs
+++ b/src/Movement.cs
@@ -1,4 +1,5 @@
using HarmonyLib;
+using Il2CppSystem.Net;
using Polytopia.Data;
namespace PolyPlus
@@ -20,16 +21,25 @@ public class Movement
return;
}
}
+ // FIXME: Units on algae cannot move on water tiles to embark.
if (PlayerExtensions.HasAbility(settings.playerState, EnumCache.GetType("waterembark"), settings.gameState)
&& settings.allowedTerrain.Contains(tile.terrain) && tile.GetExplored(settings.playerState.Id))
{
- if(tile.IsWater && !tile.HasImprovement(ImprovementData.Type.Bridge) && (!origin.IsWater || origin.HasImprovement(ImprovementData.Type.Bridge))) // I NEED TO CHECK BRIDGE ABIL INSTEAD
+ bool tileHasBridge = tile.HasEffect(TileData.EffectType.Algae)
+ || tile.HasImprovement(ImprovementData.Type.Bridge);
+
+ bool originHasBridge = origin.HasEffect(TileData.EffectType.Algae)
+ || origin.HasImprovement(ImprovementData.Type.Bridge);
+ if(tile.IsWater && !tileHasBridge &&
+ (!origin.IsWater || originHasBridge)) // I NEED TO CHECK BRIDGE ABIL INSTEAD
{
__result = true;
return;
}
- if(origin.IsWater && !origin.HasImprovement(ImprovementData.Type.Bridge) && !tile.IsWater && settings.unit.HasAbility(UnitAbility.Type.Land)) // I NEED TO CHECK BRIDGE ABIL INSTEAD
+ if(origin.IsWater && !originHasBridge &&
+ !tile.IsWater && settings.unit.HasAbility(UnitAbility.Type.Land)) // I NEED TO CHECK BRIDGE ABIL INSTEAD
{
+ // wat?
__result = false;
return;
}
@@ -65,7 +75,7 @@ private static void MoveAction_ExecuteDefault(MoveAction __instance, GameState g
{
hasNoBridge = false;
}
- if (hasNoBridge && !unitData.IsAquatic() && !unitState.HasAbility(UnitAbility.Type.Fly, gameState) && tile2.IsWater
+ if (hasNoBridge && !unitData.IsAquatic() && !unitState.HasAbility(UnitAbility.Type.Fly) && tile2.IsWater
&& PlayerExtensions.HasAbility(playerState, EnumCache.GetType("waterembark"),gameState))
{
gameState.ActionStack.Add(new EmbarkAction(__instance.PlayerId, worldCoordinates));
@@ -90,20 +100,303 @@ private static void EmbarkAction_ExecuteDefault_Postfix(EmbarkAction __instance,
}
}
- [HarmonyPostfix]
+ private static int GetBaseTerrainCost(TileData tile, Data.UnitMovementType unitMovementType)
+ {
+ int cost = 10;
+ switch (unitMovementType)
+ {
+ case Data.UnitMovementType.Land:
+ if(tile.terrain == TerrainData.Type.Forest)
+ {
+ cost *= 2;
+ }
+ else if(tile.terrain == TerrainData.Type.Mountain)
+ {
+ cost *= 100;
+ }
+ break;
+ case Data.UnitMovementType.Amphibious:
+ break;
+ case Data.UnitMovementType.Water:
+ break;
+ case Data.UnitMovementType.Air:
+ break;
+ case Data.UnitMovementType.Sled:
+ break;
+ default:
+ break;
+ }
+
+ return cost;
+ }
+
+ [HarmonyPrefix]
[HarmonyPatch(typeof(TileData), nameof(TileData.GetMovementCost))]
- private static void TileData_GetMovementCost(ref int __result, TileData __instance, MapData map, TileData fromTile, PathFinderSettings settings)
+ private static bool TileData_GetMovementCost2(
+ ref int __result,
+ TileData __instance,
+ MapData map,
+ TileData fromTile,
+ PathFinderSettings settings)
{
+ const int BLOCKED = 1000;
+ const int SLOW_COST = 30;
+ const int HARD_COST = 20;
+ const int TILE_COST = 10;
+ const int HALF_COST = 5;
+
+ if (settings.unit == null)
+ {
+ if (settings.shouldFollowTransportPaths && (__instance.HasRoad || __instance.hasRoute))
+ {
+ __result = HALF_COST;
+ return false;
+ }
+ __result = TILE_COST;
+ return false;
+ }
+ ImprovementData data = null;
+ if (__instance.improvement != null)
+ {
+ settings.gameState.GameLogicData.TryGetData(__instance.improvement.type, out data);
+ }
+ if (ActionUtils.WillUnitEmbark(settings.unit, __instance, settings.gameState) != ActionUtils.EmbarkStatus.None)
+ {
+ __result = BLOCKED;
+ return false;
+ }
+ if (!settings.shouldAllowOccupiedTiles && !settings.unitData.HasAbility(UnitAbility.Type.Sneak) && !settings.unitData.HasAbility(UnitAbility.Type.Hide) && !settings.unit.HasEffect(UnitEffect.Invisible))
+ {
+ foreach (TileData tileNeighbor in map.GetTileNeighbors(__instance.coordinates))
+ {
+ if (tileNeighbor.unit != null && tileNeighbor.unit.owner != settings.playerState.Id
+ && !settings.playerState.HasPeaceWith(tileNeighbor.unit.owner) &&
+ !tileNeighbor.unit.HasEffect(UnitEffect.Invisible) && tileNeighbor.unit.leader == 0)
+ {
+ __result = BLOCKED;
+ return false;
+ }
+ }
+ }
+ if (settings.unitData.HasAbility(UnitAbility.Type.Fly))
+ {
+ __result = TILE_COST;
+ return false;
+ }
+ if (settings.unitData.HasAbility(UnitAbility.Type.Skate))
+ {
+ if (__instance.terrain == TerrainData.Type.Ice)
+ {
+ __result = TILE_COST;
+ return false;
+ }
+ __result = BLOCKED;
+ return false;
+ }
+ if (__instance.terrain == TerrainData.Type.Ice &&
+ !settings.unitData.HasAbility(UnitAbility.Type.Skate) &&
+ settings.playerState.HasAbility(PlayerAbility.Type.Glide, settings.gameState))
+ {
+ __result = 9;
+ return false;
+ }
+ if (!__instance.IsWater && !__instance.HasEffect(TileData.EffectType.Flooded) &&
+ settings.unitData.HasAbility(UnitAbility.Type.Swim))
+ {
+ __result = BLOCKED;
+ return false;
+ }
+ if (__instance.terrain != TerrainData.Type.Mountain && settings.unitData.HasAbility(UnitAbility.Type.Creep))
+ {
+ __result = TILE_COST;
+ return false;
+ }
+ if (__instance.HasRoadTo(fromTile, settings.gameState, settings.unit.owner) &&
+ __instance.terrain != TerrainData.Type.Ice && !settings.unitData.HasAbility(UnitAbility.Type.Skate) &&
+ !settings.unitData.HasAbility(UnitAbility.Type.Creep) && !settings.unitData.HasAbility(UnitAbility.Type.Swim))
+ {
+ __result = HALF_COST;
+ return false;
+ }
+ if (__instance.improvement != null && data != null && data.HasAbility(ImprovementAbility.Type.Slow))
+ {
+ __result = BLOCKED;
+ return false;
+ }
+ if (__instance.terrain == TerrainData.Type.Forest || __instance.terrain == TerrainData.Type.Mountain)
+ {
+ __result = BLOCKED;
+ return false;
+ }
+ if (__instance.HasEffect(TileData.EffectType.Flooded) && settings.unit.UnitData.IsWaterBound())
+ {
+ __result = BLOCKED;
+ return false;
+ }
+ if (__instance.HasEffect(TileData.EffectType.Algae) && settings.unit.UnitData.IsLandBound())
+ {
+ __result = BLOCKED;
+ return false;
+ }
+
+ __result = TILE_COST;
+ return false;
+ }
+
+ [HarmonyPrefix]
+ [HarmonyPatch(typeof(TileData), nameof(TileData.GetMovementCost))]
+ private static bool TileData_GetMovementCost(
+ ref int __result,
+ TileData __instance,
+ MapData map,
+ TileData fromTile,
+ PathFinderSettings settings)
+ {
+ const int BLOCKED = 1000;
+ const int TILE_COST = 10;
+ __result = TILE_COST;
+
UnitState unit = settings.unit;
- if (unit != null && __instance.terrain == Polytopia.Data.TerrainData.Type.Ice && settings.unitData.HasAbility(EnumCache.GetType("slide")))
- __result = 5;
+ UnitData unitData = settings.unitData;
+ byte playerId = settings.playerState.Id;
+
+ // No unit
+ if (unit == null)
+ {
+ if(settings.shouldFollowTransportPaths && (__instance.HasRoad || __instance.hasRoute))
+ __result /= 2;
+ // wait i just realized that some pathfinder shi never triggers cuz
+ // sherlock this shit was never in actual game like dawg WHAT????
+ // reeferring to shouldFollowTransportPaths
+ return false;
+ }
+
+ // Water / embark
+ if (settings.isRequiredToUsePortToGoIntoWater &&
+ __instance.IsWater &&
+ __instance.HasEmbarkImprovement(settings.gameState))
+ {
+ __result = BLOCKED;
+ return false;
+ }
+
+ if (!__instance.IsWater &&
+ unit.HasAbility(UnitAbility.Type.Carry))
+ {
+ __result = BLOCKED;
+ return false;
+ }
+
+ // ZOC
+ if (!settings.shouldAllowOccupiedTiles &&
+ !unitData.HasAbility(UnitAbility.Type.Sneak) &&
+ !unitData.HasAbility(UnitAbility.Type.Hide))
+ {
+ foreach (TileData neighbor in map.GetTileNeighbors(__instance.coordinates))
+ {
+ UnitState neighborUnit = neighbor.unit;
+ if (neighborUnit == null)
+ continue;
+
+ if (neighborUnit.owner == playerId)
+ continue;
+
+ if (settings.playerState.HasPeaceWith(neighborUnit.owner))
+ continue;
+
+ if (neighborUnit.HasEffect(UnitEffect.Invisible))
+ continue;
+
+ __result = BLOCKED;
+ return false;
+ }
+ }
+
+ // Fly / Creep
+ if (unitData.HasAbility(UnitAbility.Type.Fly) ||
+ unitData.HasAbility(UnitAbility.Type.Creep) ||
+ unit.HasEffect(UnitEffect.Boosted) ||
+ unit.HasEffect(UnitEffect.Swift))
+ {
+ __result = TILE_COST;
+ return false;
+ }
+
+ // From water to land
+ if (fromTile.IsWater &&
+ !fromTile.HasImprovement(ImprovementData.Type.Bridge) &&
+ !__instance.IsWater &&
+ !__instance.HasImprovement(ImprovementData.Type.City))
+ {
+ __result = BLOCKED;
+ return false;
+ }
+
+ // Roads REEEEEEE FUCKING WRITE......é
+ if (__instance.HasRoadTo(fromTile, settings.gameState, unit.owner) &&
+ __instance.terrain != TerrainData.Type.Ice &&
+ !unitData.HasAbility(UnitAbility.Type.Skate) &&
+ !unitData.HasAbility(UnitAbility.Type.Swim))
+ {
+ __result /= 2;
+ return false;
+ }
+
+ bool hasRoughTerrain = ( __instance.improvement != null && settings.gameState.GameLogicData.TryGetData(__instance.improvement.type, out ImprovementData improvementData)
+ && improvementData.HasAbility(ImprovementAbility.Type.Slow)) ||__instance.terrain == TerrainData.Type.Mountain;
+
+ // Condition for tiles to cost 30
+ if (hasRoughTerrain)
+ {
+ __result *= 3;
+ return false;
+ }
+
+ if(__instance.terrain == TerrainData.Type.Forest)
+ {
+ __result *= 2;
+ return false;
+ }
+ // Ice / skate / slide / polarism
+ bool canSlide =
+ settings.unitData.HasAbility(EnumCache.GetType("slide")) ||
+ settings.playerState.HasAbility(PlayerAbility.Type.Glide, settings.gameState);
+
+ if (canSlide && __instance.terrain == TerrainData.Type.Ice)
+ {
+ __result /= 2;
+ return false;
+ }
+ else if (unitData.HasAbility(UnitAbility.Type.Skate))
+ {
+ __result *= 2;
+ return false;
+ }
+
+ // Swim units on land (Kill me why does swim still exist why does swim still exist why does
+ // swoim stikl exist i actually manually type it and dont cntrlc cntrlv why does swim stikll exist)
+ if (!__instance.IsWater &&
+ unitData.HasAbility(UnitAbility.Type.Water))
+ {
+ __result *= 2;
+ return false;
+ }
+
+ if (!__instance.IsWater && !__instance.IsWetland() &&
+ unitData.HasAbility(UnitAbility.Type.Amphibious))
+ {
+ __result *= 2;
+ return false;
+ }
+
+ return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(UnitDataExtensions), nameof(UnitDataExtensions.CanExplode))]
private static bool UnitDataExtensions_CanExplode(ref bool __result, UnitState unit, GameState gameState)
{
- __result = unit.CanAttack() && unit.owner == gameState.CurrentPlayer && unit.HasAbility(UnitAbility.Type.Explode, gameState);
+ __result = unit.CanAttack() && unit.owner == gameState.CurrentPlayer && unit.HasAbility(UnitAbility.Type.Explode);
return false;
}