Browse Source

* Compilation fix (missing includes, do not remove)
* New settings.txt file (needed for kingdom overview to work)
* Last remainings of h3m format: hero placeholders parsing
* Minor improvements

Michał W. Urbańczyk 15 years ago
parent
commit
94fa59cf45

+ 1 - 1
client/AdventureMapButton.cpp

@@ -78,7 +78,7 @@ void CButtonBase::addTextOverlay( const std::string Text, EFonts font, SDL_Color
 	const Font *f = graphics->fonts[font];
 	text->x = pos.w/2 - f->getWidth(Text.c_str())/2;
 	text->y = pos.h/2 - f->height/2;
-	text->font = font;
+	text->font = font;
 	text->color = color;
 }
 

+ 1 - 1
client/CConfigHandler.cpp

@@ -293,7 +293,7 @@ struct SettingsGrammar : public grammar<SettingsGrammar>
 							(	"maxInputPerLine=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::inputLineLength)]
 							  |	"maxOutputPerLine=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::outputLineLength)]
 							) 
-						 )
+						 )
 				| str_p("Overview:") >>
 						*(	
 							(	"pics=" >> uint_p[SetAdventureProp_a(&AdventureMapConfig::overviewPics)]

+ 3 - 1
client/CKingdomInterface.cpp

@@ -13,14 +13,16 @@
 #include "../hch/CArtHandler.h"
 #include "../hch/CBuildingHandler.h"
 #include "../hch/CDefHandler.h"
+#include "../hch/CHeroHandler.h"
 #include "../hch/CGeneralTextHandler.h"
 #include "../hch/CObjectHandler.h"
 #include "../hch/CTownHandler.h"
-#include "../hch/CHeroHandler.h"
 #include "../lib/map.h"
 #include "../lib/NetPacks.h"
+#include <boost/algorithm/string/replace.hpp>
 #include <boost/assign/std/vector.hpp> 
 #include <boost/assign/list_of.hpp>
+#include <boost/lexical_cast.hpp>
 #include <boost/format.hpp>
 #include <sstream>
 using namespace boost::assign;

+ 9 - 0
client/CPlayerInterface.cpp

@@ -1608,6 +1608,15 @@ void CPlayerInterface::gameOver(ui8 player, bool victory )
  		event.user.code = 2;
  		SDL_PushEvent(&event);
 	}
+	else
+	{
+		if(!victory) //enemy has lost
+		{
+			std::string txt = CGI->generaltexth->allTexts[5]; //%s has been vanquished!
+			boost::algorithm::replace_first(txt, "%s", CGI->generaltexth->capColors[player]);
+			showInfoDialog(txt,std::vector<SComponent*>(1, new SComponent(SComponent::flag, player, 0)));
+		}
+	}
 }
 
 void SystemOptions::setMusicVolume( int newVolume )

+ 5 - 0
client/GUIClasses.cpp

@@ -866,6 +866,9 @@ void SComponent::init(Etype Type, int Subtype, int Val)
 			subtitle = oss.str();
 		}
 		break;
+	case flag:
+		subtitle = CGI->generaltexth->capColors[Subtype];
+		break;
 	}
 	type = Type;
 	subtype = Subtype;
@@ -933,6 +936,8 @@ SDL_Surface * SComponent::getImg()
 		break;
 	case creature:
 		return graphics->bigImgs[subtype];
+	case flag:
+		return graphics->flags->ourImages[subtype].bitmap;
 	}
 	return NULL;
 }

+ 1 - 1
client/GUIClasses.h

@@ -130,7 +130,7 @@ class SComponent : public virtual CIntObject //common popup window component
 public:
 	enum Etype
 	{
-		primskill, secskill, resource, creature, artifact, experience, secskill44, spell, morale, luck, building
+		primskill, secskill, resource, creature, artifact, experience, secskill44, spell, morale, luck, building, flag
 	} type; //component type
 	int subtype; //TODO: comment me
 	int val; //TODO: comment me

+ 65 - 28
config/settings.txt

@@ -16,18 +16,19 @@ GUISettings
 	{
 		AdventureMap
 		{
-			InGameConsole: maxInputPerLine=60 maxOutputPerLine=40;
+			InGameConsole: maxInputPerLine=60 maxOutputPerLine=44;
 			AdvMap: x=7 y=7 width=594 height=546 smoothMove=1 puzzleSepia=1;
 			InfoBox: x=605 y=389;
 			gem0: x=6 y=508 graphic=agemLL.def;
 			gem1: x=556 y=508 graphic=agemLR.def;
 			gem2: x=6 y=6 graphic=agemUL.def;
 			gem3: x=556 y=6 graphic=agemUR.def;
-			background=ADVMAP.bmp;
+			background=AdvMap.bmp;
 			HeroList: size=5 x=609 y=196 movePoints=IMOBIL.DEF manaPoints=IMANA.DEF arrowUp=IAM012.DEF arrowDown=IAM013.DEF;
 			TownList: size=5 x=747 y=196 arrowUp=IAM014.DEF arrowDown=IAM015.DEF;
 			Minimap: width=144 height=144 x=630 y=26;
-			Statusbar: x=7 y=556 graphic=ADROLLVR.bmp;
+			Statusbar: x=7 y=556 graphic=AdRollvr.bmp;
+			Overview: pics=4 size=4 graphic=OvCast.pcx;
 			ResDataBar: x=3 y=575 graphic=ZRESBAR.bmp offsetX=32 offsetY=2 resSpace=85 resDateSpace=85;
 			ButtonKingdomOv: x=679 y=196 graphic=IAM002.DEF playerColoured=1;
 			ButtonUnderground: x=711 y=196 graphic=IAM010.DEF playerColoured=1 additionalDefs=(IAM003.DEF);
@@ -45,19 +46,20 @@ GUISettings
 	{
 		AdventureMap
 		{
-			InGameConsole: maxInputPerLine=60 maxOutputPerLine=40;
+			InGameConsole: maxInputPerLine=70 maxOutputPerLine=50;
 			AdvMap: x=7 y=7 width=818 height=546 smoothMove=1 puzzleSepia=1;
 			InfoBox: x=829 y=389;
 		 	gem0: x=6 y=508 graphic=agemLL.def;
 			gem1: x=780 y=508 graphic=agemLR.def;
 			gem2: x=6 y=6 graphic=agemUL.def;
 			gem3: x=780 y=6 graphic=agemUR.def;
-			background=ADVMAP2.pcx;
+			background=AdvMap2.pcx;
 			HeroList: size=5 x=833 y=196 movePoints=IMOBIL.DEF manaPoints=IMANA.DEF arrowUp=IAM012.DEF arrowDown=IAM013.DEF;
 			TownList: size=5 x=971 y=196 arrowUp=IAM014.DEF arrowDown=IAM015.DEF;
 			Minimap: width=144 height=144 x=854 y=26;
-			Statusbar: x=8 y=556 graphic=ADROLLVR2.pcx;
-			ResDataBar: x=0 y=575 graphic=ZRESBAR2.pcx offsetX=65 offsetY=2 resSpace=109 resDateSpace=135;
+			Statusbar: x=8 y=556 graphic=AdRollvr2.pcx;
+			Overview: pics=4 size=4 graphic=OvCast.pcx;
+			ResDataBar: x=0 y=575 graphic=ZResBar2.pcx offsetX=65 offsetY=2 resSpace=109 resDateSpace=135;
 			ButtonKingdomOv: x=903 y=196 graphic=IAM002.DEF playerColoured=1;
 			ButtonUnderground: x=935 y=196 graphic=IAM010.DEF playerColoured=1 additionalDefs=(IAM003.DEF);
 			ButtonQuestLog: x=903 y=228 graphic=IAM004.DEF playerColoured=1;
@@ -75,19 +77,20 @@ GUISettings
 	{
 		AdventureMap
 		{
-			InGameConsole: maxInputPerLine=60 maxOutputPerLine=40;
+			InGameConsole: maxInputPerLine=70 maxOutputPerLine=50;
 			AdvMap: x=7 y=7 width=818 height=714 smoothMove=1 puzzleSepia=1;
 			InfoBox: x=829 y=557;
 			gem0: x=6 y=676 graphic=agemLL.def;
 			gem1: x=780 y=676 graphic=agemLR.def;
 			gem2: x=6 y=6 graphic=agemUL.def;
 			gem3: x=780 y=6 graphic=agemUR.def;
-			background=ADVMAP3.pcx;
+			background=AdvMap3.pcx;
 			HeroList: size=10 x=833 y=201 movePoints=IMOBIL.DEF manaPoints=IMANA.DEF arrowUp=IAM012.DEF arrowDown=IAM013.DEF;
 			TownList: size=10 x=971 y=201 arrowUp=IAM014.DEF arrowDown=IAM015.DEF;
 			Minimap: width=144 height=144 x=854 y=26;
-			Statusbar: x=8 y=723 graphic=ADROLLVR2.pcx;
-			ResDataBar: x=0 y=743 graphic=ZRESBAR2.pcx offsetX=65 offsetY=2 resSpace=109 resDateSpace=135;
+			Statusbar: x=8 y=723 graphic=AdRollvr2.pcx;
+			ResDataBar: x=0 y=743 graphic=ZResBar2.pcx offsetX=65 offsetY=2 resSpace=109 resDateSpace=135;
+			Overview: pics=4 size=5 graphic=OvCast5.pcx;
 			ButtonKingdomOv: x=903 y=197 graphic=IAM002L.DEF playerColoured=1;
 			ButtonUnderground: x=903 y=229 graphic=IAM010L.DEF playerColoured=1 additionalDefs=(IAM003L.DEF);
 			ButtonQuestLog: x=903 y=261 graphic=IAM004L.DEF playerColoured=1;
@@ -104,19 +107,20 @@ GUISettings
 	{
 		AdventureMap
 		{
-			InGameConsole: maxInputPerLine=60 maxOutputPerLine=40;
+			InGameConsole: maxInputPerLine=80 maxOutputPerLine=55;
 			AdvMap: x=7 y=7 width=1074 height=906 smoothMove=1 puzzleSepia=1;
 			InfoBox: x=1085 y=749;
 			gem0: x=6 y=868 graphic=agemLL.def;
 			gem1: x=1036 y=868 graphic=agemLR.def;
 			gem2: x=6 y=6 graphic=agemUL.def;
 			gem3: x=1036 y=6 graphic=agemUR.def;
-			background=ADVMAP4.pcx;
+			background=AdvMap4.pcx;
 			HeroList: size=16 x=1089 y=196 movePoints=IMOBIL.DEF manaPoints=IMANA.DEF arrowUp=IAM012.DEF arrowDown=IAM013.DEF;
 			TownList: size=16 x=1227 y=196 arrowUp=IAM014.DEF arrowDown=IAM015.DEF;
 			Minimap: width=144 height=144 x=1110 y=26;
-			Statusbar: x=8 y=916 graphic=ADROLLVR4.pcx;
-			ResDataBar: x=0 y=935 graphic=ZRESBAR4.pcx offsetX=97 offsetY=2 resSpace=142 resDateSpace=160;
+			Statusbar: x=8 y=916 graphic=AdRollvr4.pcx;
+			Overview: pics=4 size=5 graphic=OvCast5.pcx;
+			ResDataBar: x=0 y=935 graphic=ZResBar4.pcx offsetX=97 offsetY=2 resSpace=142 resDateSpace=160;
 			ButtonKingdomOv: x=1159 y=197 graphic=IAM002L.DEF playerColoured=1;
 			ButtonUnderground: x=1159 y=229 graphic=IAM010L.DEF playerColoured=1 additionalDefs=(IAM003L.DEF);
 			ButtonQuestLog: x=1159 y=261 graphic=IAM004L.DEF playerColoured=1;
@@ -133,19 +137,20 @@ GUISettings
 	{
 		AdventureMap
 		{
-			InGameConsole: maxInputPerLine=60 maxOutputPerLine=40;
+			InGameConsole: maxInputPerLine=80 maxOutputPerLine=55;
 			AdvMap: x=7 y=7 width=1074 height=970 smoothMove=1 puzzleSepia=1;
 			InfoBox: x=1085 y=517;
 			gem0: x=6 y=932 graphic=agemLL.def;
 			gem1: x=1036 y=932 graphic=agemLR.def;
 			gem2: x=6 y=6 graphic=agemUL.def;
 			gem3: x=1036 y=6 graphic=agemUR.def;
-			background=ADVMAP5.PCX;
+			background=AdvMap5.PCX;
 			HeroList: size=9 x=1089 y=196 movePoints=IMOBIL.DEF manaPoints=IMANA.DEF arrowUp=IAM012.DEF arrowDown=IAM013.DEF;
 			TownList: size=9 x=1227 y=196 arrowUp=IAM014.DEF arrowDown=IAM015.DEF;
 			Minimap: width=144 height=144 x=1110 y=26;
-			Statusbar: x=8 y=980 graphic=ADROLLVR4.pcx;
-			ResDataBar: x=0 y=999 graphic=ZRESBAR4.pcx offsetX=97 offsetY=2 resSpace=142 resDateSpace=160;
+			Statusbar: x=8 y=980 graphic=AdRollvr4.pcx;
+			Overview: pics=4 size=5 graphic=OvCast5.pcx;
+			ResDataBar: x=0 y=999 graphic=ZResBar4.pcx offsetX=97 offsetY=2 resSpace=142 resDateSpace=160;
 			ButtonKingdomOv: x=1159 y=196 graphic=IAM002L.DEF playerColoured=1;
 			ButtonUnderground: x=1159 y=228 graphic=IAM010L.DEF playerColoured=1 additionalDefs=(IAM003L.DEF);
 			ButtonQuestLog: x=1159 y=260 graphic=IAM004L.DEF playerColoured=1;
@@ -162,19 +167,20 @@ GUISettings
 	{
 		AdventureMap
 		{
-			InGameConsole: maxInputPerLine=60 maxOutputPerLine=40;
+			InGameConsole: maxInputPerLine=90 maxOutputPerLine=60;
 			AdvMap: x=7 y=7 width=1234 height=846 smoothMove=1 puzzleSepia=1;
 			InfoBox: x=1245 y=689;
 			gem0: x=6 y=808 graphic=agemLL.def;
 			gem1: x=1196 y=808 graphic=agemLR.def;
 			gem2: x=6 y=6 graphic=agemUL.def;
 			gem3: x=1196 y=6 graphic=agemUR.def;
-			background=ADVMAP6.pcx;
+			background=AdvMap6.pcx;
 			HeroList: size=14 x=1249 y=200 movePoints=IMOBIL.DEF manaPoints=IMANA.DEF arrowUp=IAM012.DEF arrowDown=IAM013.DEF;
 			TownList: size=14 x=1387 y=200 arrowUp=IAM014.DEF arrowDown=IAM015.DEF;
 			Minimap: width=144 height=144 x=1270 y=26;
-			Statusbar: x=8 y=855 graphic=ADROLLVR6.pcx;
-			ResDataBar: x=0 y=875 graphic=ZRESBAR6.pcx offsetX=100 offsetY=2 resSpace=155 resDateSpace=242;
+			Statusbar: x=8 y=855 graphic=AdRollvr6.pcx;
+			Overview: pics=4 size=6 graphic=OvCast6.pcx;
+			ResDataBar: x=0 y=875 graphic=ZResBar6.pcx offsetX=100 offsetY=2 resSpace=155 resDateSpace=242;
 			ButtonKingdomOv: x=1319 y=197 graphic=IAM002L.DEF playerColoured=1;
 			ButtonUnderground: x=1319 y=229 graphic=IAM010L.DEF playerColoured=1 additionalDefs=(IAM003L.DEF);
 			ButtonQuestLog: x=1319 y=261 graphic=IAM004L.DEF playerColoured=1;
@@ -191,19 +197,20 @@ GUISettings
 	{
 		AdventureMap
 		{
-			InGameConsole: maxInputPerLine=60 maxOutputPerLine=40;
+			InGameConsole: maxInputPerLine=100 maxOutputPerLine=70;
 			AdvMap: x=7 y=7 width=1394 height=1146 smoothMove=1 puzzleSepia=1;
 			InfoBox: x=1405 y=989;
 			gem0: x=6 y=1108 graphic=agemLL.def;
 			gem1: x=1356 y=1108 graphic=agemLR.def;
 			gem2: x=6 y=6 graphic=agemUL.def;
 			gem3: x=1356 y=6 graphic=agemUR.def;
-			background=ADVMAP7.pcx;
+			background=AdvMap7.pcx;
 			HeroList: size=23 x=1409 y=201 movePoints=IMOBIL.DEF manaPoints=IMANA.DEF arrowUp=IAM012.DEF arrowDown=IAM013.DEF;
 			TownList: size=23 x=1547 y=201 arrowUp=IAM014.DEF arrowDown=IAM015.DEF;
 			Minimap: width=144 height=144 x=1430 y=26;
-			Statusbar: x=285 y=1155 graphic=ADROLLVR7.pcx;
-			ResDataBar: x=0 y=1175 graphic=ZRESBAR7.pcx offsetX=65 offsetY=2 resSpace=192 resDateSpace=210;
+			Statusbar: x=285 y=1155 graphic=AdRollvr7.pcx;
+			Overview: pics=4 size=8 graphic=OvCast8.pcx;
+			ResDataBar: x=0 y=1175 graphic=ZResBar7.pcx offsetX=65 offsetY=2 resSpace=192 resDateSpace=210;
 			ButtonKingdomOv: x=1479 y=197 graphic=IAM002L.DEF playerColoured=1;
 			ButtonUnderground: x=1479 y=229 graphic=IAM010L.DEF playerColoured=1 additionalDefs=(IAM003L.DEF);
 			ButtonQuestLog: x=1479 y=261 graphic=IAM004L.DEF playerColoured=1;
@@ -216,4 +223,34 @@ GUISettings
 			ButtonEndTurn: x=1479 y=491 graphic=IAM001.DEF playerColoured=1;
 		};
 	}
-}
+	1680x1050 //setting specific for this resolution 
+		{ 
+		AdventureMap 
+		{ 
+			InGameConsole: maxInputPerLine=108 maxOutputPerLine=70;
+			AdvMap: x=7 y=7 width=1474 height=996 smoothMove=1; 
+			InfoBox: x=1485 y=839; 
+			gem0: x=6 y=958 graphic=agemLL.def; 
+			gem1: x=1436 y=958 graphic=agemLR.def; 
+			gem2: x=6 y=6 graphic=agemUL.def; 
+			gem3: x=1436 y=6 graphic=agemUR.def; 
+			background=AdvMap8.pcx; 
+			HeroList: size=19 x=1489 y=201 movePoints=IMOBIL.DEF manaPoints=IMANA.DEF arrowUp=IAM012.DEF arrowDown=IAM013.DEF; 
+			TownList: size=19 x=1627 y=201 arrowUp=IAM014.DEF arrowDown=IAM015.DEF; 
+			Minimap: width=144 height=144 x=1510 y=26; 
+			Statusbar: x=8 y=1005 graphic=AdRollvr8.pcx; 
+			Overview: pics=4 size=7 graphic=OvCast7.pcx;
+			ResDataBar: x=0 y=1025 graphic=ZResBar8.pcx offsetX=65 offsetY=2 resSpace=192 resDateSpace=290; 
+			ButtonKingdomOv: x=1559 y=197 graphic=IAM002L.DEF playerColoured=1; 
+			ButtonUnderground: x=1559 y=229 graphic=IAM010L.DEF playerColoured=1 additionalDefs=(IAM003L.DEF); 
+			ButtonQuestLog: x=1559 y=261 graphic=IAM004L.DEF playerColoured=1; 
+			ButtonSleepWake: x=1559 y=293 graphic=IAM005L.DEF playerColoured=1; 
+			ButtonMoveHero: x=1559 y=326 graphic=IAM006L.DEF playerColoured=1; 
+			ButtonSpellbook: x=1559 y=359 graphic=IAM007L.DEF playerColoured=1; 
+			ButtonAdvOptions: x=1559 y=392 graphic=IAM008L.DEF playerColoured=1; 
+			ButtonSysOptions: x=1559 y=425 graphic=IAM009L.DEF playerColoured=1; 
+			ButtonNextHero: x=1559 y=458 graphic=IAM000.DEF playerColoured=1; 
+			ButtonEndTurn: x=1559 y=491 graphic=IAM001.DEF playerColoured=1; 
+		}; 
+	}
+}

+ 1 - 0
global.h

@@ -80,6 +80,7 @@ extern CGameInfo* CGI;
 
 const int F_NUMBER = 9; //factions (town types) quantity
 const int PLAYER_LIMIT = 8; //player limit per map
+const int ALL_PLAYERS = 255; //bitfield
 const int HEROES_PER_TYPE=8; //amount of heroes of each type
 const int SKILL_QUANTITY=28;
 const int SKILL_PER_HERO=8;

+ 10 - 0
hch/CGeneralTextHandler.cpp

@@ -361,6 +361,16 @@ void CGeneralTextHandler::load()
 		overview.push_back(tmp);
 	}
 
+	std::string  strc = bitmaph->getTextFile("PLCOLORS.TXT");
+	itr=0;
+	while(itr<strc.length()-1)
+	{
+		loadToIt(tmp, strc, itr, 3);
+		colors.push_back(tmp);
+		toupper(tmp[0]);
+		capColors.push_back(tmp);
+	}
+
 	std::string  strs = bitmaph->getTextFile("ARRAYTXT.TXT");
 
 	itr=0;

+ 2 - 0
hch/CGeneralTextHandler.h

@@ -34,6 +34,8 @@ public:
 	std::vector<std::string> jktexts;
 	std::vector<std::string> heroscrn;
 	std::vector<std::string> overview;//text for Kingdom Overview window
+	std::vector<std::string> colors; //names of player colors ("red",...)
+	std::vector<std::string> capColors; //names of player colors with first letter capitalized ("Red",...)
 
 	//artifacts
 	std::vector<std::string> artifEvents;

+ 1 - 2
hch/CHeroHandler.h

@@ -41,8 +41,7 @@ public:
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & name & ID & lowStack & highStack & refTypeStack	& heroType & startingSpell;
-		//hero class pointer is restored by herohandler
+		h & name & ID & lowStack & highStack & refTypeStack	& heroType & startingSpell & heroClass;
 	}
 };
 

+ 6 - 0
hch/CObjectHandler.cpp

@@ -1667,6 +1667,7 @@ void CGTownInstance::onHeroLeave(const CGHeroInstance * h) const
 
 void CGTownInstance::initObj()
 { 
+	blockVisit = true;
 	hoverName = name + ", " + town->Name();
 
 	creatures.resize(CREATURES_PER_TOWN);
@@ -1762,6 +1763,11 @@ void CGTownInstance::removeCapitols (ui8 owner, bool me) const
 	} 
 } 
 
+ui8 CGTownInstance::getPassableness() const
+{
+	return army ? 1<<tempOwner : ALL_PLAYERS; //if there is garrison, castle be entered only by owner //TODO: allies
+}
+
 void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const
 {
 	if(visitors.find(h->id)==visitors.end())

+ 13 - 0
hch/CObjectHandler.h

@@ -182,6 +182,18 @@ public:
 		//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 <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<CGObjectInstance&>(*this);
+		h & power;
+	}
+};
 
 class DLL_EXPORT CPlayersVisited: public CGObjectInstance
 {
@@ -460,6 +472,7 @@ public:
 
 	//////////////////////////////////////////////////////////////////////////
 
+	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
 	void getOutOffsets(std::vector<int3> &offsets) const; //offsets to obj pos when we boat can be placed

+ 4 - 0
int3.h

@@ -105,6 +105,10 @@ public:
 	{
 		h & slots & formation;
 	}
+	operator bool() const
+	{
+		return slots.size() > 0;
+	}
 	void sweep()
 	{
 		for(TSlots::iterator i=slots.begin(); i!=slots.end(); ++i)

+ 1 - 1
lib/Connection.h

@@ -21,7 +21,7 @@
 #include <boost/mpl/int.hpp>
 #include <boost/mpl/identity.hpp>
 
-const ui32 version = 716;
+const ui32 version = 717;
 class CConnection;
 class CGObjectInstance;
 class CGameState;

+ 1 - 0
lib/RegisterTypes.cpp

@@ -20,6 +20,7 @@
 template<typename Serializer> DLL_EXPORT
 void registerTypes1(Serializer &s)
 {
+	s.template registerType<CGHeroPlaceholder>();
 	s.template registerType<CGHeroInstance>();
 	s.template registerType<CGTownInstance>();
 	s.template registerType<CTownBonus>();

+ 22 - 4
lib/map.cpp

@@ -263,7 +263,11 @@ void CMapHeader::initFromMemory( const unsigned char *bufor, int &i )
 					allowedHeroes[(i-pom)*8+yy] = true;
 	}
 	if(version>RoE) //probably reserved for further heroes
-		i+=4;
+	{
+		int placeholdersQty = readNormalNr(bufor, i); i+=4;
+		for(int p = 0; p < placeholdersQty; p++)
+			placeholdedHeroes.push_back(bufor[i++]);
+	}
 }
 void CMapHeader::loadPlayerInfo( int &pom, const unsigned char * bufor, int &i )
 {
@@ -333,7 +337,7 @@ void CMapHeader::loadPlayerInfo( int &pom, const unsigned char * bufor, int &i )
 
 		if(version != RoE)
 		{
-			i++; ////unknown byte
+			players[pom].powerPlacehodlers = bufor[i++];//unknown byte
 			int heroCount = bufor[i++];
 			i+=3;
 			for (int pp=0;pp<heroCount;pp++)
@@ -1905,7 +1909,21 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
 			}
 		case 214: //hero placeholder
 			{
-				i+=3; //TODO: handle it more properly
+				CGHeroPlaceholder *hp = new CGHeroPlaceholder();;
+				nobj = hp;
+
+				int a = bufor[i++]; //unkown byte, seems to be always 0 (if not - scream!)
+				assert(!a);
+
+				int htid = bufor[i++]; //hero type id
+				nobj->subID = htid;
+
+				if(htid == 0xff)
+					hp->power = bufor[i++];
+				else
+					hp->power = 0;
+
+				break;
 			}
 		case 10: //Keymaster
 			{
@@ -1954,7 +1972,7 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
 		nobj->pos = pos;
 		nobj->ID = defInfo->id;
 		nobj->id = objects.size();
-		if(nobj->ID != HEROI_TYPE)
+		if(nobj->ID != HEROI_TYPE && nobj->ID != 214)
 			nobj->subID = defInfo->subid;
 		nobj->defInfo = defInfo;
 		objects.push_back(nobj);

+ 2 - 0
lib/map.h

@@ -108,6 +108,7 @@ struct DLL_EXPORT SheroName //name of starting hero
 struct DLL_EXPORT PlayerInfo
 {
 	si32 p7, p8, p9;
+	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???
 	ui8 canHumanPlay;
 	ui8 canComputerPlay;
 	ui32 AITactic; //(00 - random, 01 -  warrior, 02 - builder, 03 - explorer)
@@ -229,6 +230,7 @@ public:
 	std::vector<PlayerInfo> players; // info about players - size 8
 	ui8 howManyTeams;
 	std::vector<ui8> allowedHeroes; //allowedHeroes[hero_ID] - if the hero is allowed
+	std::vector<ui16> placeholdedHeroes; //ID of types of heroes in placeholders
 	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);

+ 38 - 13
server/CGameHandler.cpp

@@ -1519,13 +1519,17 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
 			tmh.result = TryMoveHero::BLOCKING_VISIT;
 			sendAndApply(&tmh); 
 			//failed to move to that tile but we visit object
-			BOOST_FOREACH(CGObjectInstance *obj, t.visitableObjects)
-			{
-				if (obj->blockVisit)
-				{
-					objectVisited(obj, h);
-				}
-			}
+			if(t.visitableObjects.size())
+				objectVisited(t.visitableObjects.back(), h);
+
+
+// 			BOOST_FOREACH(CGObjectInstance *obj, t.visitableObjects)
+// 			{
+// 				if (obj->blockVisit)
+// 				{
+// 					objectVisited(obj, h);
+// 				}
+// 			}
 			tlog5 << "Blocking visit at " << hmpos << std::endl;
 			return true;
 		}
@@ -1542,10 +1546,13 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
 			tlog5 << "Moved to " <<tmh.end<<std::endl;
 
 			//call objects if they are visited
-			BOOST_FOREACH(CGObjectInstance *obj, t.visitableObjects)
-			{
-				objectVisited(obj, h);
-			}
+
+			if(t.visitableObjects.size())
+				objectVisited(t.visitableObjects.back(), h);
+// 			BOOST_FOREACH(CGObjectInstance *obj, t.visitableObjects)
+// 			{
+// 				objectVisited(obj, h);
+// 			}
 		}
 		tlog5 << "Movement end!\n";
 		return true;
@@ -3518,6 +3525,24 @@ void CGameHandler::checkLossVictory( ui8 player )
 	peg.victory = vic;
 	sendAndApply(&peg);
 
+	if(vic) //one player won -> all enemies lost  //TODO: allies
+	{
+		iw.text.localStrings.front().second++; //message about losing because enemy won first is just after victory message
+
+		for (std::map<ui8,PlayerState>::const_iterator i = gs->players.begin(); i!=gs->players.end(); i++)
+		{
+			if(i->first < PLAYER_LIMIT && i->first != player)
+			{
+				iw.player = i->first;
+				sendAndApply(&iw);
+
+				peg.player = i->first;
+				peg.victory = false;
+				sendAndApply(&peg);
+			}
+		}
+	}
+
 	if(vic)
 		end2 = true;
 }
@@ -3525,8 +3550,8 @@ void CGameHandler::checkLossVictory( ui8 player )
 void CGameHandler::getLossVicMessage( ui8 player, bool standard, bool victory, InfoWindow &out ) const
 {
 	const PlayerState *p = gs->getPlayer(player);
-	if(!p->human)
-		return; //AI doesn't need text info of loss
+// 	if(!p->human)
+// 		return; //AI doesn't need text info of loss
 
 	out.player = player;