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; }