/* * CCampaignHandler.h, part of VCMI engine * * Authors: listed in file AUTHORS in main folder * * License: GNU General Public License v2.0 or later * Full text of license available in license.txt file, in main folder * */ #pragma once #include "../../lib/GameConstants.h" struct StartInfo; class CGHeroInstance; class CBinaryReader; class CMap; class CMapHeader; class CMapInfo; class JsonNode; namespace CampaignVersion { enum Version { RoE = 4, AB = 5, SoD = 6, WoG = 6 }; } class DLL_LINKAGE CCampaignHeader { public: si32 version; //4 - RoE, 5 - AB, 6 - SoD and WoG ui8 mapVersion; //CampText.txt's format std::string name, description; ui8 difficultyChoosenByPlayer; ui8 music; //CmpMusic.txt, start from 0 std::string filename; ui8 loadFromLod; //if true, this campaign must be loaded fro, .lod file CCampaignHeader(); template void serialize(Handler &h, const int formatVersion) { h & version; h & mapVersion; h & name; h & description; h & difficultyChoosenByPlayer; h & music; h & filename; h & loadFromLod; } }; class DLL_LINKAGE CScenarioTravel { public: ui8 whatHeroKeeps; //bitfield [0] - experience, [1] - prim skills, [2] - sec skills, [3] - spells, [4] - artifacts std::array monstersKeptByHero; std::array artifsKeptByHero; ui8 startOptions; //1 - start bonus, 2 - traveling hero, 3 - hero options ui8 playerColor; //only for startOptions == 1 struct DLL_LINKAGE STravelBonus { enum EBonusType {SPELL, MONSTER, BUILDING, ARTIFACT, SPELL_SCROLL, PRIMARY_SKILL, SECONDARY_SKILL, RESOURCE, HEROES_FROM_PREVIOUS_SCENARIO, HERO}; EBonusType type; //uses EBonusType si32 info1, info2, info3; //purpose depends on type bool isBonusForHero() const; STravelBonus(); template void serialize(Handler &h, const int formatVersion) { h & type; h & info1; h & info2; h & info3; } }; std::vector bonusesToChoose; CScenarioTravel(); template void serialize(Handler &h, const int formatVersion) { h & whatHeroKeeps; h & monstersKeptByHero; h & artifsKeptByHero; h & startOptions; h & playerColor; h & bonusesToChoose; } }; class DLL_LINKAGE CCampaignScenario { public: struct DLL_LINKAGE SScenarioPrologEpilog { bool hasPrologEpilog; ui8 prologVideo; // from CmpMovie.txt ui8 prologMusic; // from CmpMusic.txt std::string prologText; SScenarioPrologEpilog(); template void serialize(Handler &h, const int formatVersion) { h & hasPrologEpilog; h & prologVideo; h & prologMusic; h & prologText; } }; std::string mapName; //*.h3m std::string scenarioName; //from header. human-readble ui32 packedMapSize; //generally not used std::set preconditionRegions; //what we need to conquer to conquer this one (stored as bitfield in h3c) ui8 regionColor; ui8 difficulty; bool conquered; std::string regionText; SScenarioPrologEpilog prolog, epilog; CScenarioTravel travelOptions; std::vector keepHeroes; // contains list of heroes which should be kept for next scenario (doesn't matter if they lost) std::vector crossoverHeroes; // contains all heroes with the same state when the campaign scenario was finished std::vector placedCrossoverHeroes; // contains all placed crossover heroes defined by hero placeholders when the scenario was started void loadPreconditionRegions(ui32 regions); bool isNotVoid() const; // FIXME: due to usage of JsonNode I can't make these methods const const CGHeroInstance * strongestHero(PlayerColor owner); std::vector getLostCrossoverHeroes(); /// returns a list of crossover heroes which started the scenario, but didn't complete it std::vector update787(std::vector & heroes); CCampaignScenario(); template void serialize(Handler &h, const int formatVersion) { h & mapName; h & scenarioName; h & packedMapSize; h & preconditionRegions; h & regionColor; h & difficulty; h & conquered; h & regionText; h & prolog; h & epilog; h & travelOptions; if(formatVersion < 787) { std::vector crossoverHeroesOld, placedCrossoverHeroesOld; h & crossoverHeroesOld; h & placedCrossoverHeroesOld; crossoverHeroes = update787(crossoverHeroesOld); placedCrossoverHeroes = update787(placedCrossoverHeroesOld); } else { h & crossoverHeroes; h & placedCrossoverHeroes; } h & keepHeroes; } }; class DLL_LINKAGE CCampaign { public: CCampaignHeader header; std::vector scenarios; std::map mapPieces; //binary h3ms, scenario number -> map data template void serialize(Handler &h, const int formatVersion) { h & header; h & scenarios; h & mapPieces; } bool conquerable(int whichScenario) const; CCampaign(); }; class DLL_LINKAGE CCampaignState { public: std::unique_ptr camp; std::string campaignName; std::vector mapsConquered, mapsRemaining; boost::optional currentMap; std::map chosenCampaignBonuses; void setCurrentMapAsConquered(const std::vector & heroes); boost::optional getBonusForCurrentMap() const; const CCampaignScenario & getCurrentScenario() const; CCampaignScenario & getCurrentScenario(); ui8 currentBonusID() const; CMap * getMap(int scenarioId = -1) const; std::unique_ptr getHeader(int scenarioId = -1) const; std::shared_ptr getMapInfo(int scenarioId = -1) const; static JsonNode crossoverSerialize(CGHeroInstance * hero); static CGHeroInstance * crossoverDeserialize(JsonNode & node); CCampaignState(); CCampaignState(std::unique_ptr _camp); ~CCampaignState(){}; template void serialize(Handler &h, const int version) { h & camp; h & campaignName; h & mapsRemaining; h & mapsConquered; h & currentMap; h & chosenCampaignBonuses; } }; class DLL_LINKAGE CCampaignHandler { static CCampaignHeader readHeaderFromMemory(CBinaryReader & reader); static CCampaignScenario readScenarioFromMemory(CBinaryReader & reader, int version, int mapVersion ); static CScenarioTravel readScenarioTravelFromMemory(CBinaryReader & reader, int version); /// returns h3c split in parts. 0 = h3c header, 1-end - maps (binary h3m) /// headerOnly - only header will be decompressed, returned vector wont have any maps static std::vector< std::vector > getFile(const std::string & name, bool headerOnly); public: static std::string prologVideoName(ui8 index); static std::string prologMusicName(ui8 index); static std::string prologVoiceName(ui8 index); static CCampaignHeader getHeader( const std::string & name); //name - name of appropriate file static std::unique_ptr getCampaign(const std::string & name); //name - name of appropriate file };