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
2010-12-20 23:22:53 +02:00
# include "CObjectHandler.h"
# include "CDefObjInfoHandler.h"
2009-01-30 20:36:00 +02:00
# endif
2009-04-15 17:03:31 +03:00
2010-12-17 20:47:07 +02:00
# include "ConstTransitivePtr.h"
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
*
*/
2010-12-17 20:47:07 +02:00
class CArtifactInstance ;
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-11-10 02:06:25 +02:00
class IModableArt ;
2008-12-27 03:01:59 +02:00
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
2010-07-09 07:29:11 +03:00
unsigned char siodmyTajemniczyBajt ; //first two bits - how to rotate terrain graphic (next two - river graphic, next two - road); 7th bit - whether tile is coastal (allows disembarking if land or block movement if water); 8th bit - Favourable Winds effect
2008-12-27 03:01:59 +02:00
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
2010-10-24 14:35:14 +03:00
si8 defaultCastle ( ) const
{
si8 ret = - 2 ;
for ( int j = 0 ; j < F_NUMBER & & ret ! = - 1 ; j + + ) //we start with none and find matching faction. if more than one, then set to random
{
if ( ( 1 < < j ) & allowedFactions )
{
if ( ret > = 0 ) //we've already assigned a castle and another one is possible -> set random and let player choose
ret = - 1 ; //breaks
if ( ret = = - 2 ) //first available castle - pick
ret = j ;
}
}
return ret ;
}
si8 defaultHero ( bool isMapRoE = false ) const
{
2010-10-25 22:37:21 +03:00
if ( ( ( generateHeroAtMainTown | | isMapRoE ) & & hasMainTown ) //we will generate hero in front of main town
2010-10-24 14:35:14 +03:00
| | p8 ) //random hero
return - 1 ;
else
return - 2 ;
}
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;
2010-08-18 17:24:30 +03:00
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
} ;
2010-08-18 17:24:30 +03:00
class DLL_EXPORT CCastleEvent : public CMapEvent
{
public :
std : : set < si32 > buildings ; //build specific buildings
std : : vector < si32 > creatures ; //additional creatures in i-th level dwelling
CGTownInstance * town ; //owner of this event
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & static_cast < CMapEvent & > ( * this ) ;
h & buildings & creatures ;
}
} ;
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 ;
2010-12-20 15:04:24 +02:00
std : : vector < ConstTransitivePtr < CGHeroInstance > > predefinedHeroes ;
std : : vector < ConstTransitivePtr < 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
2010-12-20 15:04:24 +02:00
std : : list < ConstTransitivePtr < CMapEvent > > events ;
2008-12-27 03:01:59 +02:00
int3 grailPos ;
int grailRadious ;
2010-12-17 20:47:07 +02:00
std : : vector < ConstTransitivePtr < CGObjectInstance > > objects ;
2010-12-20 15:04:24 +02:00
std : : vector < ConstTransitivePtr < CGHeroInstance > > heroes ;
std : : vector < ConstTransitivePtr < CGTownInstance > > towns ;
2010-12-17 20:47:07 +02:00
std : : vector < ConstTransitivePtr < CArtifactInstance > > artInstances ; //stores all artifacts
2010-12-20 15:04:24 +02:00
bmap < ui16 , ConstTransitivePtr < CGCreature > > monsters ;
bmap < ui16 , ConstTransitivePtr < 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 ) ;
2010-12-12 01:11:26 +02:00
CGObjectInstance * loadHero ( const unsigned char * bufor , int & i ) ;
2009-09-25 15:33:29 +03:00
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 ( ) ;
2010-12-17 20:47:07 +02:00
void addNewArtifactInstance ( CArtifactInstance * art ) ;
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 ( ) ;
2010-08-16 16:51:31 +03:00
TerrainTile & getTile ( const int3 & tile ) ;
const TerrainTile & getTile ( const 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
2010-08-16 16:51:31 +03:00
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-11-20 02:03:31 +02:00
h & monsters ;
h & heroesToBeat ;
h & artInstances ; //hopefully 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 ] ;
}
2010-07-28 13:46:36 +03:00
h & defy & objects ;
// //definfos
// std::vector<CGDefInfo*> defs;
//
// if(h.saving) //create vector with all defs used on map
// {
// for(unsigned int i=0; i<objects.size(); i++)
// if(objects[i])
// objects[i]->defInfo->serial = -1; //set serial to serial -1 - indicates that def is not present in defs vector
//
// for(unsigned int i=0; i<objects.size(); i++)
// {
// if(!objects[i]) continue;
// 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);
// }
2009-01-06 20:42:20 +02:00
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 ;
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
2010-07-28 13:46:36 +03:00
// for(unsigned int i=0; i<objects.size(); i++)
// {
// CGObjectInstance *&obj = objects[i];
// h & obj;
//
// 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 )
2010-12-17 20:47:07 +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 )
2010-12-17 20:47:07 +02:00
towns . push_back ( static_cast < CGTownInstance * > ( + objects [ i ] ) ) ;
2009-01-06 20:42:20 +02:00
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__