From bcb4d3231d68018a79630174812981716ff12d8a Mon Sep 17 00:00:00 2001 From: Francisco Altoe Date: Fri, 29 Jan 2021 14:18:21 -0300 Subject: [PATCH] Separate patches into dedicated source files --- .clang-format | 25 ++ CMakeLists.txt | 15 +- create-data-mod.cpp | 16 +- patches.cpp | 765 -------------------------------- patches.h | 23 - patches/community_games.cpp | 160 +++++++ patches/community_games.h | 9 + patches/duplicate_techs.cpp | 147 ++++++ patches/duplicate_techs.h | 9 + patches/exploding_villagers.cpp | 34 ++ patches/exploding_villagers.h | 9 + patches/flying_dutchman.cpp | 15 + patches/flying_dutchman.h | 9 + patches/kidnap.cpp | 42 ++ patches/kidnap.h | 9 + patches/no_wall.cpp | 46 ++ patches/no_wall.h | 9 + patches/random_costs.cpp | 301 +++++++++++++ patches/random_costs.h | 11 + 19 files changed, 861 insertions(+), 793 deletions(-) create mode 100644 .clang-format delete mode 100644 patches.cpp delete mode 100644 patches.h create mode 100644 patches/community_games.cpp create mode 100644 patches/community_games.h create mode 100644 patches/duplicate_techs.cpp create mode 100644 patches/duplicate_techs.h create mode 100644 patches/exploding_villagers.cpp create mode 100644 patches/exploding_villagers.h create mode 100644 patches/flying_dutchman.cpp create mode 100644 patches/flying_dutchman.h create mode 100644 patches/kidnap.cpp create mode 100644 patches/kidnap.h create mode 100644 patches/no_wall.cpp create mode 100644 patches/no_wall.h create mode 100644 patches/random_costs.cpp create mode 100644 patches/random_costs.h diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..f95fc42 --- /dev/null +++ b/.clang-format @@ -0,0 +1,25 @@ +--- +Language: Cpp +IndentWidth: 4 +UseTab: Never +DerivePointerAlignment: false +PointerAlignment: Right +IncludeBlocks: Merge +IncludeCategories: + - Regex: '<[^>]+>' + Priority: 1 + - Regex: '"[^"]+"' + Priority: 2 +SpacesInCStyleCastParentheses: false +SpacesInAngles: false +SpacesInParentheses: false +SpaceInEmptyParentheses: false +Standard: c++17 +ColumnLimit: 120 +IndentCaseBlocks: true +InsertTrailingCommas: Wrapped +BinPackArguments: false +SpacesBeforeTrailingComments: 2 +AlignTrailingComments: true +MaxEmptyLinesToKeep: 2 +--- diff --git a/CMakeLists.txt b/CMakeLists.txt index f17787c..4babc10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,19 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++") add_subdirectory(genieutils EXCLUDE_FROM_ALL) include_directories( "genieutils/include" + "." ) -add_executable(create-data-mod create-data-mod.cpp patches.cpp ids.h) +add_executable( + create-data-mod + create-data-mod.cpp + patches/community_games.cpp + patches/exploding_villagers.cpp + patches/flying_dutchman.cpp + patches/kidnap.cpp + patches/no_wall.cpp + patches/random_costs.cpp + patches/duplicate_techs.cpp + ids.h +) +set_property(TARGET create-data-mod PROPERTY CXX_STANDARD 17) target_link_libraries(create-data-mod genieutils) diff --git a/create-data-mod.cpp b/create-data-mod.cpp index e291e42..f2f34ba 100644 --- a/create-data-mod.cpp +++ b/create-data-mod.cpp @@ -1,6 +1,13 @@ -#include "genie/dat/DatFile.h" -#include "patches.h" #include +#include "genie/dat/DatFile.h" +#include "patches/community_games.h" +#include "patches/duplicate_techs.h" +#include "patches/exploding_villagers.h" +#include "patches/flying_dutchman.h" +#include "patches/kidnap.h" +#include "patches/no_wall.h" +#include "patches/random_costs.h" + using namespace std; const char *const COMMUNITY_GAMES = "community-games"; @@ -63,6 +70,7 @@ int main(int argc, char **argv) { return 0; } + void applyModifications(genie::DatFile *df, const string &modIdentifier) { if (COMMUNITY_GAMES == modIdentifier) { configureCommunityGamesMod(df); @@ -91,6 +99,7 @@ void applyModifications(genie::DatFile *df, const string &modIdentifier) { } } + void printModIdentifiers(const vector &modIdentifiers) { cout << "Applying the following modifications in order:" << endl; for (const string &modIdentifier : modIdentifiers) { @@ -98,6 +107,7 @@ void printModIdentifiers(const vector &modIdentifiers) { } } + vector getModIdentifiers(char *const *argv) { string s = argv[1]; string delimiter = "+"; @@ -113,5 +123,3 @@ vector getModIdentifiers(char *const *argv) { modIdentifiers.push_back(s.substr(start, end)); return modIdentifiers; } - - diff --git a/patches.cpp b/patches.cpp deleted file mode 100644 index 26f627e..0000000 --- a/patches.cpp +++ /dev/null @@ -1,765 +0,0 @@ -#include "genie/dat/DatFile.h" -#include "genie/dat/TechageEffect.h" -#include "patches.h" -#include "ids.h" -#include -#include -#include -#include - -using namespace std; - - -typedef genie::ResourceUsage ResourceCost; -typedef genie::ResourceUsage ResearchResourceCost; - -void copyResourceCostAt(int unitId, int index, vector &target, const genie::Civ &civ); - -bool bothRequirePopulationHeadroom(int unitId, vector &resourceCosts, const genie::Civ &civ); - -bool isNaturalResourceCost(const ResourceCost &cost); - -bool isNaturalResearchResourceCost(const ResearchResourceCost &cost); - -bool hasNaturalResourceCost(const genie::Unit &unit); - -bool hasNaturalResearchResourceCost(vector costs); - -string costToString(const vector &costs); - -string costToString(const vector &costs); - -int getSumOfNaturalResourceCosts(const vector& resourceCosts); - -ResearchResourceCost toResearchResourceCost(const ResourceCost &resourceCost); - -ResourceCost toResourceCost(const ResearchResourceCost &researchResourceCost); - -vector toResearchResourceCosts(const vector &resourceCosts); - -vector toResourceCosts(const vector &researchResourceCosts); - - -void configureCommunityGamesMod(genie::DatFile *df) { - addPopulationCostToBombardTower(df); - addGreatHallTech(df); - addElitePetard(df); - modifyCaravanCost(df, 800, 200); - makeTreesContain200Wood(df); -} - -void addPopulationCostToBombardTower(genie::DatFile *df) { - cout << "Adding population cost to bombard towers of all civs" << endl; - for (genie::Civ &civ : df->Civs) { - genie::Unit &bombard_tower = civ.Units.at(BOMBARD_TOWER); - genie::ResourceUsage &resourceCosts = bombard_tower.Creatable.ResourceCosts.at(2); - resourceCosts.Type = TYPE_POPULATION_HEADROOM; - resourceCosts.Amount = 1; - resourceCosts.Flag = 0; - - bombard_tower.ResourceStorages.at(0).Type = TYPE_POPULATION_HEADROOM; - bombard_tower.ResourceStorages.at(0).Amount = -1; - bombard_tower.ResourceStorages.at(0).Flag = 2; - - bombard_tower.ResourceStorages.at(1).Type = TYPE_CURRENT_POPULATION; - bombard_tower.ResourceStorages.at(1).Amount = 1; - bombard_tower.ResourceStorages.at(1).Flag = 2; - - bombard_tower.ResourceStorages.at(2).Type = TYPE_TOTAL_UNITS_OWNED; - bombard_tower.ResourceStorages.at(2).Amount = 1; - bombard_tower.ResourceStorages.at(2).Flag = 1; - } -} - -void addGreatHallTech(genie::DatFile *df) { - cout << "Adding great hall tech" << endl; - auto effectCommand = new genie::EffectCommand(); - effectCommand->Type = 1; // Resource Modifier - effectCommand->A = 32; // Resource: Bonus Population Cap - effectCommand->B = 1; // Mode: +/- - effectCommand->D = 10; // Amount +/- - - auto effect = new genie::Effect(); - effect->Name = "Great Hall"; - effect->EffectCommands.push_back(*effectCommand); - - df->Effects.push_back(*effect); - size_t greatHallEffectId = df->Effects.size() - 1; - - auto tech = new genie::Tech(); - tech->Name = "The Great Hall"; - tech->RequiredTechs.push_back(BOMBARD_TOWER_TECH); - tech->ResearchTime = 5; - tech->IconID = 103; - tech->ButtonID = 1; - tech->EffectID = greatHallEffectId; - tech->ResearchLocation = BOMBARD_TOWER; - - tech->ResourceCosts.at(0).Type = TYPE_WOOD; - tech->ResourceCosts.at(0).Amount = 400; - tech->ResourceCosts.at(0).Flag = 1; - - tech->ResourceCosts.at(1).Type = TYPE_GOLD; - tech->ResourceCosts.at(1).Amount = 600; - tech->ResourceCosts.at(1).Flag = 1; - - df->Techs.push_back(*tech); -} - -void addElitePetard(genie::DatFile *df) { - int elitePetardId = -1; - for (genie::Civ &civ : df->Civs) { - genie::Unit elitePetard = civ.Units.at(PETARD); - elitePetard.Enabled = 0; - elitePetard.Name = "Elite Petard"; - elitePetard.HitPoints = 60; - elitePetard.Speed = 1.05; - elitePetard.Type50.DisplayedAttack = 45; - elitePetard.Type50.BlastWidth = 1.5; - elitePetard.Type50.BlastAttackLevel = 1; - elitePetard.Type50.Attacks.at(0).Amount = 150; - elitePetard.Type50.Attacks.at(1).Amount = 650; - elitePetard.Type50.Attacks.at(2).Amount = 45; - elitePetard.Type50.Attacks.at(3).Amount = 70; - elitePetard.Type50.Attacks.at(4).Amount = 1000; - elitePetard.Type50.Armours.at(1).Amount = 3; - elitePetard.Creatable.DisplayedPierceArmour = 3; - elitePetardId = civ.Units.size(); - cout << "Adding elite petard for civ " << civ.Name << " with ID " << elitePetardId << endl; - civ.Units.push_back(elitePetard); - civ.UnitPointers.push_back(1); - } - - auto effectCommand = new genie::EffectCommand(); - effectCommand->Type = 3; // Upgrade Unit - effectCommand->A = PETARD; - effectCommand->B = elitePetardId; - - auto effect = new genie::Effect(); - effect->Name = "Elite Petard"; - effect->EffectCommands.push_back(*effectCommand); - int elitePetardEffectId = df->Effects.size(); - df->Effects.push_back(*effect); - - auto tech = new genie::Tech(); - tech->Name = "Elite Petard"; - tech->RequiredTechs.push_back(CHEMISTRY); - tech->RequiredTechCount = 1; - tech->ResearchTime = 40; - tech->IconID = 105; - tech->ButtonID = 9; - tech->EffectID = elitePetardEffectId; - tech->ResearchLocation = CASTLE; - - tech->ResourceCosts.at(0).Type = TYPE_FOOD; - tech->ResourceCosts.at(0).Amount = 450; - tech->ResourceCosts.at(0).Flag = 1; - - tech->ResourceCosts.at(1).Type = TYPE_GOLD; - tech->ResourceCosts.at(1).Amount = 450; - tech->ResourceCosts.at(1).Flag = 1; - - cout << "Adding Elite Petard Tech with id " << df->Techs.size() << endl; - df->Techs.push_back(*tech); -} - -void modifyCaravanCost(genie::DatFile *df, int amountFood, int amountGold) { - cout << "Setting the cost of Caravan (" << TECH_CARAVAN << ") to " << amountFood << " Food, " << amountGold - << " Gold" << endl; - genie::Tech &caravan = df->Techs.at(TECH_CARAVAN); - caravan.ResourceCosts.at(0).Type = TYPE_FOOD; - caravan.ResourceCosts.at(0).Amount = amountFood; - caravan.ResourceCosts.at(0).Flag = 1; - - caravan.ResourceCosts.at(1).Type = TYPE_GOLD; - caravan.ResourceCosts.at(1).Amount = amountGold; - caravan.ResourceCosts.at(1).Flag = 1; -} - -void makeTreesContain200Wood(genie::DatFile *df) { - for (genie::Civ &civ : df->Civs) { - for (genie::Unit &unit: civ.Units) { - for (auto storage : unit.ResourceStorages) { - if (storage.Type == TYPE_WOOD && storage.Amount > 50) { - cout << "Setting amount of wood in " << unit.Name << " (" << unit.ID << ") to 200" << endl; - storage.Amount = 200; - } - } - } - } -} - -void configureExplodingVillagers(genie::DatFile *df) { - set villagers = { - ID_FISHING_SHIP, - ID_TRADE_COG, - ID_TRADE_CART_EMPTY, - ID_TRADE_CART_FULL, - ID_VILLAGER_BASE_M, - ID_VILLAGER_BASE_F, - ID_VILLAGER_FARMER_M, - ID_VILLAGER_FARMER_F, - ID_VILLAGER_SHEPHERD_M, - ID_VILLAGER_SHEPHERD_F, - ID_VILLAGER_FORAGER_M, - ID_VILLAGER_FORAGER_F, - ID_VILLAGER_HUNTER_M, - ID_VILLAGER_HUNTER_F, - ID_VILLAGER_FISHER_M, - ID_VILLAGER_FISHER_F, - ID_VILLAGER_WOOD_M, - ID_VILLAGER_WOOD_F, - ID_VILLAGER_GOLD_M, - ID_VILLAGER_GOLD_F, - ID_VILLAGER_STONE_M, - ID_VILLAGER_STONE_F, - ID_VILLAGER_BUILDER_M, - ID_VILLAGER_BUILDER_F, - ID_VILLAGER_REPAIRER_M, - ID_VILLAGER_REPAIRER_F, - }; - - for (genie::Civ &civ : df->Civs) { - for (int villager_id : villagers) { - civ.Units.at(villager_id).DeadUnitID = ID_SABOTEUR; - cout << "Patched Villager unit " << villager_id << " for civ " << civ.Name << "\n"; - } - genie::Unit &saboteur = civ.Units.at(ID_SABOTEUR); - saboteur.HitPoints = 0; - saboteur.Type50.Attacks.at(0).Amount = 50; - saboteur.Type50.Attacks.at(1).Amount = 90; - saboteur.Type50.Attacks.at(2).Amount = 0; - saboteur.Type50.MaxRange = 2; - saboteur.Type50.BlastAttackLevel = 1; // cut trees - saboteur.TrainSound = -1; - saboteur.WwiseTrainSoundID = 0; // prevent melee unit train sound from playing - cout << "Patched Saboteur unit for civ " << civ.Name << "\n"; - } -} - -void duplicateTechs(genie::DatFile *df, int totalCount) { - - const list techsToDuplicate = { - YEOMEN, - EL_DORADO, - FUROR_CELTICA, - DRILL, - MAHOUTS, - TOWN_WATCH, - ZEALOTRY, - ARTILLERY, - CRENELLATIONS, - CROP_ROTATION, - HEAVY_PLOW, - HORSE_COLLAR, - GUILDS, - BANKING, - ATHEISM, - LOOM, - GARLAND_WARS, - HUSBANDRY, - FAITH, - CHEMISTRY, - CARAVAN, - BERSERKERGANG, - MASONRY, - ARCHITECTURE, - ROCKETRY, - TREADMILL_CRANE, - GOLD_MINING, - KATAPARUTO, - LOGISTICA, - GILLNETS, - FORGING, - IRON_CASTING, - SCALE_MAIL_ARMOR, - BLAST_FURNACE, - CHAIN_MAIL_ARMOR, - PLATE_MAIL_ARMOR, - PLATE_BARDING_ARMOR, - SCALE_BARDING_ARMOR, - CHAIN_BARDING_ARMOR, - BEARDED_AXE, - GOLD_SHAFT_MINING, - FLETCHING, - BODKIN_ARROW, - BRACER, - DOUBLE_BIT_AXE, - BOW_SAW, - PADDED_ARCHER_ARMOR, - LEATHER_ARCHER_ARMOR, - WHEELBARROW, - SQUIRES, - RING_ARCHER_ARMOR, - TWO_MAN_SAW, - BLOCK_PRINTING, - SANCTITY, - ILLUMINATION, - HAND_CART, - FERVOR, - STONE_MINING, - STONE_SHAFT_MINING, - TOWN_PATROL, - CONSCRIPTION, - SAPPERS, - SHIPWRIGHT, - CAREENING, - DRY_DOCK, - SIEGE_ENGINEERS, - HOARDINGS, - HEATED_SHOT, - BLOODLINES, - PARTHIAN_TACTICS, - THUMB_RING, - SUPREMACY, - HERBAL_MEDICINE, - SHINKICHON, - PERFUSION, - ATLATL, - WARWOLF, - GREAT_WALL, - CHIEFTAINS, - GREEK_FIRE, - STRONGHOLD, - YASAMA, - OBSIDIAN_ARROWS, - PANOKSEON, - KAMANDARAN, - IRONCLAD, - SIPAHI, - INQUISITION, - CHIVALRY, - PAVISE, - SILK_ROAD, - SULTANS, - SHATAGNI, - ORTHODOXY, - DRUZHINA, - RECURVE_BOW, - FABRIC_SHIELDS, - CARRACK, - ARQUEBUS, - ROYAL_HEIRS, - TORSION_ENGINES, - TIGUI, - FARIMBA, - KASBAH, - MAGHRABI_CAMELS, - ARSON, - ARROWSLITS, - TUSK_SWORDS, - DOUBLE_CROSSBOW, - FORCED_LEVY, - HOWDAH, - MANIPUR_CAVALRY, - CHATRAS, - PAPER_MONEY, - STIRRUPS, - BAGAINS, - SILK_ARMOR, - TIMURID_SIEGECRAFT, - STEPPE_HUSBANDRY, - CUMAN_MERCENARIES, - HILL_FORTS, - TOWER_SHIELDS, - SUPPLIES, - }; - - for (int techId: techsToDuplicate) { - genie::Tech tech = df->Techs.at(techId); - duplicateTech(df, tech, totalCount); - } - -} - -void duplicateTech(genie::DatFile *df, const genie::Tech &tech, int totalCount) { - for (int i = 0; i < (totalCount - 1); ++i) { - df->Techs.push_back(tech); - } - cout << "Added Tech '" << tech.Name << "' for a total of " << totalCount << " instances" << endl; -} - -void makeTransportShipsFly(genie::DatFile *df) { - for (genie::Civ &civ : df->Civs) { - genie::Unit &transport_ship = civ.Units.at(ID_TRANSPORT_SHIP); - transport_ship.FlyMode = 1; // true - transport_ship.TerrainRestriction = 0; // All - transport_ship.CollisionSize = {0, 0, 0}; // walk through everything, like flying - cout << "Patched Transport Ship unit for civ " << civ.Name << "\n"; - } -} - -void configureKidnap(genie::DatFile *df) { - const list scoutIds = { - ID_SCOUT, - ID_EAGLE_SCOUT, - }; - for (genie::Civ &civ : df->Civs) { - for (int scoutId : scoutIds) { - genie::Unit &scout = civ.Units.at(scoutId); - cout << "Setting Scout (" << scoutId << ") properties for civ " << civ.Name << endl; - scout.Type50.Attacks.clear(); - scout.Type50.DisplayedAttack = 0; - scout.GarrisonCapacity = 1; - scout.Bird.TaskList.erase(scout.Bird.TaskList.begin()); - - cout << "Adding Kidnap Task to scout (" << scoutId << ") for civ " << civ.Name << endl; - auto kidnapTask = new genie::Task(); - kidnapTask->ActionType = ACTION_KIDNAP_UNIT; - kidnapTask->ClassID = CLASS_CIVILIAN; - kidnapTask->WorkRange = 0.25; - kidnapTask->ProceedingGraphicID = 1966; // SCOUT_AN - kidnapTask->TargetDiplomacy = 2; - kidnapTask->GatherType = 2; - scout.Bird.TaskList.push_back(*kidnapTask); - - cout << "Adding Loot Task to scout (" << scoutId << ") for civ " << civ.Name << endl; - auto lootTask = new genie::Task(); - lootTask->ActionType = ACTION_LOOT; - lootTask->ClassID = CLASS_BUILDING; - lootTask->WorkRange = 0.25; - lootTask->ProceedingGraphicID = 1966; // SCOUT_AN - lootTask->TargetDiplomacy = 2; - lootTask->GatherType = 1; - scout.Bird.TaskList.push_back(*lootTask); - } - } -} - -void disableWalls(genie::DatFile *df) { - const list unitsToDisable = { - PALISADE_WALL, - }; - - const list techsToDisable = { - TECH_PALISADE_GATE, - TECH_STONE_WALLS, - }; - - const list techsToHide = { - TECH_FORTIFIED_WALL, - }; - - for (int unitId: unitsToDisable) { - cout << "Disabling unit with id " << unitId << " for all civs" << endl; - for (genie::Civ &civ : df->Civs) { - civ.Units.at(unitId).Enabled = 0; - } - } - - for (int techId: techsToDisable) { - genie::Tech *tech = &df->Techs.at(techId); - cout << "Disabling the effect of tech with id " << techId << " ('" << tech->Name << "')" << endl; - disableTechEffect(tech); - } - - for (int techId: techsToHide) { - genie::Tech *tech = &df->Techs.at(techId); - cout << "Disabling the research location of tech with id " << techId << " ('" << tech->Name << "')" << endl; - disableTechResearchLocation(tech); - } -} - -void disableTechEffect(genie::Tech *tech) { - tech->EffectID = -1; -} - -void disableTechResearchLocation(genie::Tech *tech) { - tech->ResearchLocation = -1; -} - -void preventRamsAndSiegeTowersFromBoardingTransportShips(genie::DatFile *df) { - for (genie::Civ &civ : df->Civs) { - for (genie::Unit &unit : civ.Units) { - if (unit.ID == ID_RAM || unit.ID == ID_CAPPED_RAM || unit.ID == ID_SIEGE_RAM || unit.ID == ID_SIEGE_TOWER) { - list toDelete; - for (int i = 0; i < unit.Bird.TaskList.size(); i++) { - genie::Task task = unit.Bird.TaskList.at(i); - if (task.ActionType == ACTION_TYPE_GARRISON && task.ClassID == CLASS_TRANSPORT_BOAT) { - toDelete.push_front(i); - } - } - - for (int i:toDelete) { - unit.Bird.TaskList.erase(unit.Bird.TaskList.begin() + i); - } - cout << "Patched unit " << unit.Name << " (" << unit.ID << ") unit for civ " << civ.Name << "\n"; - } - } - } -} - -ResearchResourceCost toResearchResourceCost(const ResourceCost &resourceCost) { - ResearchResourceCost researchResourceCost; - researchResourceCost.Type = resourceCost.Type; - researchResourceCost.Amount = resourceCost.Amount; - researchResourceCost.Flag = (bool) resourceCost.Flag; - return researchResourceCost; -} - -ResourceCost toResourceCost(const ResearchResourceCost &researchResourceCost) { - ResourceCost resourceCost; - resourceCost.Type = researchResourceCost.Type; - resourceCost.Amount = researchResourceCost.Amount; - resourceCost.Flag = (bool) researchResourceCost.Flag; - return resourceCost; -} - - -vector toResearchResourceCosts(const vector &resourceCosts) { - vector researchResourceCosts; - researchResourceCosts.reserve(resourceCosts.size()); - for (const ResourceCost &resourceCost : resourceCosts) { - researchResourceCosts.push_back(toResearchResourceCost(resourceCost)); - } - return researchResourceCosts; -} - -vector toResourceCosts(const vector &researchResourceCosts) { - vector resourceCosts; - resourceCosts.reserve(researchResourceCosts.size()); - for (const ResearchResourceCost &researchResourceCost : researchResourceCosts) { - resourceCosts.push_back(toResourceCost(researchResourceCost)); - } - return resourceCosts; -} - - -void jumbleCosts(genie::DatFile *df) { - vector unitIds; - for (genie::Unit unit : df->Civs.at(0).Units) { - if (hasNaturalResourceCost(unit)) { - unitIds.push_back(unit.ID); - } - } - - vector techIds; - size_t index = 0; - for (const genie::Tech &tech : df->Techs) { - vector resourceCopy = tech.ResourceCosts; - if (hasNaturalResearchResourceCost(resourceCopy)) { - techIds.push_back(index); - } - index++; - } - - vector> allTheCosts; - for (int unitId: unitIds) { - vector resourceCopy = df->Civs.at(0).Units.at(unitId).Creatable.ResourceCosts; - allTheCosts.push_back(resourceCopy); - } - - for (int techId: techIds) { - vector resourceCopy = toResourceCosts(df->Techs.at(techId).ResourceCosts); - allTheCosts.push_back(resourceCopy); - } - - for (int i = 0; i < 10; i++) { - unsigned int seed = std::random_device()(); - cout << "Seed for shuffling unit and tech costs is: " << to_string(seed) << endl; - shuffle(allTheCosts.begin(), allTheCosts.end(), std::mt19937(seed)); - - size_t costIndex = 0; - for (int techId: techIds) { - vector researchResourceCosts = toResearchResourceCosts(allTheCosts.at(costIndex)); - cout << "Setting cost of tech with id " << techId << " to " << costToString(researchResourceCosts) << endl; - df->Techs.at(techId).ResourceCosts = researchResourceCosts; - costIndex++; - } - for (int unitId: unitIds) { - vector &resourceCosts = allTheCosts.at(costIndex); - cout << "Setting cost of unit with id " << unitId << " to " << costToString(resourceCosts) << endl; - if (!bothRequirePopulationHeadroom(unitId, resourceCosts, df->Civs.at(0))) { - copyResourceCostAt(unitId, 2, resourceCosts, df->Civs.at(0)); - } - for (genie::Civ &civ : df->Civs) { - civ.Units.at(unitId).Creatable.ResourceCosts = resourceCosts; - } - costIndex++; - } - - int maleVillagerCost = getSumOfNaturalResourceCosts( - df->Civs.at(0).Units.at(ID_VILLAGER_BASE_M).Creatable.ResourceCosts); - int femaleVillagerCost = getSumOfNaturalResourceCosts( - df->Civs.at(0).Units.at(ID_VILLAGER_BASE_F).Creatable.ResourceCosts); - if (maleVillagerCost <= 200 && femaleVillagerCost <= 200) { - return; - } - cout << "Villagers are too expensive, reshuffling…" << endl; - } - cout << "Giving up, villagers stay expensive, sorry." << endl; -} - -void jumbleUnitCosts(genie::DatFile *df) { - vector unitIds; - - for (genie::Unit unit : df->Civs.at(0).Units) { - if (hasNaturalResourceCost(unit)) { - unitIds.push_back(unit.ID); - } - } - - vector> allTheCosts; - for (int unitId: unitIds) { - vector resourceCopy = df->Civs.at(0).Units.at(unitId).Creatable.ResourceCosts; - allTheCosts.push_back(resourceCopy); - } - - for (int i = 0; i < 10; i++) { - unsigned int seed = std::random_device()(); - cout << "Seed for shuffling unit costs is: " << to_string(seed) << endl; - shuffle(allTheCosts.begin(), allTheCosts.end(), std::mt19937(seed)); - - size_t index = 0; - for (int unitId: unitIds) { - vector &resourceCosts = allTheCosts.at(index); - cout << "Setting cost of unit with id " << unitId << " to " << costToString(resourceCosts) << endl; - if (!bothRequirePopulationHeadroom(unitId, resourceCosts, df->Civs.at(0))) { - copyResourceCostAt(unitId, 2, resourceCosts, df->Civs.at(0)); - } - for (genie::Civ &civ : df->Civs) { - civ.Units.at(unitId).Creatable.ResourceCosts = resourceCosts; - } - index++; - } - - int maleVillagerCost = getSumOfNaturalResourceCosts( - df->Civs.at(0).Units.at(ID_VILLAGER_BASE_M).Creatable.ResourceCosts); - int femaleVillagerCost = getSumOfNaturalResourceCosts( - df->Civs.at(0).Units.at(ID_VILLAGER_BASE_F).Creatable.ResourceCosts); - if (maleVillagerCost <= 200 && femaleVillagerCost <= 200) { - return; - } - cout << "Villagers are too expensive, reshuffling…" << endl; - } - cout << "Giving up, villagers stay expensive, sorry." << endl; -} - -void jumbleTechCosts(genie::DatFile *df) { - vector techIds; - - vector> allTheCosts; - size_t index = 0; - for (const genie::Tech &tech : df->Techs) { - vector resourceCopy = tech.ResourceCosts; - if (hasNaturalResearchResourceCost(resourceCopy)) { - allTheCosts.push_back(resourceCopy); - techIds.push_back(index); - } - index++; - } - - unsigned int seed = std::random_device()(); - cout << "Seed for shuffling tech costs is: " << to_string(seed) << endl; - shuffle(allTheCosts.begin(), allTheCosts.end(), std::mt19937(seed)); - - index = 0; - for (size_t techId : techIds) { - vector &resourceCosts = allTheCosts.at(index); - cout << "Setting cost of tech with id " << techId << " to " << costToString(resourceCosts) << endl; - df->Techs.at(techId).ResourceCosts = resourceCosts; - index++; - } - -} - -int getSumOfNaturalResourceCosts(const vector& resourceCosts) { - int16_t sum = 0; - for (const ResourceCost& cost : resourceCosts) { - if (cost.Type > -1 && cost.Type < 4) { - sum += cost.Amount; - } - } - return sum; -} - -bool isNaturalResourceCost(const ResourceCost &cost) { - return cost.Type != -1 && cost.Type < 4 && cost.Amount > 0; -} - -bool isNaturalResearchResourceCost(const ResearchResourceCost &cost) { - return cost.Type != -1 && cost.Type < 4 && cost.Amount > 0; -} - -bool hasNaturalResourceCost(const genie::Unit &unit) { - vector costs = unit.Creatable.ResourceCosts; - return any_of(costs.begin(), costs.end(), isNaturalResourceCost); -} - -bool hasNaturalResearchResourceCost(vector costs) { - return any_of(costs.begin(), costs.end(), isNaturalResearchResourceCost); -} - -string costToString(const vector &costs) { - string s; - for (const ResourceCost &cost : costs) { - if (cost.Flag == 1) { - s += to_string(cost.Amount); - s += " "; - switch (cost.Type) { - case TYPE_FOOD: - s += "Food "; - break; - case TYPE_WOOD: - s += "Wood "; - break; - case TYPE_GOLD: - s += "Gold "; - break; - case TYPE_STONE: - s += "Stone "; - break; - case TYPE_POPULATION_HEADROOM: - s += "Pop "; - break; - default: - s += "vat?"; - } - } - } - return s; -} - -string costToString(const vector &costs) { - string s; - for (const ResearchResourceCost &cost : costs) { - if (cost.Flag == 1) { - s += to_string(cost.Amount); - s += " "; - switch (cost.Type) { - case TYPE_FOOD: - s += "Food "; - break; - case TYPE_WOOD: - s += "Wood "; - break; - case TYPE_GOLD: - s += "Gold "; - break; - case TYPE_STONE: - s += "Stone "; - break; - case TYPE_POPULATION_HEADROOM: - s += "Pop "; - break; - default: - s += "vat?"; - } - } - } - return s; -} - -bool bothRequirePopulationHeadroom(int unitId, vector &resourceCosts, const genie::Civ &civ) { - return ((civ.Units.at(unitId).Creatable.ResourceCosts.at(2).Type == TYPE_POPULATION_HEADROOM && - resourceCosts.at(2).Type == TYPE_POPULATION_HEADROOM) || - (civ.Units.at(unitId).Creatable.ResourceCosts.at(2).Type != TYPE_POPULATION_HEADROOM && - resourceCosts.at(2).Type != TYPE_POPULATION_HEADROOM)); -} - -void copyResourceCostAt(int unitId, int index, vector &target, const genie::Civ &civ) { - genie::ResourceUsage source = civ.Units.at(unitId).Creatable.ResourceCosts.at(index); - target.at(index).Type = source.Type; - target.at(index).Amount = source.Amount; - target.at(index).Flag = source.Flag; -} diff --git a/patches.h b/patches.h deleted file mode 100644 index a5dd3c2..0000000 --- a/patches.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef CREATE_DATA_MOD_PATCHES_H -#define CREATE_DATA_MOD_PATCHES_H - -void configureCommunityGamesMod(genie::DatFile *df); -void configureExplodingVillagers(genie::DatFile *df); -void makeTransportShipsFly(genie::DatFile *df); -void duplicateTechs(genie::DatFile *df, int totalCount); -void configureKidnap(genie::DatFile *df); -void disableWalls(genie::DatFile *df); -void preventRamsAndSiegeTowersFromBoardingTransportShips(genie::DatFile *df); -void duplicateTech(genie::DatFile *df, const genie::Tech &tech, int totalCount); -void disableTechEffect(genie::Tech *tech); -void disableTechResearchLocation(genie::Tech *tech); -void addPopulationCostToBombardTower(genie::DatFile *df); -void addGreatHallTech(genie::DatFile *df); -void addElitePetard(genie::DatFile *df); -void modifyCaravanCost(genie::DatFile *df, int amountFood, int amountGold); -void makeTreesContain200Wood(genie::DatFile *df); -void jumbleCosts(genie::DatFile *df); -void jumbleUnitCosts(genie::DatFile *df); -void jumbleTechCosts(genie::DatFile *df); - -#endif //CREATE_DATA_MOD_PATCHES_H diff --git a/patches/community_games.cpp b/patches/community_games.cpp new file mode 100644 index 0000000..06d93ee --- /dev/null +++ b/patches/community_games.cpp @@ -0,0 +1,160 @@ +#include "community_games.h" +#include +#include "genie/dat/DatFile.h" +#include "ids.h" + + +void addPopulationCostToBombardTower(genie::DatFile *df) { + std::cout << "Adding population cost to bombard towers of all civs" << std::endl; + for (genie::Civ &civ : df->Civs) { + genie::Unit &bombard_tower = civ.Units.at(BOMBARD_TOWER); + genie::ResourceUsage &resourceCosts = bombard_tower.Creatable.ResourceCosts.at(2); + resourceCosts.Type = TYPE_POPULATION_HEADROOM; + resourceCosts.Amount = 1; + resourceCosts.Flag = 0; + + bombard_tower.ResourceStorages.at(0).Type = TYPE_POPULATION_HEADROOM; + bombard_tower.ResourceStorages.at(0).Amount = -1; + bombard_tower.ResourceStorages.at(0).Flag = 2; + + bombard_tower.ResourceStorages.at(1).Type = TYPE_CURRENT_POPULATION; + bombard_tower.ResourceStorages.at(1).Amount = 1; + bombard_tower.ResourceStorages.at(1).Flag = 2; + + bombard_tower.ResourceStorages.at(2).Type = TYPE_TOTAL_UNITS_OWNED; + bombard_tower.ResourceStorages.at(2).Amount = 1; + bombard_tower.ResourceStorages.at(2).Flag = 1; + } +} + + +void addGreatHallTech(genie::DatFile *df) { + std::cout << "Adding great hall tech" << std::endl; + auto effectCommand = new genie::EffectCommand(); + effectCommand->Type = 1; // Resource Modifier + effectCommand->A = 32; // Resource: Bonus Population Cap + effectCommand->B = 1; // Mode: +/- + effectCommand->D = 10; // Amount +/- + + auto effect = new genie::Effect(); + effect->Name = "Great Hall"; + effect->EffectCommands.push_back(*effectCommand); + + df->Effects.push_back(*effect); + size_t greatHallEffectId = df->Effects.size() - 1; + + auto tech = new genie::Tech(); + tech->Name = "The Great Hall"; + tech->RequiredTechs.push_back(BOMBARD_TOWER_TECH); + tech->ResearchTime = 5; + tech->IconID = 103; + tech->ButtonID = 1; + tech->EffectID = greatHallEffectId; + tech->ResearchLocation = BOMBARD_TOWER; + + tech->ResourceCosts.at(0).Type = TYPE_WOOD; + tech->ResourceCosts.at(0).Amount = 400; + tech->ResourceCosts.at(0).Flag = 1; + + tech->ResourceCosts.at(1).Type = TYPE_GOLD; + tech->ResourceCosts.at(1).Amount = 600; + tech->ResourceCosts.at(1).Flag = 1; + + df->Techs.push_back(*tech); +} + + +void addElitePetard(genie::DatFile *df) { + int elitePetardId = -1; + for (genie::Civ &civ : df->Civs) { + genie::Unit elitePetard = civ.Units.at(PETARD); + elitePetard.Enabled = 0; + elitePetard.Name = "Elite Petard"; + elitePetard.HitPoints = 60; + elitePetard.Speed = 1.05; + elitePetard.Type50.DisplayedAttack = 45; + elitePetard.Type50.BlastWidth = 1.5; + elitePetard.Type50.BlastAttackLevel = 1; + elitePetard.Type50.Attacks.at(0).Amount = 150; + elitePetard.Type50.Attacks.at(1).Amount = 650; + elitePetard.Type50.Attacks.at(2).Amount = 45; + elitePetard.Type50.Attacks.at(3).Amount = 70; + elitePetard.Type50.Attacks.at(4).Amount = 1000; + elitePetard.Type50.Armours.at(1).Amount = 3; + elitePetard.Creatable.DisplayedPierceArmour = 3; + elitePetardId = civ.Units.size(); + std::cout << "Adding elite petard for civ " << civ.Name << " with ID " << elitePetardId << std::endl; + civ.Units.push_back(elitePetard); + civ.UnitPointers.push_back(1); + } + + auto effectCommand = new genie::EffectCommand(); + effectCommand->Type = 3; // Upgrade Unit + effectCommand->A = PETARD; + effectCommand->B = elitePetardId; + + auto effect = new genie::Effect(); + effect->Name = "Elite Petard"; + effect->EffectCommands.push_back(*effectCommand); + int elitePetardEffectId = df->Effects.size(); + df->Effects.push_back(*effect); + + auto tech = new genie::Tech(); + tech->Name = "Elite Petard"; + tech->RequiredTechs.push_back(CHEMISTRY); + tech->RequiredTechCount = 1; + tech->ResearchTime = 40; + tech->IconID = 105; + tech->ButtonID = 9; + tech->EffectID = elitePetardEffectId; + tech->ResearchLocation = CASTLE; + + tech->ResourceCosts.at(0).Type = TYPE_FOOD; + tech->ResourceCosts.at(0).Amount = 450; + tech->ResourceCosts.at(0).Flag = 1; + + tech->ResourceCosts.at(1).Type = TYPE_GOLD; + tech->ResourceCosts.at(1).Amount = 450; + tech->ResourceCosts.at(1).Flag = 1; + + std::cout << "Adding Elite Petard Tech with id " << df->Techs.size() << std::endl; + df->Techs.push_back(*tech); +} + + +void modifyCaravanCost(genie::DatFile *df, int amountFood, int amountGold) { + std::cout << "Setting the cost of Caravan (" << TECH_CARAVAN << ") to " << amountFood << " Food, " << amountGold + << " Gold" << std::endl; + genie::Tech &caravan = df->Techs.at(TECH_CARAVAN); + caravan.ResourceCosts.at(0).Type = TYPE_FOOD; + caravan.ResourceCosts.at(0).Amount = amountFood; + caravan.ResourceCosts.at(0).Flag = 1; + + caravan.ResourceCosts.at(1).Type = TYPE_GOLD; + caravan.ResourceCosts.at(1).Amount = amountGold; + caravan.ResourceCosts.at(1).Flag = 1; +} + + +void makeTreesContain200Wood(genie::DatFile *df) { + for (genie::Civ &civ : df->Civs) { + for (genie::Unit &unit : civ.Units) { + for (auto storage : unit.ResourceStorages) { + if (storage.Type == TYPE_WOOD && storage.Amount > 50) { + std::cout << "Setting amount of wood in " << unit.Name << " (" << unit.ID << ") to 200" + << std::endl; + storage.Amount = 200; + } + } + } + } +} + + +void configureCommunityGamesMod(genie::DatFile *df) { + addPopulationCostToBombardTower(df); + addGreatHallTech(df); + addElitePetard(df); + modifyCaravanCost(df, 800, 200); + makeTreesContain200Wood(df); +} diff --git a/patches/community_games.h b/patches/community_games.h new file mode 100644 index 0000000..7f3dd40 --- /dev/null +++ b/patches/community_games.h @@ -0,0 +1,9 @@ +#ifndef COMMUNITY_GAMES_H +#define COMMUNITY_GAMES_H + +#include "genie/dat/DatFile.h" + + +void configureCommunityGamesMod(genie::DatFile *df); + +#endif // COMMUNITY_GAMES_H diff --git a/patches/duplicate_techs.cpp b/patches/duplicate_techs.cpp new file mode 100644 index 0000000..b544940 --- /dev/null +++ b/patches/duplicate_techs.cpp @@ -0,0 +1,147 @@ +#include "duplicate_techs.h" +#include +#include +#include "genie/dat/DatFile.h" +#include "ids.h" + + +void duplicateTech(genie::DatFile *df, const genie::Tech &tech, int totalCount) { + for (int i = 0; i < (totalCount - 1); ++i) { + df->Techs.push_back(tech); + } + std::cout << "Added Tech '" << tech.Name << "' for a total of " << totalCount << " instances" << std::endl; +} + + +void duplicateTechs(genie::DatFile *df, int totalCount) { + const std::list techsToDuplicate = { + YEOMEN, + EL_DORADO, + FUROR_CELTICA, + DRILL, + MAHOUTS, + TOWN_WATCH, + ZEALOTRY, + ARTILLERY, + CRENELLATIONS, + CROP_ROTATION, + HEAVY_PLOW, + HORSE_COLLAR, + GUILDS, + BANKING, + ATHEISM, + LOOM, + GARLAND_WARS, + HUSBANDRY, + FAITH, + CHEMISTRY, + CARAVAN, + BERSERKERGANG, + MASONRY, + ARCHITECTURE, + ROCKETRY, + TREADMILL_CRANE, + GOLD_MINING, + KATAPARUTO, + LOGISTICA, + GILLNETS, + FORGING, + IRON_CASTING, + SCALE_MAIL_ARMOR, + BLAST_FURNACE, + CHAIN_MAIL_ARMOR, + PLATE_MAIL_ARMOR, + PLATE_BARDING_ARMOR, + SCALE_BARDING_ARMOR, + CHAIN_BARDING_ARMOR, + BEARDED_AXE, + GOLD_SHAFT_MINING, + FLETCHING, + BODKIN_ARROW, + BRACER, + DOUBLE_BIT_AXE, + BOW_SAW, + PADDED_ARCHER_ARMOR, + LEATHER_ARCHER_ARMOR, + WHEELBARROW, + SQUIRES, + RING_ARCHER_ARMOR, + TWO_MAN_SAW, + BLOCK_PRINTING, + SANCTITY, + ILLUMINATION, + HAND_CART, + FERVOR, + STONE_MINING, + STONE_SHAFT_MINING, + TOWN_PATROL, + CONSCRIPTION, + SAPPERS, + SHIPWRIGHT, + CAREENING, + DRY_DOCK, + SIEGE_ENGINEERS, + HOARDINGS, + HEATED_SHOT, + BLOODLINES, + PARTHIAN_TACTICS, + THUMB_RING, + SUPREMACY, + HERBAL_MEDICINE, + SHINKICHON, + PERFUSION, + ATLATL, + WARWOLF, + GREAT_WALL, + CHIEFTAINS, + GREEK_FIRE, + STRONGHOLD, + YASAMA, + OBSIDIAN_ARROWS, + PANOKSEON, + KAMANDARAN, + IRONCLAD, + SIPAHI, + INQUISITION, + CHIVALRY, + PAVISE, + SILK_ROAD, + SULTANS, + SHATAGNI, + ORTHODOXY, + DRUZHINA, + RECURVE_BOW, + FABRIC_SHIELDS, + CARRACK, + ARQUEBUS, + ROYAL_HEIRS, + TORSION_ENGINES, + TIGUI, + FARIMBA, + KASBAH, + MAGHRABI_CAMELS, + ARSON, + ARROWSLITS, + TUSK_SWORDS, + DOUBLE_CROSSBOW, + FORCED_LEVY, + HOWDAH, + MANIPUR_CAVALRY, + CHATRAS, + PAPER_MONEY, + STIRRUPS, + BAGAINS, + SILK_ARMOR, + TIMURID_SIEGECRAFT, + STEPPE_HUSBANDRY, + CUMAN_MERCENARIES, + HILL_FORTS, + TOWER_SHIELDS, + SUPPLIES, + }; + + for (int techId : techsToDuplicate) { + genie::Tech tech = df->Techs.at(techId); + duplicateTech(df, tech, totalCount); + } +} diff --git a/patches/duplicate_techs.h b/patches/duplicate_techs.h new file mode 100644 index 0000000..2c33480 --- /dev/null +++ b/patches/duplicate_techs.h @@ -0,0 +1,9 @@ +#ifndef DUPLICATE_TECHS_H +#define DUPLICATE_TECHS_H + +#include "genie/dat/DatFile.h" + + +void duplicateTechs(genie::DatFile *df, int totalCount); + +#endif // DUPLICATE_TECHS_H diff --git a/patches/exploding_villagers.cpp b/patches/exploding_villagers.cpp new file mode 100644 index 0000000..436634a --- /dev/null +++ b/patches/exploding_villagers.cpp @@ -0,0 +1,34 @@ +#include "exploding_villagers.h" +#include +#include "genie/dat/DatFile.h" +#include "ids.h" + + +void configureExplodingVillagers(genie::DatFile *df) { + std::set villagers = { + ID_FISHING_SHIP, ID_TRADE_COG, ID_TRADE_CART_EMPTY, ID_TRADE_CART_FULL, + ID_VILLAGER_BASE_M, ID_VILLAGER_BASE_F, ID_VILLAGER_FARMER_M, ID_VILLAGER_FARMER_F, + ID_VILLAGER_SHEPHERD_M, ID_VILLAGER_SHEPHERD_F, ID_VILLAGER_FORAGER_M, ID_VILLAGER_FORAGER_F, + ID_VILLAGER_HUNTER_M, ID_VILLAGER_HUNTER_F, ID_VILLAGER_FISHER_M, ID_VILLAGER_FISHER_F, + ID_VILLAGER_WOOD_M, ID_VILLAGER_WOOD_F, ID_VILLAGER_GOLD_M, ID_VILLAGER_GOLD_F, + ID_VILLAGER_STONE_M, ID_VILLAGER_STONE_F, ID_VILLAGER_BUILDER_M, ID_VILLAGER_BUILDER_F, + ID_VILLAGER_REPAIRER_M, ID_VILLAGER_REPAIRER_F, + }; + + for (genie::Civ &civ : df->Civs) { + for (int villager_id : villagers) { + civ.Units.at(villager_id).DeadUnitID = ID_SABOTEUR; + std::cout << "Patched Villager unit " << villager_id << " for civ " << civ.Name << "\n"; + } + genie::Unit &saboteur = civ.Units.at(ID_SABOTEUR); + saboteur.HitPoints = 0; + saboteur.Type50.Attacks.at(0).Amount = 50; + saboteur.Type50.Attacks.at(1).Amount = 90; + saboteur.Type50.Attacks.at(2).Amount = 0; + saboteur.Type50.MaxRange = 2; + saboteur.Type50.BlastAttackLevel = 1; // cut trees + saboteur.TrainSound = -1; + saboteur.WwiseTrainSoundID = 0; // prevent melee unit train sound from playing + std::cout << "Patched Saboteur unit for civ " << civ.Name << "\n"; + } +} diff --git a/patches/exploding_villagers.h b/patches/exploding_villagers.h new file mode 100644 index 0000000..b85a8bd --- /dev/null +++ b/patches/exploding_villagers.h @@ -0,0 +1,9 @@ +#ifndef EXPLODING_VILLAGERS_H +#define EXPLODING_VILLAGERS_H + +#include "genie/dat/DatFile.h" + + +void configureExplodingVillagers(genie::DatFile *df); + +#endif // EXPLODING_VILLAGERS_H diff --git a/patches/flying_dutchman.cpp b/patches/flying_dutchman.cpp new file mode 100644 index 0000000..a050a75 --- /dev/null +++ b/patches/flying_dutchman.cpp @@ -0,0 +1,15 @@ +#include "flying_dutchman.h" +#include +#include "genie/dat/DatFile.h" +#include "ids.h" + + +void makeTransportShipsFly(genie::DatFile *df) { + for (genie::Civ &civ : df->Civs) { + genie::Unit &transport_ship = civ.Units.at(ID_TRANSPORT_SHIP); + transport_ship.FlyMode = 1; // true + transport_ship.TerrainRestriction = 0; // All + transport_ship.CollisionSize = {0, 0, 0}; // walk through everything, like flying + std::cout << "Patched Transport Ship unit for civ " << civ.Name << "\n"; + } +} diff --git a/patches/flying_dutchman.h b/patches/flying_dutchman.h new file mode 100644 index 0000000..e38942f --- /dev/null +++ b/patches/flying_dutchman.h @@ -0,0 +1,9 @@ +#ifndef FLYING_DUTCHMAN_H +#define FLYING_DUTCHMAN_H + +#include "genie/dat/DatFile.h" + + +void makeTransportShipsFly(genie::DatFile *df); + +#endif // FLYING_DUTCHMAN_H diff --git a/patches/kidnap.cpp b/patches/kidnap.cpp new file mode 100644 index 0000000..205e0b1 --- /dev/null +++ b/patches/kidnap.cpp @@ -0,0 +1,42 @@ +#include "kidnap.h" +#include +#include "genie/dat/DatFile.h" +#include "ids.h" + + +void configureKidnap(genie::DatFile *df) { + const std::list scoutIds = { + ID_SCOUT, + ID_EAGLE_SCOUT, + }; + for (genie::Civ &civ : df->Civs) { + for (int scoutId : scoutIds) { + genie::Unit &scout = civ.Units.at(scoutId); + std::cout << "Setting Scout (" << scoutId << ") properties for civ " << civ.Name << std::endl; + scout.Type50.Attacks.clear(); + scout.Type50.DisplayedAttack = 0; + scout.GarrisonCapacity = 1; + scout.Bird.TaskList.erase(scout.Bird.TaskList.begin()); + + std::cout << "Adding Kidnap Task to scout (" << scoutId << ") for civ " << civ.Name << std::endl; + auto kidnapTask = new genie::Task(); + kidnapTask->ActionType = ACTION_KIDNAP_UNIT; + kidnapTask->ClassID = CLASS_CIVILIAN; + kidnapTask->WorkRange = 0.25; + kidnapTask->ProceedingGraphicID = 1966; // SCOUT_AN + kidnapTask->TargetDiplomacy = 2; + kidnapTask->GatherType = 2; + scout.Bird.TaskList.push_back(*kidnapTask); + + std::cout << "Adding Loot Task to scout (" << scoutId << ") for civ " << civ.Name << std::endl; + auto lootTask = new genie::Task(); + lootTask->ActionType = ACTION_LOOT; + lootTask->ClassID = CLASS_BUILDING; + lootTask->WorkRange = 0.25; + lootTask->ProceedingGraphicID = 1966; // SCOUT_AN + lootTask->TargetDiplomacy = 2; + lootTask->GatherType = 1; + scout.Bird.TaskList.push_back(*lootTask); + } + } +} diff --git a/patches/kidnap.h b/patches/kidnap.h new file mode 100644 index 0000000..44f8941 --- /dev/null +++ b/patches/kidnap.h @@ -0,0 +1,9 @@ +#ifndef KIDNAP_H +#define KIDNAP_H + +#include "genie/dat/DatFile.h" + + +void configureKidnap(genie::DatFile *df); + +#endif // KIDNAP_H diff --git a/patches/no_wall.cpp b/patches/no_wall.cpp new file mode 100644 index 0000000..3449783 --- /dev/null +++ b/patches/no_wall.cpp @@ -0,0 +1,46 @@ +#include "no_wall.h" +#include +#include "genie/dat/DatFile.h" +#include "ids.h" + + +void disableTechEffect(genie::Tech *tech) { tech->EffectID = -1; } + + +void disableTechResearchLocation(genie::Tech *tech) { tech->ResearchLocation = -1; } + + +void disableWalls(genie::DatFile *df) { + const std::list unitsToDisable = { + PALISADE_WALL, + }; + + const std::list techsToDisable = { + TECH_PALISADE_GATE, + TECH_STONE_WALLS, + }; + + const std::list techsToHide = { + TECH_FORTIFIED_WALL, + }; + + for (int unitId : unitsToDisable) { + std::cout << "Disabling unit with id " << unitId << " for all civs" << std::endl; + for (genie::Civ &civ : df->Civs) { + civ.Units.at(unitId).Enabled = 0; + } + } + + for (int techId : techsToDisable) { + genie::Tech *tech = &df->Techs.at(techId); + std::cout << "Disabling the effect of tech with id " << techId << " ('" << tech->Name << "')" << std::endl; + disableTechEffect(tech); + } + + for (int techId : techsToHide) { + genie::Tech *tech = &df->Techs.at(techId); + std::cout << "Disabling the research location of tech with id " << techId << " ('" << tech->Name << "')" + << std::endl; + disableTechResearchLocation(tech); + } +} diff --git a/patches/no_wall.h b/patches/no_wall.h new file mode 100644 index 0000000..4afef04 --- /dev/null +++ b/patches/no_wall.h @@ -0,0 +1,9 @@ +#ifndef NO_WALL_H +#define NO_WALL_H + +#include "genie/dat/DatFile.h" + + +void disableWalls(genie::DatFile *df); + +#endif // NO_WALL_H diff --git a/patches/random_costs.cpp b/patches/random_costs.cpp new file mode 100644 index 0000000..ee67d3a --- /dev/null +++ b/patches/random_costs.cpp @@ -0,0 +1,301 @@ +#include "random_costs.h" +#include +#include +#include +#include +#include "genie/dat/DatFile.h" +#include "ids.h" + + +typedef genie::ResourceUsage ResourceCost; +typedef genie::ResourceUsage ResearchResourceCost; + + +bool isNaturalResourceCost(const ResourceCost &cost) { return cost.Type != -1 && cost.Type < 4 && cost.Amount > 0; } + + +bool isNaturalResearchResourceCost(const ResearchResourceCost &cost) { + return cost.Type != -1 && cost.Type < 4 && cost.Amount > 0; +} + + +bool hasNaturalResourceCost(const genie::Unit &unit) { + std::vector costs = unit.Creatable.ResourceCosts; + return std::any_of(costs.begin(), costs.end(), isNaturalResourceCost); +} + + +bool hasNaturalResearchResourceCost(std::vector costs) { + return std::any_of(costs.begin(), costs.end(), isNaturalResearchResourceCost); +} + + +int getSumOfNaturalResourceCosts(const std::vector &resourceCosts) { + int16_t sum = 0; + for (const ResourceCost &cost : resourceCosts) { + if (cost.Type > -1 && cost.Type < 4) { + sum += cost.Amount; + } + } + return sum; +} + + +ResearchResourceCost toResearchResourceCost(const ResourceCost &resourceCost) { + ResearchResourceCost researchResourceCost; + researchResourceCost.Type = resourceCost.Type; + researchResourceCost.Amount = resourceCost.Amount; + researchResourceCost.Flag = (bool)resourceCost.Flag; + return researchResourceCost; +} + + +ResourceCost toResourceCost(const ResearchResourceCost &researchResourceCost) { + ResourceCost resourceCost; + resourceCost.Type = researchResourceCost.Type; + resourceCost.Amount = researchResourceCost.Amount; + resourceCost.Flag = (bool)researchResourceCost.Flag; + return resourceCost; +} + + +std::vector toResearchResourceCosts(const std::vector &resourceCosts) { + std::vector researchResourceCosts; + researchResourceCosts.reserve(resourceCosts.size()); + for (const ResourceCost &resourceCost : resourceCosts) { + researchResourceCosts.push_back(toResearchResourceCost(resourceCost)); + } + return researchResourceCosts; +} + + +std::vector toResourceCosts(const std::vector &researchResourceCosts) { + std::vector resourceCosts; + resourceCosts.reserve(researchResourceCosts.size()); + for (const ResearchResourceCost &researchResourceCost : researchResourceCosts) { + resourceCosts.push_back(toResourceCost(researchResourceCost)); + } + return resourceCosts; +} + + +std::string costToString(const std::vector &costs) { + std::string s; + for (const ResourceCost &cost : costs) { + if (cost.Flag == 1) { + s += std::to_string(cost.Amount); + s += " "; + switch (cost.Type) { + case TYPE_FOOD: + s += "Food "; + break; + case TYPE_WOOD: + s += "Wood "; + break; + case TYPE_GOLD: + s += "Gold "; + break; + case TYPE_STONE: + s += "Stone "; + break; + case TYPE_POPULATION_HEADROOM: + s += "Pop "; + break; + default: + s += "vat?"; + } + } + } + return s; +} + + +std::string costToString(const std::vector &costs) { + std::string s; + for (const ResearchResourceCost &cost : costs) { + if (cost.Flag == 1) { + s += std::to_string(cost.Amount); + s += " "; + switch (cost.Type) { + case TYPE_FOOD: + s += "Food "; + break; + case TYPE_WOOD: + s += "Wood "; + break; + case TYPE_GOLD: + s += "Gold "; + break; + case TYPE_STONE: + s += "Stone "; + break; + case TYPE_POPULATION_HEADROOM: + s += "Pop "; + break; + default: + s += "vat?"; + } + } + } + return s; +} + + +bool bothRequirePopulationHeadroom(int unitId, std::vector &resourceCosts, const genie::Civ &civ) { + return ((civ.Units.at(unitId).Creatable.ResourceCosts.at(2).Type == TYPE_POPULATION_HEADROOM && + resourceCosts.at(2).Type == TYPE_POPULATION_HEADROOM) || + (civ.Units.at(unitId).Creatable.ResourceCosts.at(2).Type != TYPE_POPULATION_HEADROOM && + resourceCosts.at(2).Type != TYPE_POPULATION_HEADROOM)); +} + + +void copyResourceCostAt(int unitId, int index, std::vector &target, const genie::Civ &civ) { + genie::ResourceUsage source = civ.Units.at(unitId).Creatable.ResourceCosts.at(index); + target.at(index).Type = source.Type; + target.at(index).Amount = source.Amount; + target.at(index).Flag = source.Flag; +} + + +void jumbleCosts(genie::DatFile *df) { + std::vector unitIds; + for (genie::Unit unit : df->Civs.at(0).Units) { + if (hasNaturalResourceCost(unit)) { + unitIds.push_back(unit.ID); + } + } + + std::vector techIds; + size_t index = 0; + for (const genie::Tech &tech : df->Techs) { + std::vector resourceCopy = tech.ResourceCosts; + if (hasNaturalResearchResourceCost(resourceCopy)) { + techIds.push_back(index); + } + index++; + } + + std::vector> allTheCosts; + for (int unitId : unitIds) { + std::vector resourceCopy = df->Civs.at(0).Units.at(unitId).Creatable.ResourceCosts; + allTheCosts.push_back(resourceCopy); + } + + for (int techId : techIds) { + std::vector resourceCopy = toResourceCosts(df->Techs.at(techId).ResourceCosts); + allTheCosts.push_back(resourceCopy); + } + + for (int i = 0; i < 10; i++) { + unsigned int seed = std::random_device()(); + std::cout << "Seed for shuffling unit and tech costs is: " << std::to_string(seed) << std::endl; + shuffle(allTheCosts.begin(), allTheCosts.end(), std::mt19937(seed)); + + size_t costIndex = 0; + for (int techId : techIds) { + std::vector researchResourceCosts = + toResearchResourceCosts(allTheCosts.at(costIndex)); + std::cout << "Setting cost of tech with id " << techId << " to " << costToString(researchResourceCosts) + << std::endl; + df->Techs.at(techId).ResourceCosts = researchResourceCosts; + costIndex++; + } + for (int unitId : unitIds) { + std::vector &resourceCosts = allTheCosts.at(costIndex); + std::cout << "Setting cost of unit with id " << unitId << " to " << costToString(resourceCosts) + << std::endl; + if (!bothRequirePopulationHeadroom(unitId, resourceCosts, df->Civs.at(0))) { + copyResourceCostAt(unitId, 2, resourceCosts, df->Civs.at(0)); + } + for (genie::Civ &civ : df->Civs) { + civ.Units.at(unitId).Creatable.ResourceCosts = resourceCosts; + } + costIndex++; + } + + int maleVillagerCost = + getSumOfNaturalResourceCosts(df->Civs.at(0).Units.at(ID_VILLAGER_BASE_M).Creatable.ResourceCosts); + int femaleVillagerCost = + getSumOfNaturalResourceCosts(df->Civs.at(0).Units.at(ID_VILLAGER_BASE_F).Creatable.ResourceCosts); + if (maleVillagerCost <= 200 && femaleVillagerCost <= 200) { + return; + } + std::cout << "Villagers are too expensive, reshuffling…" << std::endl; + } + std::cout << "Giving up, villagers stay expensive, sorry." << std::endl; +} + + +void jumbleUnitCosts(genie::DatFile *df) { + std::vector unitIds; + + for (genie::Unit unit : df->Civs.at(0).Units) { + if (hasNaturalResourceCost(unit)) { + unitIds.push_back(unit.ID); + } + } + + std::vector> allTheCosts; + for (int unitId : unitIds) { + std::vector resourceCopy = df->Civs.at(0).Units.at(unitId).Creatable.ResourceCosts; + allTheCosts.push_back(resourceCopy); + } + + for (int i = 0; i < 10; i++) { + unsigned int seed = std::random_device()(); + std::cout << "Seed for shuffling unit costs is: " << std::to_string(seed) << std::endl; + std::shuffle(allTheCosts.begin(), allTheCosts.end(), std::mt19937(seed)); + + size_t index = 0; + for (int unitId : unitIds) { + std::vector &resourceCosts = allTheCosts.at(index); + std::cout << "Setting cost of unit with id " << unitId << " to " << costToString(resourceCosts) + << std::endl; + if (!bothRequirePopulationHeadroom(unitId, resourceCosts, df->Civs.at(0))) { + copyResourceCostAt(unitId, 2, resourceCosts, df->Civs.at(0)); + } + for (genie::Civ &civ : df->Civs) { + civ.Units.at(unitId).Creatable.ResourceCosts = resourceCosts; + } + index++; + } + + int maleVillagerCost = + getSumOfNaturalResourceCosts(df->Civs.at(0).Units.at(ID_VILLAGER_BASE_M).Creatable.ResourceCosts); + int femaleVillagerCost = + getSumOfNaturalResourceCosts(df->Civs.at(0).Units.at(ID_VILLAGER_BASE_F).Creatable.ResourceCosts); + if (maleVillagerCost <= 200 && femaleVillagerCost <= 200) { + return; + } + std::cout << "Villagers are too expensive, reshuffling…" << std::endl; + } + std::cout << "Giving up, villagers stay expensive, sorry." << std::endl; +} + + +void jumbleTechCosts(genie::DatFile *df) { + std::vector techIds; + + std::vector> allTheCosts; + size_t index = 0; + for (const genie::Tech &tech : df->Techs) { + std::vector resourceCopy = tech.ResourceCosts; + if (hasNaturalResearchResourceCost(resourceCopy)) { + allTheCosts.push_back(resourceCopy); + techIds.push_back(index); + } + index++; + } + + unsigned int seed = std::random_device()(); + std::cout << "Seed for shuffling tech costs is: " << std::to_string(seed) << std::endl; + shuffle(allTheCosts.begin(), allTheCosts.end(), std::mt19937(seed)); + + index = 0; + for (size_t techId : techIds) { + std::vector &resourceCosts = allTheCosts.at(index); + std::cout << "Setting cost of tech with id " << techId << " to " << costToString(resourceCosts) << std::endl; + df->Techs.at(techId).ResourceCosts = resourceCosts; + index++; + } +} diff --git a/patches/random_costs.h b/patches/random_costs.h new file mode 100644 index 0000000..7f36e7e --- /dev/null +++ b/patches/random_costs.h @@ -0,0 +1,11 @@ +#ifndef RANDOM_COSTS_H +#define RANDOM_COSTS_H + +#include "genie/dat/DatFile.h" + + +void jumbleCosts(genie::DatFile *df); +void jumbleUnitCosts(genie::DatFile *df); +void jumbleTechCosts(genie::DatFile *df); + +#endif // RANDOM_COSTS_H