#ifndef __COBJECTHANDLER_H__ #define __COBJECTHANDLER_H__ #include "../global.h" #include #include #include #include #include #ifndef _MSC_VER #include "CHeroHandler.h" #include "CTownHandler.h" #include "../lib/VCMI_Lib.h" #endif #include "../lib/CCreatureSet.h" #include "CArtHandler.h" #include "../lib/ConstTransitivePtr.h" #include /* * CObjectHandler.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 * */ class CGameState; class CArtifactInstance; struct MetaString; struct BattleInfo; class IGameCallback; struct BattleResult; class CCPPObjectScript; class CGObjectInstance; class CScript; class CObjectScript; class CGHeroInstance; class CTown; class CHero; class CBuilding; class CSpell; class CGTownInstance; class CGTownBuilding; class CArtifact; class CGDefInfo; class CSpecObjInfo; class CCastleEvent; struct TerrainTile; struct InfoWindow; struct Component; struct BankConfig; struct UpdateHeroSpeciality; struct NewArtifact; class CGBoat; class CArtifactSet; class DLL_EXPORT CQuest { public: enum Emission {MISSION_NONE = 0, MISSION_LEVEL = 1, MISSION_PRIMARY_STAT = 2, MISSION_KILL_HERO = 3, MISSION_KILL_CREATURE = 4, MISSION_ART = 5, MISSION_ARMY = 6, MISSION_RESOURCES = 7, MISSION_HERO = 8, MISSION_PLAYER = 9}; ui8 missionType, progress; si32 lastDay; //after this day (first day is 0) mission cannot be completed; if -1 - no limit ui32 m13489val; std::vector m2stats; std::vector m5arts; //artifacts id std::vector m6creatures; //pair[cre id, cre count], CreatureSet info irrelevant std::vector m7resources; std::string firstVisitText, nextVisitText, completedText; bool isCustom; bool checkQuest (const CGHeroInstance * h) const; //determines whether the quest is complete or not virtual void completeQuest (const CGHeroInstance * h) const {}; template void serialize(Handler &h, const int version) { h & missionType & progress & lastDay & m13489val & m2stats & m5arts & m6creatures & m7resources & firstVisitText & nextVisitText & completedText & isCustom; } }; class DLL_EXPORT IObjectInterface { public: static IGameCallback *cb; IObjectInterface(); virtual ~IObjectInterface(); virtual void onHeroVisit(const CGHeroInstance * h) const; virtual void onHeroLeave(const CGHeroInstance * h) const; virtual void newTurn() const; virtual void initObj(); //synchr virtual void setProperty(ui8 what, ui32 val);//synchr static void preInit(); //called before objs receive their initObj static void postInit();//caleed after objs receive their initObj }; class DLL_EXPORT IBoatGenerator { public: const CGObjectInstance *o; IBoatGenerator(const CGObjectInstance *O); virtual int getBoatType() const; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral virtual void getOutOffsets(std::vector &offsets) const =0; //offsets to obj pos when we boat can be placed int3 bestLocation() const; //returns location when the boat should be placed int state() const; //0 - can buid, 1 - there is already a boat at dest tile, 2 - dest tile is blocked, 3 - no water void getProblemText(MetaString &out, const CGHeroInstance *visitor = NULL) const; }; class DLL_EXPORT IShipyard : public IBoatGenerator { public: IShipyard(const CGObjectInstance *O); virtual void getBoatCost(std::vector &cost) const; static const IShipyard *castFrom(const CGObjectInstance *obj); static IShipyard *castFrom(CGObjectInstance *obj); }; class DLL_EXPORT IMarket { virtual int getMarketEfficiency() const =0; public: const CGObjectInstance *o; IMarket(const CGObjectInstance *O); virtual bool allowsTrade(EMarketMode mode) const; virtual int availableUnits(EMarketMode mode, int marketItemSerial) const; //-1 if unlimited virtual std::vector availableItemsIds(EMarketMode mode) const; bool getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode) const; //val1 - how many units of id1 player has to give to receive val2 units std::vector availableModes() const; static const IMarket *castFrom(const CGObjectInstance *obj); }; class DLL_EXPORT CGObjectInstance : public IObjectInterface { protected: void getNameVis(std::string &hname) const; void giveDummyBonus(int heroID, ui8 duration = Bonus::ONE_DAY) const; public: mutable std::string hoverName; int3 pos; //h3m pos si32 ID, subID; //normal ID (this one from OH3 maps ;]) - eg. town=98; hero=34 si32 id;//number of object in CObjectHandler's vector CGDefInfo * defInfo; ui8 animPhaseShift; ui8 tempOwner; ui8 blockVisit; //if non-zero then blocks the tile but is visitable from neighbouring tile virtual ui8 getPassableness() const; //bitmap - if the bit is set the corresponding player can pass through the visitable tiles of object, even if it's blockvis; if not set - default properties from definfo are used virtual int3 getSightCenter() const; //"center" tile from which the sight distance is calculated virtual int getSightRadious() const; //sight distance (should be used if player-owned structure) void getSightTiles(boost::unordered_set &tiles) const; //returns reference to the set int getOwner() const; void setOwner(int ow); int getWidth() const; //returns width of object graphic in tiles int getHeight() const; //returns height of object graphic in tiles bool visitableAt(int x, int y) const; //returns true if object is visitable at location (x, y) form left top tile of image (x, y in tiles) int3 getVisitableOffset() const; //returns (x,y,0) offset to first visitable tile from bottom right obj tile (0,0,0) (h3m pos) int3 visitablePos() const; bool blockingAt(int x, int y) const; //returns true if object is blocking location (x, y) form left top tile of image (x, y in tiles) bool coveringAt(int x, int y) const; //returns true if object covers with picture location (x, y) form left top tile of maximal possible image (8 x 6 tiles) (x, y in tiles) bool hasShadowAt(int x, int y) const;//returns true if object covers with shadow location (x, y) form left top tile of maximal possible image (8 x 6 tiles) (x, y in tiles) std::set getBlockedPos() const; //returns set of positions blocked by this object bool isVisitable() const; //returns true if object is visitable bool operator<(const CGObjectInstance & cmp) const; //screen printing priority comparing void hideTiles(int ourplayer, int radius) const; CGObjectInstance(); virtual ~CGObjectInstance(); //CGObjectInstance(const CGObjectInstance & right); //CGObjectInstance& operator=(const CGObjectInstance & right); virtual const std::string & getHoverText() const; ////////////////////////////////////////////////////////////////////////// void initObj(); void onHeroVisit(const CGHeroInstance * h) const; void setProperty(ui8 what, ui32 val);//synchr virtual void setPropertyDer(ui8 what, ui32 val);//synchr friend class CGameHandler; template void serialize(Handler &h, const int version) { h & hoverName & pos & ID & subID & id & animPhaseShift & tempOwner & blockVisit & defInfo; //definfo is handled by map serializer } }; class CGHeroPlaceholder : public CGObjectInstance { public: //subID stores id of hero type. If it's 0xff then following field is used ui8 power; template void serialize(Handler &h, const int version) { h & static_cast(*this); h & power; } }; class DLL_EXPORT CPlayersVisited: public CGObjectInstance { public: std::set players; //players that visited this object bool hasVisited(ui8 player) const; virtual void setPropertyDer( ui8 what, ui32 val ); template void serialize(Handler &h, const int version) { h & static_cast(*this); h & players; } }; class DLL_EXPORT CArmedInstance: public CGObjectInstance, public CBonusSystemNode, public CCreatureSet { public: BattleInfo *battle; //set to the current battle, if engaged void randomizeArmy(int type); void updateMoraleBonusFromArmy(); void armyChanged() OVERRIDE; ////////////////////////////////////////////////////////////////////////// int valOfGlobalBonuses(CSelector selector) const; //used only for castle interface ??? virtual CBonusSystemNode *whereShouldBeAttached(CGameState *gs); virtual CBonusSystemNode *whatShouldBeAttached(); ////////////////////////////////////////////////////////////////////////// CArmedInstance(); template void serialize(Handler &h, const int version) { h & static_cast(*this); h & static_cast(*this); h & static_cast(*this); } }; class DLL_EXPORT CGHeroInstance : public CArmedInstance, public IBoatGenerator, public CArtifactSet { public: enum SecondarySkill { PATHFINDING = 0, ARCHERY, LOGISTICS, SCOUTING, DIPLOMACY, NAVIGATION, LEADERSHIP, WISDOM, MYSTICISM, LUCK, BALLISTICS, EAGLE_EYE, NECROMANCY, ESTATES, FIRE_MAGIC, AIR_MAGIC, WATER_MAGIC, EARTH_MAGIC, SCHOLAR, TACTICS, ARTILLERY, LEARNING, OFFENCE, ARMORER, INTELLIGENCE, SORCERY, RESISTANCE, FIRST_AID }; ////////////////////////////////////////////////////////////////////////// ui8 moveDir; //format: 123 // 8 4 // 765 mutable ui8 isStanding, tacticFormationEnabled; ////////////////////////////////////////////////////////////////////////// ConstTransitivePtr type; ui64 exp; //experience points si32 level; //current level of hero std::string name; //may be custom std::string biography; //if custom si32 portrait; //may be custom si32 mana; // remaining spell points std::vector > secSkills; //first - ID of skill, second - level of skill (1 - basic, 2 - adv., 3 - expert); if hero has ability (-1, -1) it meansthat it should have default secondary abilities si32 movement; //remaining movement points ui8 sex; ui8 inTownGarrison; // if hero is in town garrison ConstTransitivePtr visitedTown; //set if hero is visiting town or in the town garrison const CGBoat *boat; //set to CGBoat when sailing //std::vector artifacts; //hero's artifacts from bag //std::map artifWorn; //map; positions: 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5 std::set spells; //known spells (spell IDs) struct DLL_EXPORT Patrol { Patrol(){patrolling=false;patrolRadious=-1;}; ui8 patrolling; si32 patrolRadious; template void serialize(Handler &h, const int version) { h & patrolling & patrolRadious; } } patrol; struct DLL_EXPORT HeroSpecial : CBonusSystemNode { bool growthsWithLevel; template void serialize(Handler &h, const int version) { h & static_cast(*this); h & growthsWithLevel; } } speciality; //BonusList bonuses; ////////////////////////////////////////////////////////////////////////// template void serialize(Handler &h, const int version) { h & static_cast(*this); h & static_cast(*this); h & exp & level & name & biography & portrait & mana & secSkills & movement & sex & inTownGarrison & /*artifacts & artifWorn & */spells & patrol & moveDir; h & type & speciality; BONUS_TREE_DESERIALIZATION_FIX //visitied town pointer will be restored by map serialization method } ////////////////////////////////////////////////////////////////////////// // void getParents(TCNodes &out, const CBonusSystemNode *root = NULL) const; // void getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root = NULL) const; ////////////////////////////////////////////////////////////////////////// int3 getSightCenter() const; //"center" tile from which the sight distance is calculated int getSightRadious() const; //sight distance (should be used if player-owned structure) ////////////////////////////////////////////////////////////////////////// int getBoatType() const; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral void getOutOffsets(std::vector &offsets) const; //offsets to obj pos when we boat can be placed ////////////////////////////////////////////////////////////////////////// bool hasSpellbook() const; EAlignment getAlignment() const; const std::string &getBiography() const; bool needsLastStack()const; unsigned int getTileCost(const TerrainTile &dest, const TerrainTile &from) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling unsigned int getLowestCreatureSpeed() const; int3 getPosition(bool h3m = false) const; //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation' si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day bool canWalkOnSea() const; int getCurrentLuck(int stack=-1, bool town=false) const; int getSpellCost(const CSpell *sp) const; //do not use during battles -> bonuses from army would be ignored ui8 getSecSkillLevel(SecondarySkill skill) const; //0 - no skill void setSecSkillLevel(SecondarySkill which, int val, bool abs);// abs == 0 - changes by value; 1 - sets to value int maxMovePoints(bool onLand) const; // const CArtifact* getArtAtPos(ui16 pos) const; //NULL - no artifact // const CArtifact * getArt(int pos) const; // si32 getArtPos(int aid) const; //looks for equipped artifact with given ID and returns its slot ID or -1 if none(if more than one such artifact lower ID is returned) // bool hasArt(ui32 aid) const; //checks if hero possess artifact of given id (either in backack or worn) //int getSpellSecLevel(int spell) const; //returns level of secondary ability (fire, water, earth, air magic) known to this hero and applicable to given spell; -1 if error static int3 convertPosition(int3 src, bool toh3m); //toh3m=true: manifest->h3m; toh3m=false: h3m->manifest double getHeroStrength() const; ui64 getTotalStrength() const; expType calculateXp(expType exp) const; //apply learning skill ui8 getSpellSchoolLevel(const CSpell * spell, int *outSelectedSchool = NULL) const; //returns level on which given spell would be cast by this hero (0 - none, 1 - basic etc); optionally returns number of selected school by arg - 0 - air magic, 1 - fire magic, 2 - water magic, 3 - earth magic, bool canCastThisSpell(const CSpell * spell) const; //determines if this hero can cast given spell; takes into account existing spell in spellbook, existing spellbook and artifact bonuses CStackBasicDescriptor calculateNecromancy (const BattleResult &battleResult) const; void showNecromancyDialog(const CStackBasicDescriptor &raisedStack) const; ////////////////////////////////////////////////////////////////////////// void initHero(); void initHero(int SUBID); void putArtifact(ui16 pos, CArtifactInstance *art); void putInBackpack(CArtifactInstance *art); void initExp(); void initArmy(IArmyDescriptor *dst = NULL); void giveArtifact (ui32 aid); void initHeroDefInfo(); void pushPrimSkill(int which, int val); void UpdateSpeciality(); void updateSkill(int which, int val); CGHeroInstance(); virtual ~CGHeroInstance(); ////////////////////////////////////////////////////////////////////////// virtual CBonusSystemNode *whereShouldBeAttached(CGameState *gs) OVERRIDE; virtual std::string nodeName() const OVERRIDE; void deserializationFix(); void setPropertyDer(ui8 what, ui32 val);//synchr void initObj(); void onHeroVisit(const CGHeroInstance * h) const; }; class DLL_EXPORT CSpecObjInfo { public: virtual ~CSpecObjInfo(){}; }; class DLL_EXPORT CCreGenObjInfo : public CSpecObjInfo { public: unsigned char player; //owner bool asCastle; ui32 identifier; unsigned char castles[2]; //allowed castles }; class DLL_EXPORT CCreGen2ObjInfo : public CSpecObjInfo { public: unsigned char player; //owner bool asCastle; ui32 identifier; unsigned char castles[2]; //allowed castles unsigned char minLevel, maxLevel; //minimal and maximal level of creature in dwelling: <0, 6> }; class DLL_EXPORT CCreGen3ObjInfo : public CSpecObjInfo { public: unsigned char player; //owner unsigned char minLevel, maxLevel; //minimal and maximal level of creature in dwelling: <0, 6> }; class DLL_EXPORT CGDwelling : public CArmedInstance { public: CSpecObjInfo * info; //h3m info about dewlling std::vector > > creatures; //creatures[level] -> template void serialize(Handler &h, const int version) { h & static_cast(*this) & creatures; } void initObj(); void setProperty(ui8 what, ui32 val); void onHeroVisit(const CGHeroInstance * h) const; void newTurn() const; void heroAcceptsCreatures(const CGHeroInstance *h, ui32 answer) const; void fightOver(const CGHeroInstance *h, BattleResult *result) const; void wantsFight(const CGHeroInstance *h, ui32 answer) const; }; class DLL_EXPORT CGVisitableOPH : public CGObjectInstance //objects visitable only once per hero { public: std::set visitors; //ids of heroes who have visited this obj si8 ttype; //tree type - used only by trees of knowledge: 0 - give level for free; 1 - take 2000 gold; 2 - take 10 gems const std::string & getHoverText() const; void setPropertyDer(ui8 what, ui32 val);//synchr void onHeroVisit(const CGHeroInstance * h) const; void onNAHeroVisit(int heroID, bool alreadyVisited) const; void initObj(); void treeSelected(int heroID, int resType, int resVal, expType expVal, ui32 result) const; //handle player's anwer to the Tree of Knowledge dialog void schoolSelected(int heroID, ui32 which) const; void arenaSelected(int heroID, int primSkill) const; template void serialize(Handler &h, const int version) { h & static_cast(*this); h & visitors & ttype; } }; class DLL_EXPORT CGTownBuilding : public IObjectInterface { ///basic class for town structures handled as map objects public: si32 ID; //from buildig list si32 id; //identifies its index on towns vector CGTownInstance *town; template void serialize(Handler &h, const int version) { h & ID & id; } }; class DLL_EXPORT COPWBonus : public CGTownBuilding {///used for OPW bonusing structures public: std::set visitors; void setProperty(ui8 what, ui32 val); void onHeroVisit (const CGHeroInstance * h) const; COPWBonus (int index, CGTownInstance *TOWN); COPWBonus (){ID = 0; town = NULL;}; template void serialize(Handler &h, const int version) { h & static_cast(*this); h & visitors; } }; class DLL_EXPORT CTownBonus : public CGTownBuilding { ///used for one-time bonusing structures ///feel free to merge inheritance tree public: std::set visitors; void setProperty(ui8 what, ui32 val); void onHeroVisit (const CGHeroInstance * h) const; CTownBonus (int index, CGTownInstance *TOWN); CTownBonus (){ID = 0; town = NULL;}; template void serialize(Handler &h, const int version) { h & static_cast(*this); h & visitors; } }; class DLL_EXPORT CTownAndVisitingHero : public CBonusSystemNode { public: CTownAndVisitingHero(); }; struct DLL_EXPORT GrowthInfo { struct Entry { int count; std::string description; Entry(const std::string &format, int _count); Entry(int subID, Buildings::EBuilding building, int _count); }; std::vector entries; int totalGrowth() const; }; class DLL_EXPORT CGTownInstance : public CGDwelling, public IShipyard, public IMarket { public: CTownAndVisitingHero townAndVis; CTown * town; std::string name; // name of town si32 builded; //how many buildings has been built this turn si32 destroyed; //how many buildings has been destroyed this turn ConstTransitivePtr garrisonHero, visitingHero; ui32 identifier; //special identifier from h3m (only > RoE maps) si32 alignment; std::set forbiddenBuildings, builtBuildings; std::vector bonusingBuildings; std::vector possibleSpells, obligatorySpells; std::vector > spells; //spells[level] -> vector of spells, first will be available in guild std::list events; std::pair bonusValue;//var to store town bonuses (rampart = resources from mystic pond); ////////////////////////////////////////////////////////////////////////// static std::vector merchantArtifacts; //vector of artifacts available at Artifact merchant, NULLs possible (for making empty space when artifact is bought) static std::vector universitySkills;//skills for university of magic template void serialize(Handler &h, const int version) { h & static_cast(*this); h & name & builded & destroyed & identifier & alignment & forbiddenBuildings & builtBuildings & bonusValue & possibleSpells & obligatorySpells & spells & /*strInfo & */events & bonusingBuildings; for (std::vector::iterator i = bonusingBuildings.begin(); i!=bonusingBuildings.end(); i++) (*i)->town = this; h & town & townAndVis; BONUS_TREE_DESERIALIZATION_FIX //garrison/visiting hero pointers will be restored in the map serialization } ////////////////////////////////////////////////////////////////////////// virtual CBonusSystemNode *whatShouldBeAttached() OVERRIDE; std::string nodeName() const OVERRIDE; void deserializationFix(); void recreateBuildingsBonuses(); bool addBonusIfBuilt(int building, int type, int val, IPropagator *prop, int subtype = -1); //returns true if building is built and bonus has been added bool addBonusIfBuilt(int building, int type, int val, int subtype = -1); //convienence version of above void setVisitingHero(CGHeroInstance *h); void setGarrisonedHero(CGHeroInstance *h); const CArmedInstance *getUpperArmy() const; //garrisoned hero if present or the town itself // void getParents(TCNodes &out, const CBonusSystemNode *root = NULL) const; // void getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root = NULL) const; ////////////////////////////////////////////////////////////////////////// ui8 getPassableness() const; //bitmap - if the bit is set the corresponding player can pass through the visitable tiles of object, even if it's blockvis; if not set - default properties from definfo are used int3 getSightCenter() const; //"center" tile from which the sight distance is calculated int getSightRadious() const; //returns sight distance int getBoatType() const; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral void getOutOffsets(std::vector &offsets) const; //offsets to obj pos when we boat can be placed int getMarketEfficiency() const; //=market count bool allowsTrade(EMarketMode mode) const; std::vector availableItemsIds(EMarketMode mode) const; void setPropertyDer(ui8 what, ui32 val); void newTurn() const; ////////////////////////////////////////////////////////////////////////// bool needsLastStack() const; int fortLevel() const; //0 - none, 1 - fort, 2 - citadel, 3 - castle int hallLevel() const; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol int mageGuildLevel() const; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol bool creatureDwelling(const int & level, bool upgraded=false) const; int getHordeLevel(const int & HID) const; //HID - 0 or 1; returns creature level or -1 if that horde structure is not present int creatureGrowth(const int & level) const; GrowthInfo getGrowthInfo(int level) const; bool hasFort() const; bool hasCapitol() const; int dailyIncome() const; //calculates daily income of this town int spellsAtLevel(int level, bool checkGuild) const; //levels are counted from 1 (1 - 5) void removeCapitols (ui8 owner) const; bool armedGarrison() const; //true if town has creatures in garrison or garrisoned hero CGTownInstance(); virtual ~CGTownInstance(); ////////////////////////////////////////////////////////////////////////// void fightOver(const CGHeroInstance *h, BattleResult *result) const; void onHeroVisit(const CGHeroInstance * h) const; void onHeroLeave(const CGHeroInstance * h) const; void initObj(); }; class DLL_EXPORT CGPandoraBox : public CArmedInstance { public: std::string message; //gained things: ui32 gainedExp; si32 manaDiff; //amount of gained / lost mana si32 moraleDiff; //morale modifier si32 luckDiff; //luck modifier std::vector resources;//gained / lost resources std::vector primskills;//gained / lost resources std::vector abilities; //gained abilities std::vector abilityLevels; //levels of gained abilities std::vector artifacts; //gained artifacts std::vector spells; //gained spells CCreatureSet creatures; //gained creatures void initObj(); void onHeroVisit(const CGHeroInstance * h) const; void open (const CGHeroInstance * h, ui32 accept) const; void endBattle(const CGHeroInstance *h, BattleResult *result) const; void giveContents(const CGHeroInstance *h, bool afterBattle) const; void getText( InfoWindow &iw, bool &afterBattle, int val, int negative, int positive, const CGHeroInstance * h ) const; void getText( InfoWindow &iw, bool &afterBattle, int text, const CGHeroInstance * h ) const; template void serialize(Handler &h, const int version) { h & static_cast(*this); h & message & gainedExp & manaDiff & moraleDiff & luckDiff & resources & primskills & abilities & abilityLevels & artifacts & spells & creatures; } }; class DLL_EXPORT CGEvent : public CGPandoraBox //event objects { public: ui8 removeAfterVisit; //true if event is removed after occurring ui8 availableFor; //players whom this event is available for ui8 computerActivate; //true if computre player can activate this event ui8 humanActivate; //true if human player can activate this event template void serialize(Handler &h, const int version) { h & static_cast(*this); h & removeAfterVisit & availableFor & computerActivate & humanActivate; } void onHeroVisit(const CGHeroInstance * h) const; void activated(const CGHeroInstance * h) const; }; class DLL_EXPORT CGCreature : public CArmedInstance //creatures on map { public: ui32 identifier; //unique code for this monster (used in missions) si8 character; //chracter of this set of creatures (0 - the most friendly, 4 - the most hostile) => on init changed to 0 (compliant) - 10 value (savage) std::string message; //message printed for attacking hero std::vector resources; //[res_id], resources given to hero that has won with monsters si32 gainedArtifact; //ID of artifact gained to hero, -1 if none ui8 neverFlees; //if true, the troops will never flee ui8 notGrowingTeam; //if true, number of units won't grow ui64 temppower; //used to handle fractional stack growth for tiny stacks void fight(const CGHeroInstance *h) const; void onHeroVisit(const CGHeroInstance * h) const; const std::string & getHoverText() const; void flee( const CGHeroInstance * h ) const; void endBattle(BattleResult *result) const; void fleeDecision(const CGHeroInstance *h, ui32 pursue) const; void joinDecision(const CGHeroInstance *h, int cost, ui32 accept) const; void initObj(); void newTurn() const; void setPropertyDer(ui8 what, ui32 val); int takenAction(const CGHeroInstance *h, bool allowJoin=true) const; //action on confrontation: -2 - fight, -1 - flee, >=0 - will join for given value of gold (may be 0) struct DLL_EXPORT RestoredCreature // info about merging stacks after battle back into one { si32 basicType; template void serialize(Handler &h, const int version) { h & basicType; } } restore; template void serialize(Handler &h, const int version) { h & static_cast(*this); h & identifier & character & message & resources & gainedArtifact & neverFlees & notGrowingTeam & temppower & restore; } }; class DLL_EXPORT CGSignBottle : public CGObjectInstance //signs and ocean bottles { public: std::string message; void onHeroVisit(const CGHeroInstance * h) const; void initObj(); template void serialize(Handler &h, const int version) { h & static_cast(*this); h & message; } }; class DLL_EXPORT CGSeerHut : public CArmedInstance, public CQuest //army is used when giving reward { public: ui8 rewardType; //type of reward: 0 - no reward; 1 - experience; 2 - mana points; 3 - morale bonus; 4 - luck bonus; 5 - resources; 6 - main ability bonus (attak, defence etd.); 7 - secondary ability gain; 8 - artifact; 9 - spell; 10 - creature si32 rID; //reward ID si32 rVal; //reward value ui8 textOption; //store randomized mission write-ups rather than entire string (?) std::string seerName; //following field are used only for kill creature/hero missions, the original objects became inaccessible after their removal, so we need to store info needed for messages / hover text //TODO? organize CStackBasicDescriptor stackToKill; ui8 stackDirection; std::string heroName; //backup of hero name si32 heroPortrait; void initObj(); const std::string & getHoverText() const; void setPropertyDer (ui8 what, ui32 val); int checkDirection() const; //calculates the region of map where monster is placed void newTurn() const; void onHeroVisit (const CGHeroInstance * h) const; void finishQuest (const CGHeroInstance * h, ui32 accept) const; //common for both objects void completeQuest (const CGHeroInstance * h) const; const CGHeroInstance *getHeroToKill(bool allowNull = false) const; const CGCreature *getCreatureToKill(bool allowNull = false) const; void addReplacements(MetaString &out, const std::string &base) const; template void serialize(Handler &h, const int version) { h & static_cast(*this) & static_cast(*this); h & rewardType & rID & rVal & textOption & seerName; h & stackToKill & stackDirection & heroName & heroPortrait; } }; class DLL_EXPORT CGQuestGuard : public CGSeerHut { public: void initObj(); void completeQuest (const CGHeroInstance * h) const; template void serialize(Handler &h, const int version) { h & static_cast(*this); } }; class DLL_EXPORT CGWitchHut : public CPlayersVisited { public: std::vector allowedAbilities; ui32 ability; const std::string & getHoverText() const; void onHeroVisit(const CGHeroInstance * h) const; void initObj(); template void serialize(Handler &h, const int version) { h & static_cast(*this); h & allowedAbilities & ability; } }; class DLL_EXPORT CGScholar : public CGObjectInstance { public: ui8 bonusType; //255 - random, 0 - primary skill, 1 - secondary skill, 2 - spell ui16 bonusID; //ID of skill/spell void giveAnyBonus(const CGHeroInstance * h) const; void onHeroVisit(const CGHeroInstance * h) const; void initObj(); template void serialize(Handler &h, const int version) { h & static_cast(*this); h & bonusType & bonusID; } }; class DLL_EXPORT CGGarrison : public CArmedInstance { public: ui8 removableUnits; ui8 getPassableness() const; void onHeroVisit (const CGHeroInstance *h) const; void fightOver (const CGHeroInstance *h, BattleResult *result) const; template void serialize(Handler &h, const int version) { h & static_cast(*this); h & removableUnits; } }; class DLL_EXPORT CGArtifact : public CArmedInstance { public: CArtifactInstance *storedArtifact; std::string message; void onHeroVisit(const CGHeroInstance * h) const; void fightForArt(ui32 agreed, const CGHeroInstance *h) const; void endBattle(BattleResult *result, const CGHeroInstance *h) const; void pick( const CGHeroInstance * h ) const; void initObj(); template void serialize(Handler &h, const int version) { h & static_cast(*this); h & message & storedArtifact; } }; class DLL_EXPORT CGResource : public CArmedInstance { public: ui32 amount; //0 if random std::string message; void onHeroVisit(const CGHeroInstance * h) const; void collectRes(int player) const; void initObj(); void fightForRes(ui32 agreed, const CGHeroInstance *h) const; void endBattle(BattleResult *result, const CGHeroInstance *h) const; template void serialize(Handler &h, const int version) { h & static_cast(*this); h & amount & message; } }; class DLL_EXPORT CGPickable : public CGObjectInstance //campfire, treasure chest, Flotsam, Shipwreck Survivor, Sea Chest { public: ui32 type, val1, val2; void onHeroVisit(const CGHeroInstance * h) const; void initObj(); void chosen(int which, int heroID) const; template void serialize(Handler &h, const int version) { h & static_cast(*this); h & type & val1 & val2; } }; class DLL_EXPORT CGShrine : public CPlayersVisited { public: ui8 spell; //number of spell or 255 if random void onHeroVisit(const CGHeroInstance * h) const; void initObj(); const std::string & getHoverText() const; template void serialize(Handler &h, const int version) { h & static_cast(*this);; h & spell; } }; class DLL_EXPORT CGMine : public CArmedInstance { public: ui8 producedResource; ui32 producedQuantity; void offerLeavingGuards(const CGHeroInstance *h) const; void endBattle(BattleResult *result, ui8 attackingPlayer) const; void fight(ui32 agreed, const CGHeroInstance *h) const; void onHeroVisit(const CGHeroInstance * h) const; void flagMine(ui8 player) const; void newTurn() const; void initObj(); template void serialize(Handler &h, const int version) { h & static_cast(*this); h & producedResource & producedQuantity; } ui32 defaultResProduction(); }; class DLL_EXPORT CGVisitableOPW : public CGObjectInstance //objects visitable OPW { public: ui8 visited; //true if object has been visited this week void setPropertyDer(ui8 what, ui32 val);//synchr void onHeroVisit(const CGHeroInstance * h) const; void newTurn() const; template void serialize(Handler &h, const int version) { h & static_cast(*this); h & visited; } }; class DLL_EXPORT CGTeleport : public CGObjectInstance //teleports and subterranean gates { public: static std::map > > objs; //teleports: map[ID][subID] => vector of ids static std::vector > gates; //subterranean gates: pairs of ids void onHeroVisit(const CGHeroInstance * h) const; void initObj(); static void postInit(); template void serialize(Handler &h, const int version) { h & static_cast(*this); } }; class DLL_EXPORT CGBonusingObject : public CGObjectInstance //objects giving bonuses to luck/morale/movement { public: void onHeroVisit(const CGHeroInstance * h) const; const std::string & getHoverText() const; void initObj(); template void serialize(Handler &h, const int version) { h & static_cast(*this); } }; class DLL_EXPORT CGMagicSpring : public CGVisitableOPW {///unfortunatelly, this one is quite different than others public: void onHeroVisit(const CGHeroInstance * h) const; const std::string & getHoverText() const; template void serialize(Handler &h, const int version) { h & static_cast(*this); h & visited; } }; class DLL_EXPORT CGMagicWell : public CGObjectInstance //objects giving bonuses to luck/morale/movement { public: void onHeroVisit(const CGHeroInstance * h) const; const std::string & getHoverText() const; template void serialize(Handler &h, const int version) { h & static_cast(*this); } }; class DLL_EXPORT CGSirens : public CGObjectInstance { public: void onHeroVisit(const CGHeroInstance * h) const; const std::string & getHoverText() const; void initObj(); template void serialize(Handler &h, const int version) { h & static_cast(*this); } }; class DLL_EXPORT CGObservatory : public CGObjectInstance //Redwood observatory { public: void onHeroVisit(const CGHeroInstance * h) const; template void serialize(Handler &h, const int version) { h & static_cast(*this); } }; class DLL_EXPORT CGKeys : public CGObjectInstance //Base class for Keymaster and guards { public: static std::map > playerKeyMap; //[players][keysowned] //SubID 0 - lightblue, 1 - green, 2 - red, 3 - darkblue, 4 - brown, 5 - purple, 6 - white, 7 - black void setPropertyDer (ui8 what, ui32 val); bool wasMyColorVisited (int player) const; template void serialize(Handler &h, const int version) { h & static_cast(*this); } }; class DLL_EXPORT CGKeymasterTent : public CGKeys { public: void onHeroVisit(const CGHeroInstance * h) const; const std::string & getHoverText() const; template void serialize(Handler &h, const int version) { h & static_cast(*this); } }; class DLL_EXPORT CGBorderGuard : public CGKeys { public: void initObj(); const std::string & getHoverText() const; void onHeroVisit(const CGHeroInstance * h) const; void openGate(const CGHeroInstance *h, ui32 accept) const; template void serialize(Handler &h, const int version) { h & static_cast(*this); h & blockVisit; } }; class DLL_EXPORT CGBorderGate : public CGBorderGuard //not fully imlemented, waiting for garrison { public: void onHeroVisit(const CGHeroInstance * h) const; ui8 getPassableness() const; }; class DLL_EXPORT CGBoat : public CGObjectInstance { public: ui8 direction; const CGHeroInstance *hero; //hero on board void initObj(); CGBoat() { hero = NULL; direction = 4; } template void serialize(Handler &h, const int version) { h & static_cast(*this) & direction; } }; class DLL_EXPORT CGOnceVisitable : public CPlayersVisited ///wagon, corpse, lean to, warriors tomb { public: ui8 artOrRes; //0 - nothing; 1 - artifact; 2 - resource ui32 bonusType, //id of res or artifact bonusVal; //resource amount (or not used) void onHeroVisit(const CGHeroInstance * h) const; const std::string & getHoverText() const; void initObj(); void searchTomb(const CGHeroInstance *h, ui32 accept) const; template void serialize(Handler &h, const int version) { h & static_cast(*this);; h & artOrRes & bonusType & bonusVal; } }; class DLL_EXPORT CBank : public CArmedInstance { public: int index; //banks have unusal numbering - see ZCRBANK.txt and initObj() BankConfig *bc; float multiplier; //for improved banks script std::vector artifacts; //fixed and deterministic ui32 daycounter; void initObj(); const std::string & getHoverText() const; void setPropertyDer (ui8 what, ui32 val); void initialize() const; void reset(ui16 var1); void newTurn() const; virtual void onHeroVisit (const CGHeroInstance * h) const; virtual void fightGuards (const CGHeroInstance *h, ui32 accept) const; virtual void endBattle (const CGHeroInstance *h, const BattleResult *result) const; template void serialize(Handler &h, const int version) { h & static_cast(*this); h & index & multiplier & artifacts & daycounter & bc; } }; class DLL_EXPORT CGPyramid : public CBank { public: ui16 spell; void initObj(); const std::string & getHoverText() const; void newTurn() const {}; //empty, no reset void onHeroVisit (const CGHeroInstance * h) const; void endBattle (const CGHeroInstance *h, const BattleResult *result) const; template void serialize(Handler &h, const int version) { h & static_cast(*this); h & spell; } }; class CGShipyard : public CGObjectInstance, public IShipyard { public: void getOutOffsets(std::vector &offsets) const; //offsets to obj pos when we boat can be placed CGShipyard(); void onHeroVisit(const CGHeroInstance * h) const; }; class DLL_EXPORT CGMagi : public CGObjectInstance { public: static std::map > eyelist; //[subID][id], supports multiple sets as in H5 void initObj(); void onHeroVisit(const CGHeroInstance * h) const; template void serialize(Handler &h, const int version) { h & static_cast(*this); } }; class DLL_EXPORT CCartographer : public CPlayersVisited { ///behaviour varies depending on surface and floor public: void onHeroVisit( const CGHeroInstance * h ) const; void buyMap (const CGHeroInstance *h, ui32 accept) const; template void serialize(Handler &h, const int version) { h & static_cast(*this); } }; class DLL_EXPORT CGDenOfthieves : public CGObjectInstance { void onHeroVisit (const CGHeroInstance * h) const; }; class DLL_EXPORT CGObelisk : public CPlayersVisited { public: static ui8 obeliskCount; //how many obelisks are on map static std::map visited; //map: team_id => how many obelisks has been visited void setPropertyDer (ui8 what, ui32 val); void onHeroVisit(const CGHeroInstance * h) const; void initObj(); const std::string & getHoverText() const; template void serialize(Handler &h, const int version) { h & static_cast(*this); } }; class DLL_EXPORT CGLighthouse : public CGObjectInstance { public: void onHeroVisit(const CGHeroInstance * h) const; void initObj(); const std::string & getHoverText() const; template void serialize(Handler &h, const int version) { h & static_cast(*this); } void giveBonusTo( ui8 player ) const; }; class DLL_EXPORT CGMarket : public CGObjectInstance, public IMarket { public: CGMarket(); void onHeroVisit(const CGHeroInstance * h) const; //open trading window int getMarketEfficiency() const; bool allowsTrade(EMarketMode mode) const; int availableUnits(EMarketMode mode, int marketItemSerial) const; //-1 if unlimited std::vector availableItemsIds(EMarketMode mode) const; template void serialize(Handler &h, const int version) { h & static_cast(*this); } }; class DLL_EXPORT CGBlackMarket : public CGMarket { public: std::vector artifacts; //available artifacts void newTurn() const; //reset artifacts for black market every month std::vector availableItemsIds(EMarketMode mode) const; template void serialize(Handler &h, const int version) { h & static_cast(*this); h & artifacts; } }; class DLL_EXPORT CGUniversity : public CGMarket { public: std::vector skills; //available skills std::vector availableItemsIds(EMarketMode mode) const; void initObj();//set skills for trade void onHeroVisit(const CGHeroInstance * h) const; //open window template void serialize(Handler &h, const int version) { h & static_cast(*this); h & skills; } }; struct BankConfig { BankConfig() {level = chance = upgradeChance = combatValue = value = rewardDifficulty = easiest = 0; }; ui8 level; //1 - 4, how hard the battle will be ui8 chance; //chance for this level being chosen ui8 upgradeChance; //chance for creatures to be in upgraded versions std::vector< std::pair > guards; //creature ID, amount ui32 combatValue; //how hard are guards of this level std::vector resources; //resources given in case of victory std::vector< std::pair > creatures; //creatures granted in case of victory (creature ID, amount) std::vector artifacts; //number of artifacts given in case of victory [0] -> treasure, [1] -> minor [2] -> major [3] -> relic ui32 value; //overall value of given things ui32 rewardDifficulty; //proportion of reward value to difficulty of guards; how profitable is this creature Bank config ui16 easiest; //?!? template void serialize(Handler &h, const int version) { h & level & chance & upgradeChance & guards & combatValue & resources & creatures & artifacts & value & rewardDifficulty & easiest; } }; class DLL_EXPORT CObjectHandler { public: std::vector cregens; //type 17. dwelling subid -> creature ID std::map > > banksInfo; //[index][preset] std::map creBanksNames; //[crebank index] -> name of this creature bank std::vector resVals; //default values of resources in gold void loadObjects(); void readConfigLine(std::ifstream &istr, int g); template void serialize(Handler &h, const int version) { h & cregens & banksInfo & creBanksNames & resVals; } }; #endif // __COBJECTHANDLER_H__