2008-12-27 03:01:59 +02:00
# ifndef __MAP_H__
# define __MAP_H__
# ifdef _MSC_VER
# pragma warning (disable : 4482)
# endif
# include <cstring>
# include <vector>
# include <map>
# include <set>
2009-02-06 13:15:39 +02:00
# include <list>
2009-05-20 13:08:56 +03:00
# include "../global.h"
2009-01-30 20:36:00 +02:00
# ifndef _MSC_VER
2009-05-20 13:08:56 +03:00
# include "../hch/CObjectHandler.h"
# include "../hch/CDefObjInfoHandler.h"
2009-01-30 20:36:00 +02:00
# endif
2009-04-15 17:03:31 +03:00
/*
* map . 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
*
*/
2008-12-27 03:01:59 +02:00
class CGDefInfo ;
class CGObjectInstance ;
class CGHeroInstance ;
2010-02-02 19:05:03 +02:00
class CGCreature ;
2008-12-27 03:01:59 +02:00
class CQuest ;
class CGTownInstance ;
2010-02-08 16:38:06 +02:00
2008-12-27 03:01:59 +02:00
enum EDefType { TOWN_DEF , HERO_DEF , CREATURES_DEF , SEERHUT_DEF , RESOURCE_DEF , TERRAINOBJ_DEF ,
EVENTOBJ_DEF , SIGN_DEF , GARRISON_DEF , ARTIFACT_DEF , WITCHHUT_DEF , SCHOLAR_DEF , PLAYERONLY_DEF ,
SHRINE_DEF , SPELLSCROLL_DEF , PANDORA_DEF , GRAIL_DEF , CREGEN_DEF , CREGEN2_DEF , CREGEN3_DEF ,
BORDERGUARD_DEF , HEROPLACEHOLDER_DEF } ;
class DLL_EXPORT CSpecObjInfo
{
public :
virtual ~ CSpecObjInfo ( ) { } ;
} ;
class DLL_EXPORT CCreGenObjInfo : public CSpecObjInfo
{
public :
unsigned char player ; //owner
bool asCastle ;
2010-02-07 17:06:14 +02:00
ui32 identifier ;
2008-12-27 03:01:59 +02:00
unsigned char castles [ 2 ] ; //allowed castles
} ;
class DLL_EXPORT CCreGen2ObjInfo : public CSpecObjInfo
{
public :
unsigned char player ; //owner
bool asCastle ;
2010-02-07 17:06:14 +02:00
ui32 identifier ;
2008-12-27 03:01:59 +02:00
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>
} ;
struct DLL_EXPORT TerrainTile
{
2009-05-07 20:20:41 +03:00
enum EterrainType { border = - 1 , dirt , sand , grass , snow , swamp , rough , subterranean , lava , water , rock } ;
enum Eriver { noRiver = 0 , clearRiver , icyRiver , muddyRiver , lavaRiver } ;
enum Eroad { dirtRoad = 1 , grazvelRoad , cobblestoneRoad } ;
2008-12-27 03:01:59 +02:00
EterrainType tertype ; // type of terrain
unsigned char terview ; // look of terrain
2009-12-22 23:53:50 +02:00
Eriver nuine ; // type of Eriver (0 if there is no river)
2008-12-27 03:01:59 +02:00
unsigned char rivDir ; // direction of Eriver
2009-12-22 23:53:50 +02:00
Eroad malle ; // type of Eroad (0 if there is no river)
2008-12-27 03:01:59 +02:00
unsigned char roadDir ; // direction of Eroad
unsigned char siodmyTajemniczyBajt ; //bitfield, info whether this tile is coastal and how to rotate tile graphics
bool visitable ; //false = not visitable; true = visitable
bool blocked ; //false = free; true = blocked;
std : : vector < CGObjectInstance * > visitableObjects ; //pointers to objects hero can visit while being on this tile
std : : vector < CGObjectInstance * > blockingObjects ; //pointers to objects that are blocking this tile
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & tertype & terview & nuine & rivDir & malle & roadDir & siodmyTajemniczyBajt ;
2009-01-06 20:42:20 +02:00
if ( ! h . saving )
{
visitable = blocked = false ;
//these flags (and obj vectors) will be restored in map serialization
}
2008-12-27 03:01:59 +02:00
}
2010-03-21 00:17:19 +02:00
bool entrableTerrain ( const TerrainTile * from = NULL ) const ; //checks if terrain is not a rock. If from is water/land, same type is also required.
bool entrableTerrain ( bool allowLand , bool allowSea ) const ; //checks if terrain is not a rock. If from is water/land, same type is also required.
bool isClear ( const TerrainTile * from = NULL ) const ; //checks for blocking objs and terraint type (water / land)
2008-12-27 03:01:59 +02:00
} ;
struct DLL_EXPORT SheroName //name of starting hero
{
int heroID ;
std : : string heroName ;
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & heroID & heroName ;
}
} ;
struct DLL_EXPORT PlayerInfo
{
si32 p7 , p8 , p9 ;
2010-02-01 19:07:46 +02:00
ui8 powerPlacehodlers ; //q-ty of hero placeholders containing hero type, WARNING: powerPlacehodlers sometimes gives false 0 (eg. even if there is one placeholder), maybe different meaning???
2008-12-27 03:01:59 +02:00
ui8 canHumanPlay ;
ui8 canComputerPlay ;
ui32 AITactic ; //(00 - random, 01 - warrior, 02 - builder, 03 - explorer)
ui32 allowedFactions ; //(01 - castle; 02 - rampart; 04 - tower; 08 - inferno; 16 - necropolis; 32 - dungeon; 64 - stronghold; 128 - fortress; 256 - conflux);
ui8 isFactionRandom ;
ui32 mainHeroPortrait ; //it's ID of hero with choosen portrait; 255 if standard
std : : string mainHeroName ;
std : : vector < SheroName > heroesNames ;
ui8 hasMainTown ;
ui8 generateHeroAtMainTown ;
int3 posOfMainTown ;
ui8 team ;
ui8 generateHero ;
2009-05-29 06:53:53 +03:00
PlayerInfo ( ) : p7 ( 0 ) , p8 ( 0 ) , p9 ( 0 ) , canHumanPlay ( 0 ) , canComputerPlay ( 0 ) ,
AITactic ( 0 ) , allowedFactions ( 0 ) , isFactionRandom ( 0 ) ,
mainHeroPortrait ( 0 ) , hasMainTown ( 0 ) , generateHeroAtMainTown ( 0 ) ,
2009-08-22 16:59:15 +03:00
team ( 255 ) , generateHero ( 0 ) { } ;
2009-05-29 06:53:53 +03:00
2008-12-27 03:01:59 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & p7 & p8 & p9 & canHumanPlay & canComputerPlay & AITactic & allowedFactions & isFactionRandom &
mainHeroPortrait & mainHeroName & heroesNames & hasMainTown & generateHeroAtMainTown &
posOfMainTown & team & generateHero ;
}
} ;
struct DLL_EXPORT LossCondition
{
ElossCon typeOfLossCon ;
2010-01-29 22:52:45 +02:00
int3 pos ;
si32 timeLimit ; // in days; -1 if not used
const CGObjectInstance * obj ; //set during map parsing: hero/town (depending on typeOfLossCon); NULL if not used
2008-12-27 03:01:59 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2010-01-29 22:52:45 +02:00
h & typeOfLossCon & pos & timeLimit & obj ;
2008-12-27 03:01:59 +02:00
}
2010-01-29 22:52:45 +02:00
LossCondition ( ) ;
2008-12-27 03:01:59 +02:00
} ;
2009-01-06 20:42:20 +02:00
struct DLL_EXPORT CVictoryCondition
2008-12-27 03:01:59 +02:00
{
2009-01-06 20:42:20 +02:00
EvictoryConditions condition ; //ID of condition
ui8 allowNormalVictory , appliesToAI ;
int3 pos ; //pos of city to upgrade (3); pos of town to build grail, {-1,-1,-1} if not relevant (4); hero pos (5); town pos(6); monster pos (7); destination pos(8)
2010-01-30 14:46:15 +02:00
si32 ID ; //artifact ID (0); monster ID (1); resource ID (2); needed fort level in upgraded town (3); artifact ID (8)
si32 count ; //needed count for creatures (1) / resource (2); upgraded town hall level (3);
2009-01-06 20:42:20 +02:00
2010-01-29 22:52:45 +02:00
const CGObjectInstance * obj ; //object of specific monster / city / hero instance (NULL if not used); set during map parsing
CVictoryCondition ( ) ;
2009-01-06 20:42:20 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2010-01-29 22:52:45 +02:00
h & condition & allowNormalVictory & appliesToAI & pos & ID & count & obj ;
2009-01-06 20:42:20 +02:00
}
2008-12-27 03:01:59 +02:00
} ;
2009-01-06 20:42:20 +02:00
2008-12-27 03:01:59 +02:00
struct DLL_EXPORT Rumor
{
std : : string name , text ;
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & name & text ;
}
} ;
struct DLL_EXPORT DisposedHero
{
ui32 ID ;
ui16 portrait ; //0xFF - default
std : : string name ;
ui8 players ; //who can hire this hero (bitfield)
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & ID & portrait & name & players ;
}
} ;
class DLL_EXPORT CMapEvent
{
public :
std : : string name , message ;
2009-02-06 13:15:39 +02:00
std : : vector < si32 > resources ; //gained / taken resources
2008-12-27 03:01:59 +02:00
ui8 players ; //affected players
ui8 humanAffected ;
ui8 computerAffected ;
ui32 firstOccurence ;
2009-02-06 13:15:39 +02:00
ui32 nextOccurence ; //after nextOccurance day event will occur; if it it 0, event occures only one time;
2008-12-27 03:01:59 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2009-02-06 13:15:39 +02:00
h & name & message & resources
2008-12-27 03:01:59 +02:00
& players & humanAffected & computerAffected & firstOccurence & nextOccurence ;
}
2009-03-09 21:40:43 +02:00
bool operator < ( const CMapEvent & b ) const
{
return firstOccurence < b . firstOccurence ;
}
2008-12-27 03:01:59 +02:00
} ;
class DLL_EXPORT CMapHeader
{
public :
2009-08-17 11:50:31 +03:00
enum Eformat { invalid , WoG = 0x33 , AB = 0x15 , RoE = 0x0e , SoD = 0x1c } ;
2008-12-27 03:01:59 +02:00
Eformat version ; // version of map Eformat
2009-01-06 20:42:20 +02:00
ui8 areAnyPLayers ; // if there are any playable players on map
si32 height , width , twoLevel ; //sizes
2008-12-27 03:01:59 +02:00
std : : string name ; //name of map
std : : string description ; //and description
2009-01-06 20:42:20 +02:00
ui8 difficulty ; // 0 easy - 4 impossible
ui8 levelLimit ;
2008-12-27 03:01:59 +02:00
LossCondition lossCondition ;
2009-01-06 20:42:20 +02:00
CVictoryCondition victoryCondition ; //victory conditions
2009-01-11 00:08:18 +02:00
std : : vector < PlayerInfo > players ; // info about players - size 8
2009-01-06 20:42:20 +02:00
ui8 howManyTeams ;
2009-08-17 11:50:31 +03:00
std : : vector < ui8 > allowedHeroes ; //allowedHeroes[hero_ID] - if the hero is allowed
2010-02-01 19:07:46 +02:00
std : : vector < ui16 > placeholdedHeroes ; //ID of types of heroes in placeholders
2009-09-25 15:33:29 +03:00
void initFromMemory ( const unsigned char * bufor , int & i ) ;
void loadViCLossConditions ( const unsigned char * bufor , int & i ) ;
void loadPlayerInfo ( int & pom , const unsigned char * bufor , int & i ) ;
CMapHeader ( const unsigned char * map ) ; //an argument is a reference to string described a map (unpacked)
2009-01-06 20:42:20 +02:00
CMapHeader ( ) ;
2009-08-27 11:04:32 +03:00
virtual ~ CMapHeader ( ) ;
2009-01-11 00:08:18 +02:00
template < typename Handler > void serialize ( Handler & h , const int Version )
{
h & version & name & description & width & height & twoLevel & difficulty & levelLimit & areAnyPLayers ;
2009-08-22 16:59:15 +03:00
h & players & lossCondition & victoryCondition & howManyTeams ;
2009-01-11 00:08:18 +02:00
}
2008-12-27 03:01:59 +02:00
} ;
2009-01-06 20:42:20 +02:00
struct DLL_EXPORT Mapa : public CMapHeader
2008-12-27 03:01:59 +02:00
{
ui32 checksum ;
TerrainTile * * * terrain ;
std : : vector < Rumor > rumors ;
std : : vector < DisposedHero > disposedHeroes ;
std : : vector < CGHeroInstance * > predefinedHeroes ;
std : : vector < CGDefInfo * > defy ; // list of .def files with definitions from .h3m (may be custom)
2008-12-31 11:33:46 +02:00
std : : vector < ui8 > allowedSpell ; //allowedSpell[spell_ID] - if the spell is allowed
std : : vector < ui8 > allowedArtifact ; //allowedArtifact[artifact_ID] - if the artifact is allowed
std : : vector < ui8 > allowedAbilities ; //allowedAbilities[ability_ID] - if the ability is allowed
2009-03-09 21:40:43 +02:00
std : : list < CMapEvent * > events ;
2008-12-27 03:01:59 +02:00
int3 grailPos ;
int grailRadious ;
std : : vector < CGObjectInstance * > objects ;
std : : vector < CGHeroInstance * > heroes ;
std : : vector < CGTownInstance * > towns ;
2010-02-02 19:05:03 +02:00
std : : map < ui16 , CGCreature * > monsters ;
2010-02-04 22:34:20 +02:00
std : : map < ui16 , CGHeroInstance * > heroesToBeat ;
2008-12-27 03:01:59 +02:00
2009-09-25 15:33:29 +03:00
void initFromBytes ( const unsigned char * bufor ) ; //creates map from decompressed .h3m data
2008-12-27 03:01:59 +02:00
2009-09-25 15:33:29 +03:00
void readEvents ( const unsigned char * bufor , int & i ) ;
void readObjects ( const unsigned char * bufor , int & i ) ;
void loadQuest ( CQuest * guard , const unsigned char * bufor , int & i ) ;
void readDefInfo ( const unsigned char * bufor , int & i ) ;
void readTerrain ( const unsigned char * bufor , int & i ) ;
void readPredefinedHeroes ( const unsigned char * bufor , int & i ) ;
void readHeader ( const unsigned char * bufor , int & i ) ;
void readRumors ( const unsigned char * bufor , int & i ) ;
void loadHero ( CGObjectInstance * & nobj , const unsigned char * bufor , int & i ) ;
void loadTown ( CGObjectInstance * & nobj , const unsigned char * bufor , int & i , int subid ) ;
int loadSeerHut ( const unsigned char * bufor , int i , CGObjectInstance * & nobj ) ;
2008-12-27 03:01:59 +02:00
2010-01-29 22:52:45 +02:00
void checkForObjectives ( ) ;
2008-12-27 03:01:59 +02:00
void addBlockVisTiles ( CGObjectInstance * obj ) ;
2009-02-14 21:12:40 +02:00
void removeBlockVisTiles ( CGObjectInstance * obj , bool total = false ) ;
2008-12-27 03:01:59 +02:00
Mapa ( std : : string filename ) ; //creates map structure from .h3m file
2009-01-06 20:42:20 +02:00
Mapa ( ) ;
2009-01-11 00:08:18 +02:00
~ Mapa ( ) ;
2009-02-12 16:44:58 +02:00
TerrainTile & getTile ( int3 tile ) ;
2009-07-26 06:33:13 +03:00
const TerrainTile & getTile ( int3 tile ) const ;
2008-12-27 03:01:59 +02:00
CGHeroInstance * getHero ( int ID , int mode = 0 ) ;
2009-08-22 16:59:15 +03:00
bool isInTheMap ( const int3 & pos ) const ;
bool isWaterTile ( const int3 & pos ) const ; //out-of-pos safe
2009-01-06 20:42:20 +02:00
template < typename Handler > void serialize ( Handler & h , const int formatVersion )
{
2009-01-11 00:08:18 +02:00
h & static_cast < CMapHeader & > ( * this ) ;
h & rumors & allowedSpell & allowedAbilities & allowedArtifact & allowedHeroes & events & grailPos ;
2010-02-04 22:34:20 +02:00
h & monsters & heroesToBeat ; //hoprfully serialization is now automagical?
2009-01-06 20:42:20 +02:00
2008-12-27 03:01:59 +02:00
//TODO: viccondetails
if ( h . saving )
{
//saving terrain
for ( int i = 0 ; i < width ; i + + )
for ( int j = 0 ; j < height ; j + + )
for ( int k = 0 ; k < = twoLevel ; k + + )
h & terrain [ i ] [ j ] [ k ] ;
}
else
{
//loading terrain
terrain = new TerrainTile * * [ width ] ; // allocate memory
for ( int ii = 0 ; ii < width ; ii + + )
{
terrain [ ii ] = new TerrainTile * [ height ] ; // allocate memory
for ( int jj = 0 ; jj < height ; jj + + )
terrain [ ii ] [ jj ] = new TerrainTile [ twoLevel + 1 ] ;
}
for ( int i = 0 ; i < width ; i + + )
for ( int j = 0 ; j < height ; j + + )
for ( int k = 0 ; k < = twoLevel ; k + + )
h & terrain [ i ] [ j ] [ k ] ;
}
2009-01-06 20:42:20 +02:00
//definfos
std : : vector < CGDefInfo * > defs ;
if ( h . saving ) //create vector with all defs used on map
{
2009-10-31 18:32:18 +02:00
for ( unsigned int i = 0 ; i < objects . size ( ) ; i + + )
2009-02-01 16:11:41 +02:00
if ( objects [ i ] )
objects [ i ] - > defInfo - > serial = - 1 ; //set serial to serial -1 - indicates that def is not present in defs vector
2009-01-06 20:42:20 +02:00
2009-10-31 18:32:18 +02:00
for ( unsigned int i = 0 ; i < objects . size ( ) ; i + + )
2009-01-06 20:42:20 +02:00
{
2009-02-01 16:11:41 +02:00
if ( ! objects [ i ] ) continue ;
2009-01-06 20:42:20 +02:00
CGDefInfo * cur = objects [ i ] - > defInfo ;
if ( cur - > serial < 0 )
{
cur - > serial = defs . size ( ) ;
defs . push_back ( cur ) ;
}
}
}
h & ( ( h . saving ) ? defs : defy ) ;
//objects
if ( h . saving )
{
ui32 hlp = objects . size ( ) ;
h & hlp ;
}
else
{
ui32 hlp ;
h & hlp ;
objects . resize ( hlp ) ;
}
2010-02-10 04:56:00 +02:00
//static members
2009-01-06 20:42:20 +02:00
h & CGTeleport : : objs ;
2009-09-07 05:29:44 +03:00
h & CGTeleport : : gates ;
2009-08-11 10:50:29 +03:00
h & CGKeys : : playerKeyMap ;
h & CGMagi : : eyelist ;
2009-09-24 20:54:02 +03:00
h & CGPyramid : : pyramidConfig ;
2010-02-10 04:56:00 +02:00
h & CGObelisk : : obeliskCount & CGObelisk : : visited ;
2010-06-26 19:02:10 +03:00
h & CGTownInstance : : merchantArtifacts ;
2009-01-06 20:42:20 +02:00
2009-10-31 18:32:18 +02:00
for ( unsigned int i = 0 ; i < objects . size ( ) ; i + + )
2009-01-06 20:42:20 +02:00
{
CGObjectInstance * & obj = objects [ i ] ;
2009-03-07 00:11:17 +02:00
h & obj ;
2009-01-06 20:42:20 +02:00
2009-03-21 14:49:58 +02:00
if ( obj )
{
si32 shlp ;
//definfo
h & ( h . saving ? ( shlp = obj - > defInfo - > serial ) : shlp ) ; //read / write pos of definfo in defs vector
if ( ! h . saving )
obj - > defInfo = defy [ shlp ] ;
}
2009-01-06 20:42:20 +02:00
}
if ( ! h . saving )
{
2009-10-31 18:32:18 +02:00
for ( unsigned int i = 0 ; i < objects . size ( ) ; i + + )
2009-01-06 20:42:20 +02:00
{
2009-02-02 01:56:45 +02:00
if ( ! objects [ i ] ) continue ;
2009-02-06 16:15:45 +02:00
if ( objects [ i ] - > ID = = HEROI_TYPE )
2009-01-06 20:42:20 +02:00
heroes . push_back ( static_cast < CGHeroInstance * > ( objects [ i ] ) ) ;
2009-02-06 16:15:45 +02:00
else if ( objects [ i ] - > ID = = TOWNI_TYPE )
2009-01-06 20:42:20 +02:00
towns . push_back ( static_cast < CGTownInstance * > ( objects [ i ] ) ) ;
addBlockVisTiles ( objects [ i ] ) ; //recreate blockvis map
}
2009-10-31 18:32:18 +02:00
for ( unsigned int i = 0 ; i < heroes . size ( ) ; i + + ) //if hero is visiting/garrisoned in town set appropriate pointers
2009-01-06 20:42:20 +02:00
{
int3 vistile = heroes [ i ] - > pos ; vistile . x + + ;
2009-10-31 18:32:18 +02:00
for ( unsigned int j = 0 ; j < towns . size ( ) ; j + + )
2009-01-06 20:42:20 +02:00
{
if ( vistile = = towns [ j ] - > pos ) //hero stands on the town entrance
{
if ( heroes [ i ] - > inTownGarrison )
2009-08-01 22:25:12 +03:00
{
2009-01-06 20:42:20 +02:00
towns [ j ] - > garrisonHero = heroes [ i ] ;
2009-08-01 22:25:12 +03:00
removeBlockVisTiles ( heroes [ i ] ) ;
}
2009-01-06 20:42:20 +02:00
else
2009-08-01 22:25:12 +03:00
{
2009-01-06 20:42:20 +02:00
towns [ j ] - > visitingHero = heroes [ i ] ;
2009-08-01 22:25:12 +03:00
}
2009-01-06 20:42:20 +02:00
heroes [ i ] - > visitedTown = towns [ j ] ;
2009-08-01 22:25:12 +03:00
break ;
2009-01-06 20:42:20 +02:00
}
}
2009-08-01 13:08:16 +03:00
vistile . x - = 2 ; //manifest pos
const TerrainTile & t = getTile ( vistile ) ;
if ( t . tertype ! = TerrainTile : : water ) continue ;
//hero stands on the water - he must be in the boat
2009-10-31 18:32:18 +02:00
for ( unsigned int j = 0 ; j < t . visitableObjects . size ( ) ; j + + )
2009-08-01 13:08:16 +03:00
{
if ( t . visitableObjects [ j ] - > ID = = 8 )
{
CGBoat * b = static_cast < CGBoat * > ( t . visitableObjects [ j ] ) ;
heroes [ i ] - > boat = b ;
b - > hero = heroes [ i ] ;
removeBlockVisTiles ( b ) ;
break ;
}
}
} //heroes loop
} //!saving
2008-12-27 03:01:59 +02:00
}
} ;
# endif // __MAP_H__