2012-12-19 17:54:10 +03:00
/*
* CCreatureSet . 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
*
*/
2017-07-13 10:26:03 +02:00
# pragma once
2023-05-01 19:29:53 +02:00
# include "bonuses/Bonus.h"
2023-04-30 16:35:15 +02:00
# include "bonuses/CBonusSystemNode.h"
2017-07-13 10:26:03 +02:00
# include "GameConstants.h"
# include "CArtHandler.h"
2023-06-22 16:08:16 +02:00
# include "CArtifactInstance.h"
2022-09-26 02:50:08 +02:00
# include "CCreatureHandler.h"
2017-07-13 10:26:03 +02:00
2023-04-05 17:56:28 +02:00
# include <vcmi/Entity.h>
2022-07-26 15:07:42 +02:00
VCMI_LIB_NAMESPACE_BEGIN
2016-01-15 19:24:17 +02:00
class JsonNode ;
2010-04-02 05:23:22 +03:00
class CCreature ;
class CGHeroInstance ;
2010-05-02 21:20:26 +03:00
class CArmedInstance ;
2012-01-30 19:07:52 +03:00
class CCreatureArtifactSet ;
2016-02-22 01:37:19 +02:00
class JsonSerializeFormat ;
2010-04-02 05:23:22 +03:00
2011-12-14 00:23:17 +03:00
class DLL_LINKAGE CStackBasicDescriptor
2010-11-22 02:34:46 +02:00
{
public :
2023-03-16 20:48:37 +02:00
const CCreature * type = nullptr ;
TQuantity count = - 1 ; //exact quantity or quantity ID from CCreature::getQuantityID when getting info about enemy army
2010-05-02 21:20:26 +03:00
2010-11-22 02:34:46 +02:00
CStackBasicDescriptor ( ) ;
2023-03-13 23:26:44 +02:00
CStackBasicDescriptor ( const CreatureID & id , TQuantity Count ) ;
2010-12-06 01:10:02 +02:00
CStackBasicDescriptor ( const CCreature * c , TQuantity Count ) ;
2016-10-29 17:00:12 +02:00
virtual ~ CStackBasicDescriptor ( ) = default ;
2010-11-22 02:34:46 +02:00
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
const Creature * getType ( ) const ;
TQuantity getCount ( ) const ;
2016-11-13 12:38:42 +02:00
virtual void setType ( const CCreature * c ) ;
2010-11-22 02:34:46 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2022-09-26 02:50:08 +02:00
if ( h . saving )
{
2023-04-05 02:26:29 +02:00
auto idNumber = type ? type - > getId ( ) : CreatureID ( CreatureID : : NONE ) ;
2022-09-26 02:50:08 +02:00
h & idNumber ;
}
else
{
CreatureID idNumber ;
h & idNumber ;
if ( idNumber ! = CreatureID : : NONE )
2023-08-20 17:16:00 +02:00
setType ( dynamic_cast < const CCreature * > ( VLC - > creatures ( ) - > getById ( idNumber ) ) ) ;
2022-09-26 02:50:08 +02:00
else
type = nullptr ;
}
2017-07-31 15:35:42 +02:00
h & count ;
2010-11-22 02:34:46 +02:00
}
2016-01-15 19:24:17 +02:00
2016-11-13 12:38:42 +02:00
void serializeJson ( JsonSerializeFormat & handler ) ;
2010-11-22 02:34:46 +02:00
} ;
2023-04-30 17:21:02 +02:00
class DLL_LINKAGE CStackInstance : public CBonusSystemNode , public CStackBasicDescriptor , public CArtifactSet , public ACreature
2010-04-02 05:23:22 +03:00
{
2012-04-22 20:38:36 +03:00
protected :
2010-11-27 03:46:19 +02:00
const CArmedInstance * _armyObj ; //stack must be part of some army, army must be part of some object
2021-03-01 21:38:50 +02:00
2010-04-02 05:23:22 +03:00
public :
2023-04-02 18:56:10 +02:00
struct RandomStackInfo
{
uint8_t level ;
uint8_t upgrade ;
} ;
// helper variable used during loading map, when object (hero or town) have creatures that must have same alignment.
2023-04-16 19:42:56 +02:00
std : : optional < RandomStackInfo > randomStack ;
2010-05-02 21:20:26 +03:00
2010-11-27 03:46:19 +02:00
const CArmedInstance * const & armyObj ; //stack must be part of some army, army must be part of some object
2012-09-23 21:01:04 +03:00
TExpType experience ; //commander needs same amount of exp as hero
2010-04-02 05:23:22 +03:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2010-05-02 21:20:26 +03:00
h & static_cast < CBonusSystemNode & > ( * this ) ;
2010-11-22 02:34:46 +02:00
h & static_cast < CStackBasicDescriptor & > ( * this ) ;
2012-04-14 05:20:22 +03:00
h & static_cast < CArtifactSet & > ( * this ) ;
2017-07-31 15:35:42 +02:00
h & _armyObj ;
h & experience ;
2011-02-22 11:47:25 +02:00
BONUS_TREE_DESERIALIZATION_FIX
2010-04-02 05:23:22 +03:00
}
2016-11-13 12:38:42 +02:00
void serializeJson ( JsonSerializeFormat & handler ) ;
2016-01-15 19:24:17 +02:00
2010-05-02 21:20:26 +03:00
//overrides CBonusSystemNode
2016-09-19 23:36:35 +02:00
std : : string bonusToString ( const std : : shared_ptr < Bonus > & bonus , bool description ) const override ; // how would bonus description look for this particular type of node
2023-03-13 23:26:44 +02:00
std : : string bonusToGraphics ( const std : : shared_ptr < Bonus > & bonus ) const ; //file name of graphics from StackSkills , in future possibly others
2010-05-02 21:20:26 +03:00
2023-04-09 03:03:47 +02:00
//IConstBonusProvider
2023-04-05 17:56:28 +02:00
const IBonusBearer * getBonusBearer ( ) const override ;
2023-04-09 03:03:47 +02:00
//INativeTerrainProvider
2023-04-05 17:56:28 +02:00
FactionID getFaction ( ) const override ;
2012-04-04 20:41:55 +03:00
virtual ui64 getPower ( ) const ;
2023-01-14 16:55:08 +02:00
CCreature : : CreatureQuantityId getQuantityID ( ) const ;
2010-07-31 03:26:34 +03:00
std : : string getQuantityTXT ( bool capitalized = true ) const ;
2012-04-04 20:41:55 +03:00
virtual int getExpRank ( ) const ;
2013-03-30 23:09:50 +03:00
virtual int getLevel ( ) const ; //different for regular stack and commander
2013-02-11 02:24:57 +03:00
CreatureID getCreatureID ( ) const ; //-1 if not available
2011-10-22 10:05:57 +03:00
std : : string getName ( ) const ; //plural or singular
2012-04-22 20:38:36 +03:00
virtual void init ( ) ;
2010-04-02 05:23:22 +03:00
CStackInstance ( ) ;
2023-03-13 23:26:44 +02:00
CStackInstance ( const CreatureID & id , TQuantity count , bool isHypothetic = false ) ;
2021-03-01 21:38:50 +02:00
CStackInstance ( const CCreature * cre , TQuantity count , bool isHypothetic = false ) ;
2023-03-13 23:26:44 +02:00
virtual ~ CStackInstance ( ) = default ;
2010-12-06 01:10:02 +02:00
2023-03-13 23:26:44 +02:00
void setType ( const CreatureID & creID ) ;
2016-11-13 12:38:42 +02:00
void setType ( const CCreature * c ) override ;
2010-11-22 02:34:46 +02:00
void setArmyObj ( const CArmedInstance * ArmyObj ) ;
2012-09-23 21:01:04 +03:00
virtual void giveStackExp ( TExpType exp ) ;
2010-11-27 03:46:19 +02:00
bool valid ( bool allowUnrandomized ) const ;
2016-11-13 12:38:42 +02:00
void putArtifact ( ArtifactPosition pos , CArtifactInstance * art ) override ; //from CArtifactSet
2023-05-23 19:24:55 +02:00
void removeArtifact ( ArtifactPosition pos ) override ;
2013-06-26 14:18:27 +03:00
ArtBearer : : ArtBearer bearerType ( ) const override ; //from CArtifactSet
virtual std : : string nodeName ( ) const override ; //from CBonusSystemnode
2011-02-04 16:58:14 +02:00
void deserializationFix ( ) ;
2021-09-12 13:30:54 +02:00
PlayerColor getOwner ( ) const override ;
2010-04-02 05:23:22 +03:00
} ;
2012-04-04 20:41:55 +03:00
class DLL_LINKAGE CCommanderInstance : public CStackInstance
{
2012-04-22 20:38:36 +03:00
public :
2012-04-04 20:41:55 +03:00
//TODO: what if Commander is not a part of creature set?
//commander class is determined by its base creature
2016-10-02 16:57:26 +02:00
ui8 alive ; //maybe change to bool when breaking save compatibility?
2012-05-18 17:02:27 +03:00
ui8 level ; //required only to count callbacks
2012-04-04 20:41:55 +03:00
std : : string name ; // each Commander has different name
2012-05-18 17:02:27 +03:00
std : : vector < ui8 > secondarySkills ; //ID -> level
2012-05-18 22:44:15 +03:00
std : : set < ui8 > specialSKills ;
2012-04-04 20:41:55 +03:00
//std::vector <CArtifactInstance *> arts;
2013-06-26 14:18:27 +03:00
void init ( ) override ;
2012-04-22 20:38:36 +03:00
CCommanderInstance ( ) ;
2023-03-13 23:26:44 +02:00
CCommanderInstance ( const CreatureID & id ) ;
2012-05-01 11:52:22 +03:00
void setAlive ( bool alive ) ;
2015-10-12 15:47:10 +02:00
void giveStackExp ( TExpType exp ) override ;
2012-05-07 15:54:22 +03:00
void levelUp ( ) ;
2012-04-04 20:41:55 +03:00
2013-04-20 14:34:01 +03:00
bool gainsLevel ( ) const ; //true if commander has lower level than should upon his experience
2015-10-12 15:47:10 +02:00
ui64 getPower ( ) const override { return 0 ; } ;
int getExpRank ( ) const override ;
2016-01-15 19:24:17 +02:00
int getLevel ( ) const override ;
2013-06-26 14:18:27 +03:00
ArtBearer : : ArtBearer bearerType ( ) const override ; //from CArtifactSet
2012-04-04 20:41:55 +03:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & static_cast < CStackInstance & > ( * this ) ;
2017-07-31 15:35:42 +02:00
h & alive ;
h & level ;
h & name ;
h & secondarySkills ;
h & specialSKills ;
2012-04-04 20:41:55 +03:00
}
} ;
2023-04-17 23:11:16 +02:00
using TSlots = std : : map < SlotID , CStackInstance * > ;
using TSimpleSlots = std : : map < SlotID , std : : pair < CreatureID , TQuantity > > ;
2010-04-02 05:23:22 +03:00
2023-04-17 23:11:16 +02:00
using TPairCreatureSlot = std : : pair < const CCreature * , SlotID > ;
using TMapCreatureSlot = std : : map < const CCreature * , SlotID > ;
2021-11-28 14:57:38 +02:00
struct DLL_LINKAGE CreatureSlotComparer
{
bool operator ( ) ( const TPairCreatureSlot & lhs , const TPairCreatureSlot & rhs ) ;
} ;
2023-04-17 23:11:16 +02:00
using TCreatureQueue = std : : priority_queue < TPairCreatureSlot , std : : vector < TPairCreatureSlot > , CreatureSlotComparer > ;
2021-11-28 14:57:38 +02:00
2011-01-28 04:11:58 +02:00
class IArmyDescriptor
{
public :
2023-08-07 18:13:02 +02:00
virtual void clearSlots ( ) = 0 ;
2013-02-16 17:03:47 +03:00
virtual bool setCreature ( SlotID slot , CreatureID cre , TQuantity count ) = 0 ;
2011-01-28 04:11:58 +02:00
} ;
//simplified version of CCreatureSet
2011-12-14 00:23:17 +03:00
class DLL_LINKAGE CSimpleArmy : public IArmyDescriptor
2011-01-28 04:11:58 +02:00
{
public :
TSimpleSlots army ;
2023-08-07 18:13:02 +02:00
void clearSlots ( ) override ;
2013-06-26 14:18:27 +03:00
bool setCreature ( SlotID slot , CreatureID cre , TQuantity count ) override ;
2011-01-28 04:11:58 +02:00
operator bool ( ) const ;
2010-05-02 21:20:26 +03:00
2011-01-28 04:11:58 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & army ;
}
} ;
2010-05-02 21:20:26 +03:00
2023-04-02 18:56:10 +02:00
enum class EArmyFormation : uint8_t
{
2023-04-10 13:00:34 +02:00
LOOSE ,
2023-04-02 18:56:10 +02:00
TIGHT
} ;
2011-12-14 00:23:17 +03:00
class DLL_LINKAGE CCreatureSet : public IArmyDescriptor //seven combined creatures
2010-04-02 05:23:22 +03:00
{
2023-03-13 23:26:44 +02:00
CCreatureSet ( const CCreatureSet & ) = delete ;
2010-12-06 01:10:02 +02:00
CCreatureSet & operator = ( const CCreatureSet & ) ;
2010-04-02 05:23:22 +03:00
public :
2023-04-02 18:56:10 +02:00
2011-01-21 04:36:30 +02:00
TSlots stacks ; //slots[slot_id]->> pair(creature_id,creature_quantity)
2023-04-10 13:00:34 +02:00
EArmyFormation formation = EArmyFormation : : LOOSE ; //0 - wide, 1 - tight
2010-04-02 05:23:22 +03:00
2023-03-13 23:26:44 +02:00
CCreatureSet ( ) = default ; //Should be here to avoid compile errors
2010-11-27 03:46:19 +02:00
virtual ~ CCreatureSet ( ) ;
2011-02-04 16:58:14 +02:00
virtual void armyChanged ( ) ;
2010-11-27 03:46:19 +02:00
2023-03-13 23:26:44 +02:00
const CStackInstance & operator [ ] ( const SlotID & slot ) const ;
2010-04-02 05:23:22 +03:00
2011-01-21 04:36:30 +02:00
const TSlots & Slots ( ) const { return stacks ; }
2010-04-02 05:23:22 +03:00
2023-03-13 23:26:44 +02:00
void addToSlot ( const SlotID & slot , const CreatureID & cre , TQuantity count , bool allowMerging = true ) ; //Adds stack to slot. Slot must be empty or with same type creature
void addToSlot ( const SlotID & slot , CStackInstance * stack , bool allowMerging = true ) ; //Adds stack to slot. Slot must be empty or with same type creature
2023-08-07 18:13:02 +02:00
void clearSlots ( ) override ;
2010-05-02 21:20:26 +03:00
void setFormation ( bool tight ) ;
2010-11-27 03:46:19 +02:00
CArmedInstance * castToArmyObj ( ) ;
//basic operations
2023-03-13 23:26:44 +02:00
void putStack ( const SlotID & slot , CStackInstance * stack ) ; //adds new stack to the army, slot must be empty
void setStackCount ( const SlotID & slot , TQuantity count ) ; //stack must exist!
CStackInstance * detachStack ( const SlotID & slot ) ; //removes stack from army but doesn't destroy it (so it can be moved somewhere else or safely deleted)
void setStackType ( const SlotID & slot , const CreatureID & type ) ;
2012-09-23 21:01:04 +03:00
void giveStackExp ( TExpType exp ) ;
2023-03-13 23:26:44 +02:00
void setStackExp ( const SlotID & slot , TExpType exp ) ;
2010-11-27 03:46:19 +02:00
2012-09-15 22:16:16 +03:00
//derivative
2023-03-13 23:26:44 +02:00
void eraseStack ( const SlotID & slot ) ; //slot must be occupied
void joinStack ( const SlotID & slot , CStackInstance * stack ) ; //adds new stack to the existing stack of the same type
void changeStackCount ( const SlotID & slot , TQuantity toAdd ) ; //stack must exist!
2013-04-21 19:38:31 +03:00
bool setCreature ( SlotID slot , CreatureID type , TQuantity quantity ) override ; //replaces creature in stack; slots 0 to 6, if quantity=0 erases stack
2011-01-28 04:11:58 +02:00
void setToArmy ( CSimpleArmy & src ) ; //erases all our army and moves stacks from src to us; src MUST NOT be an armed object! WARNING: use it wisely. Or better do not use at all.
2012-09-15 22:16:16 +03:00
2023-03-13 23:26:44 +02:00
const CStackInstance & getStack ( const SlotID & slot ) const ; //stack must exist
const CStackInstance * getStackPtr ( const SlotID & slot ) const ; //if stack doesn't exist, returns nullptr
const CCreature * getCreature ( const SlotID & slot ) const ; //workaround of map issue;
int getStackCount ( const SlotID & slot ) const ;
TExpType getStackExperience ( const SlotID & slot ) const ;
2013-02-16 17:03:47 +03:00
SlotID findStack ( const CStackInstance * stack ) const ; //-1 if none
2023-03-13 23:26:44 +02:00
SlotID getSlotFor ( const CreatureID & creature , ui32 slotsAmount = GameConstants : : ARMY_SIZE ) const ; //returns -1 if no slot available
2013-02-16 17:03:47 +03:00
SlotID getSlotFor ( const CCreature * c , ui32 slotsAmount = GameConstants : : ARMY_SIZE ) const ; //returns -1 if no slot available
2023-03-13 23:26:44 +02:00
bool hasCreatureSlots ( const CCreature * c , const SlotID & exclude ) const ;
std : : vector < SlotID > getCreatureSlots ( const CCreature * c , const SlotID & exclude , TQuantity ignoreAmount = - 1 ) const ;
2021-11-28 14:57:38 +02:00
bool isCreatureBalanced ( const CCreature * c , TQuantity ignoreAmount = 1 ) const ; // Check if the creature is evenly distributed across slots
SlotID getFreeSlot ( ui32 slotsAmount = GameConstants : : ARMY_SIZE ) const ; //returns first free slot
std : : vector < SlotID > getFreeSlots ( ui32 slotsAmount = GameConstants : : ARMY_SIZE ) const ;
std : : queue < SlotID > getFreeSlotsQueue ( ui32 slotsAmount = GameConstants : : ARMY_SIZE ) const ;
TMapCreatureSlot getCreatureMap ( ) const ;
2023-03-13 23:26:44 +02:00
TCreatureQueue getCreatureQueue ( const SlotID & exclude ) const ;
2021-11-28 14:57:38 +02:00
2023-03-13 23:26:44 +02:00
bool mergableStacks ( std : : pair < SlotID , SlotID > & out , const SlotID & preferable = SlotID ( ) ) const ; //looks for two same stacks, returns slot positions;
2010-04-02 05:23:22 +03:00
bool validTypes ( bool allowUnrandomized = false ) const ; //checks if all types of creatures are set properly
2023-03-13 23:26:44 +02:00
bool slotEmpty ( const SlotID & slot ) const ;
2010-05-02 21:20:26 +03:00
int stacksCount ( ) const ;
virtual bool needsLastStack ( ) const ; //true if last stack cannot be taken
2011-06-21 12:31:08 +03:00
ui64 getArmyStrength ( ) const ; //sum of AI values of creatures
2023-03-13 23:26:44 +02:00
ui64 getPower ( const SlotID & slot ) const ; //value of specific stack
std : : string getRoughAmount ( const SlotID & slot , int mode = 0 ) const ; //rough size of specific stack
2015-12-24 20:03:51 +02:00
std : : string getArmyDescription ( ) const ;
2023-03-13 23:26:44 +02:00
bool hasStackAtSlot ( const SlotID & slot ) const ;
2012-09-15 22:16:16 +03:00
2010-05-02 21:20:26 +03:00
bool contains ( const CStackInstance * stack ) const ;
2010-12-13 01:44:16 +02:00
bool canBeMergedWith ( const CCreatureSet & cs , bool allowMergingStacks = true ) const ;
2010-11-22 02:34:46 +02:00
2010-04-02 05:23:22 +03:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2017-07-31 15:35:42 +02:00
h & stacks ;
h & formation ;
2010-04-02 05:23:22 +03:00
}
2016-01-15 19:24:17 +02:00
2023-04-16 19:42:56 +02:00
void serializeJson ( JsonSerializeFormat & handler , const std : : string & fieldName , const std : : optional < int > fixedSize = std : : nullopt ) ;
2016-01-15 19:24:17 +02:00
2010-04-02 05:23:22 +03:00
operator bool ( ) const
{
2013-11-03 15:51:25 +03:00
return ! stacks . empty ( ) ;
2010-04-02 05:23:22 +03:00
}
void sweep ( ) ;
} ;
2022-07-26 15:07:42 +02:00
VCMI_LIB_NAMESPACE_END