浏览代码

- uploaded config/settings.txt from 0.82 (fix for #605)
- fixes for #604 and #364
- ally support is mostly done:
-- exchange between heroes
-- exchange between hero\town
-- finishing the game

Ivan Savenko 15 年之前
父节点
当前提交
520d40cc59

+ 1 - 1
CCallback.cpp

@@ -431,7 +431,7 @@ bool CCallback::dismissHero(const CGHeroInstance *hero)
 
 bool CCallback::swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2)
 {
-	if(player!=hero1->tempOwner || player!=hero2->tempOwner)
+	if(player!=hero1->tempOwner && player!=hero2->tempOwner)
 		return false;
 
 	ExchangeArtifacts ea(hero1->id, hero2->id, pos1, pos2);

+ 3 - 3
client/CKingdomInterface.cpp

@@ -378,7 +378,7 @@ void CKingdomInterface::recreateHeroList(int pos)
 		heroes[i]->setHero(Heroes[j]);
 		i++;
 	}
-	for (i;i<size;i++)//if we still have empty pieces
+	for (;i<size;i++)//if we still have empty pieces
 		heroes[i]->setHero(NULL);//empty pic
 }
 
@@ -517,7 +517,7 @@ void CKingdomInterface::CTownItem::setTown(const CGTownInstance * newTown)
 		return;
 		garr = NULL;
 	}
-	garr = new CGarrisonInt(pos.x+313,pos.y+3,4,Point(232,0),parent->slots->ourImages[parent->PicCount+2].bitmap,Point(313,2),town,town->visitingHero,true,true, 4,Point(-126,37));
+	garr = new CGarrisonInt(pos.x+313,pos.y+3,4,Point(232,0),parent->slots->ourImages[parent->PicCount+2].bitmap,Point(313,2),town,town->visitingHero,true,true, true);
 	garr->update = true;
 
 	garrHero->hero = town->garrisonHero;
@@ -782,7 +782,7 @@ void CKingdomInterface::CHeroItem::setHero(const CGHeroInstance * newHero)
 	artLeft->block(hero->artifacts.size() <= 8);
 	artRight->block(hero->artifacts.size() <= 8);
 	garr = new CGarrisonInt(pos.x+6, pos.y+78, 4, Point(), parent->slots->ourImages[parent->PicCount].bitmap,
-		Point(6,78), hero, NULL, true, true);
+		Point(6,78), hero, NULL, true, false, true);
 
 	for (int i=0; i<artifacts.size(); i++)
 	{

+ 2 - 2
client/CPlayerInterface.cpp

@@ -480,7 +480,7 @@ void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
 }
 void CPlayerInterface::heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town)
 {
-	if(hero->tempOwner != town->tempOwner)
+	if(hero->tempOwner != playerID )
 		return;
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
 	openTownWindow(town);
@@ -1180,7 +1180,7 @@ void CPlayerInterface::requestRealized( PackageApplied *pa )
 void CPlayerInterface::heroExchangeStarted(si32 hero1, si32 hero2)
 {
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
-	GH.pushInt(new CExchangeWindow(hero2, hero1));
+	GH.pushInt(new CExchangeWindow(hero1, hero2));
 }
 
 void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop)

+ 39 - 33
client/GUIClasses.cpp

@@ -155,6 +155,11 @@ const CArmedInstance * CGarrisonSlot::getObj()
 	return 	(!upg)?(owner->oup):(owner->odown);
 }
 
+bool CGarrisonSlot::our()
+{
+	return 	upg?(owner->ourDown):(owner->ourUp);
+}
+
 void CGarrisonSlot::clickRight(tribool down, bool previousState)
 {
 	if(down && creature)
@@ -176,22 +181,15 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState)
 			{
 				UpgradeInfo pom = LOCPLINT->cb->getUpgradeInfo(getObj(), ID);
 
-				CCreInfoWindow *creWindow = NULL;
-				if(pom.oldID>=0) //upgrade is possible
-				{
-
-					creWindow = new CCreInfoWindow(
-						*myStack, 1, 
-						boost::bind(&CCallback::upgradeCreature, LOCPLINT->cb, getObj(), ID, pom.newID[0]), //bind upgrade function
-						boost::bind(&CCallback::dismissCreature, LOCPLINT->cb, getObj(), ID), &pom);
-				}
-				else
-				{
-					creWindow = new CCreInfoWindow(
-						*myStack, 1, 0, 
-						boost::bind(&CCallback::dismissCreature, LOCPLINT->cb, getObj(), ID), NULL);
-				}
+				bool canUpgrade = getObj()->tempOwner == LOCPLINT->playerID && pom.oldID>=0; //upgrade is possible
+				bool canDismiss = getObj()->tempOwner == LOCPLINT->playerID && (getObj()->stacksCount()>1  || !getObj()->needsLastStack());
+				boost::function<void()> upgr = NULL;
+				boost::function<void()> dism = NULL;
+				if (canUpgrade) upgr = boost::bind(&CCallback::upgradeCreature, LOCPLINT->cb, getObj(), ID, pom.newID[0]);
+				if (canDismiss) dism = boost::bind(&CCallback::dismissCreature, LOCPLINT->cb, getObj(), ID);
 
+				CCreInfoWindow *creWindow = new CCreInfoWindow( *myStack, 1, upgr, dism, &pom);
+				
 				GH.pushInt(creWindow);
 
 				owner->highlighted = NULL;
@@ -205,10 +203,12 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState)
 			}
 			else 
 			{
-				// Only allow certain moves if troops aren't removable.
-				if (owner->removableUnits
-					|| (upg == 0 && (owner->highlighted->upg == 1 && !creature))
-					|| (upg == 1 && owner->highlighted->upg == 1))
+				// Only allow certain moves if troops aren't removable or not ours.
+				if (  ( owner->highlighted->our()//our creature is selected
+				     || owner->highlighted->creature == creature )//or we are rebalancing army
+				   && ( owner->removableUnits
+				     || (upg == 0 &&  ( owner->highlighted->upg == 1 && !creature ) )
+					 || (upg == 1 &&    owner->highlighted->upg == 1 ) ) )
 				{
 					//we want to split
 					if((owner->splitting || LOCPLINT->shiftPressed())
@@ -350,7 +350,7 @@ void CGarrisonSlot::show(SDL_Surface * to)
 		pos1.y = owner->surOffset.y+ pos.y-owner->pos.y;
 
 		SDL_BlitSurface(owner->sur,&pos1,to,&pos2);
-		if(owner->splitting)
+		if(owner->splitting && owner->highlighted->our())
 			blitAt(imgs[-1],pos,to);
 	}
 }
@@ -472,11 +472,11 @@ void CGarrisonInt::createSlots()
 			if((*sup)[i] == NULL)
 				(*sup)[i] = new CGarrisonSlot(this, pos.x + (i*(w+interx)), pos.y,i,0,NULL);
 
-		if (shiftPos)
-			for (int i=shiftPos; i<sup->size(); i++)
+		if (twoRows)
+			for (int i=4; i<sup->size(); i++)
 			{
-				(*sup)[i]->pos.x += shiftPoint.x;
-				(*sup)[i]->pos.y += shiftPoint.y;
+				(*sup)[i]->pos.x -= 126;
+				(*sup)[i]->pos.y += 37;
 			};
 	}
 	if(set2)
@@ -490,11 +490,12 @@ void CGarrisonInt::createSlots()
 		for(int i=0; i<sdown->size(); i++)
 			if((*sdown)[i] == NULL)
 				(*sdown)[i] = new CGarrisonSlot(this, pos.x + (i*(w+interx)) + garOffset.x,	pos.y + garOffset.y,i,1, NULL);
-		if (shiftPos)
-			for (int i=shiftPos; i<sup->size(); i++)
+		
+		if (twoRows)
+			for (int i=4; i<sup->size(); i++)
 			{
-				(*sdown)[i]->pos.x += shiftPoint.x;
-				(*sdown)[i]->pos.y += shiftPoint.y;
+				(*sup)[i]->pos.x -= 126;
+				(*sup)[i]->pos.y += 37;
 			};
 	}
 }
@@ -564,10 +565,12 @@ void CGarrisonInt::splitStacks(int am2)
 
 }
 CGarrisonInt::CGarrisonInt(int x, int y, int inx, const Point &garsOffset, SDL_Surface *&pomsur, const Point& SurOffset, 
-						   const CArmedInstance *s1, const CArmedInstance *s2, bool _removableUnits, bool smallImgs, int _shiftPos, const Point &_shiftPoint)
+						   const CArmedInstance *s1, const CArmedInstance *s2, bool _removableUnits, bool smallImgs, bool _twoRows )
 	 :interx(inx),garOffset(garsOffset),highlighted(NULL),sur(pomsur),surOffset(SurOffset),sup(NULL),
-	 sdown(NULL),oup(s1),odown(s2), removableUnits(_removableUnits), smallIcons(smallImgs), shiftPos(_shiftPos), shiftPoint(_shiftPoint)
+	 sdown(NULL),oup(s1),odown(s2), smallIcons(smallImgs), twoRows(_twoRows)
 {
+	ourUp =  s1?s1->tempOwner == LOCPLINT->playerID:false;
+	ourDown = s2?s2->tempOwner == LOCPLINT->playerID:false;
 	active = false;
 	splitting = false;
 	set1 = LOCPLINT->cb->getGarrison(s1);
@@ -4621,7 +4624,8 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
 
 		if(!ourOwner->commonInfo->srcAOH) //nothing has been clicked
 		{
-			if(ourArt) //to prevent selecting empty slots (bugfix to what GrayFace reported)
+			if(ourArt  //to prevent selecting empty slots (bugfix to what GrayFace reported)
+				&&  ourOwner->curHero->tempOwner == LOCPLINT->playerID)//can't take art from another player
 			{
 				if(ourArt->id == 3) //catapult cannot be highlighted
 				{
@@ -4672,7 +4676,8 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
 				}
 			}
 			//check if swap is possible
-			else if (this->fitsHere(ourOwner->commonInfo->srcArtifact))
+			else if (this->fitsHere(ourOwner->commonInfo->srcArtifact) &&
+				(!ourArt || ourOwner->curHero->tempOwner == LOCPLINT->playerID))
 			{
 				ourOwner->commonInfo->destAOH = ourOwner;
 				ourOwner->commonInfo->destSlotID = slotID;
@@ -4929,7 +4934,8 @@ void CHeroArea::hover(bool on)
 
 void CHeroArea::showAll(SDL_Surface * to)
 {
-	blitAtLoc(graphics->portraitLarge[hero->portrait],0,0,to);
+	if (hero)
+		blitAtLoc(graphics->portraitLarge[hero->portrait],0,0,to);
 }
 
 void LRClickableAreaOpenTown::clickLeft(tribool down, bool previousState)

+ 8 - 6
client/GUIClasses.h

@@ -212,6 +212,7 @@ public:
 
 	virtual void hover (bool on); //call-in
 	const CArmedInstance * getObj();
+	bool our();
 	void clickRight(tribool down, bool previousState);
 	void clickLeft(tribool down, bool previousState);
 	void activate();
@@ -226,8 +227,7 @@ class CGarrisonInt :public CIntObject
 public:
 	int interx; //space between slots
 	Point garOffset, //offset between garrisons (not used if only one hero)
-		surOffset, //offset between garrison position on the bg surface and position on the screen
-		shiftPoint;//how last slots will be shifted (for second row, set shiftPoint for effect)
+		surOffset; //offset between garrison position on the bg surface and position on the screen
 	CGarrisonSlot *highlighted; //chosen slot
 	std::vector<AdventureMapButton *> splitButtons; //may be empty if no buttons
 
@@ -235,8 +235,10 @@ public:
 	int p2, //TODO: comment me
 	    shiftPos;//1st slot of the second row, set shiftPoint for effect
 	bool ignoreEvent, update, active, splitting, pb, 
-		smallIcons; //true - 32x32 imgs, false - 58x64
-	bool removableUnits;
+	     smallIcons, //true - 32x32 imgs, false - 58x64
+	     removableUnits,//player can remove units from up
+	     twoRows,//slots will be placed in 2 rows
+		 ourUp,ourDown;//player owns up or down army
 
 	const CCreatureSet *set1; //top set of creatures
 	const CCreatureSet *set2; //bottom set of creatures
@@ -255,8 +257,8 @@ public:
 
 	void splitClick(); //handles click on split button
 	void splitStacks(int am2); //TODO: comment me
-
-	CGarrisonInt(int x, int y, int inx, const Point &garsOffset, SDL_Surface *&pomsur, const Point &SurOffset, const CArmedInstance *s1, const CArmedInstance *s2=NULL, bool _removableUnits = true, bool smallImgs = false, int _shiftPos = 0, const Point &_shiftPoint =Point()); //c-tor
+	//x, y - position; inx - distance between slots; pomsur - background surface, SurOffset - ?; s1, s2 - top and bottom armies; removableUnits - you can take units from top; smallImgs - units images size 64x58 or 32x32; twoRows - display slots in 2 row (1st row = 4, 2nd = 3)
+	CGarrisonInt(int x, int y, int inx, const Point &garsOffset, SDL_Surface *&pomsur, const Point &SurOffset, const CArmedInstance *s1, const CArmedInstance *s2=NULL, bool _removableUnits = true, bool smallImgs = false, bool _twoRows=false); //c-tor
 	~CGarrisonInt(); //d-tor
 };
 

+ 57 - 28
config/settings.txt

@@ -16,7 +16,7 @@ GUISettings
 	{
 		AdventureMap
 		{
-			InGameConsole: maxInputPerLine=60 maxOutputPerLine=44;
+			InGameConsole: maxInputPerLine=60 maxOutputPerLine=39;
 			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;
@@ -27,8 +27,8 @@ GUISettings
 			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;
 			Overview: pics=4 size=4 graphic=OvCast.pcx;
+			Statusbar: x=7 y=556 graphic=AdRollvr.bmp;
 			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);
@@ -53,13 +53,13 @@ GUISettings
 			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=AdvMap1024x600.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;
 			Overview: pics=4 size=4 graphic=OvCast.pcx;
-			ResDataBar: x=0 y=575 graphic=ZResBar2.pcx offsetX=65 offsetY=2 resSpace=109 resDateSpace=135;
+			Statusbar: x=8 y=556 graphic=AdRollvr1024.pcx;
+			ResDataBar: x=0 y=575 graphic=ZResBar1024.pcx offsetX=66 offsetY=2 resSpace=109 resDateSpace=133;
 			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;
@@ -77,20 +77,20 @@ GUISettings
 	{
 		AdventureMap
 		{
-			InGameConsole: maxInputPerLine=70 maxOutputPerLine=50;
+			InGameConsole: maxInputPerLine=70 maxOutputPerLine=57;
 			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=AdvMap1024x768.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;
 			Overview: pics=4 size=5 graphic=OvCast5.pcx;
+			Statusbar: x=8 y=723 graphic=AdRollvr1024.pcx;
+			ResDataBar: x=0 y=743 graphic=ZResBar1024.pcx offsetX=66 offsetY=2 resSpace=109 resDateSpace=133;
 			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;
@@ -107,20 +107,20 @@ GUISettings
 	{
 		AdventureMap
 		{
-			InGameConsole: maxInputPerLine=80 maxOutputPerLine=55;
+			InGameConsole: maxInputPerLine=80 maxOutputPerLine=57;
 			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=AdvMap1280x960.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;
-			Overview: pics=4 size=5 graphic=OvCast5.pcx;
-			ResDataBar: x=0 y=935 graphic=ZResBar4.pcx offsetX=97 offsetY=2 resSpace=142 resDateSpace=160;
+			Overview: pics=4 size=6 graphic=OvCast6.pcx;
+			Statusbar: x=8 y=916 graphic=AdRollvr1280.pcx;
+			ResDataBar: x=0 y=935 graphic=ZResBar1280.pcx offsetX=88 offsetY=2 resSpace=142 resDateSpace=167;
 			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;
@@ -137,20 +137,20 @@ GUISettings
 	{
 		AdventureMap
 		{
-			InGameConsole: maxInputPerLine=80 maxOutputPerLine=55;
+			InGameConsole: maxInputPerLine=80 maxOutputPerLine=57;
 			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=AdvMap1280x1024.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;
-			Overview: pics=4 size=5 graphic=OvCast5.pcx;
-			ResDataBar: x=0 y=999 graphic=ZResBar4.pcx offsetX=97 offsetY=2 resSpace=142 resDateSpace=160;
+			Overview: pics=4 size=7 graphic=OvCast7.pcx;
+			Statusbar: x=8 y=980 graphic=AdRollvr1280.pcx;
+			ResDataBar: x=0 y=999 graphic=ZResBar1280.pcx offsetX=88 offsetY=2 resSpace=142 resDateSpace=167;
 			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;
@@ -163,6 +163,35 @@ GUISettings
 			ButtonEndTurn: x=1159 y=484 graphic=IAM001.DEF playerColoured=1;
 		};
 	}
+	1366x768 //setting specific for this resolution
+	{
+		AdventureMap
+		{
+			InGameConsole: maxInputPerLine=85 maxOutputPerLine=58;
+			AdvMap: x=7 y=7 width=1160 height=714 smoothMove=1 puzzleSepia=1;
+			InfoBox: x=1171 y=557;
+			gem0: x=6 y=676 graphic=agemLL.def;
+			gem1: x=1122 y=676 graphic=agemLR.def;
+			gem2: x=6 y=6 graphic=agemUL.def;
+			gem3: x=1122 y=6 graphic=agemUR.def;
+			background=AdvMap1366x768.pcx;
+			HeroList: size=10 x=1175 y=201 movePoints=IMOBIL.DEF manaPoints=IMANA.DEF arrowUp=IAM012.DEF arrowDown=IAM013.DEF;
+			TownList: size=10 x=1313 y=201 arrowUp=IAM014.DEF arrowDown=IAM015.DEF;
+			Minimap: width=144 height=144 x=1196 y=26;
+			Statusbar: x=8 y=723 graphic=AdRollvr1366.pcx;
+			ResDataBar: x=0 y=743 graphic=ZResBar1366.pcx offsetX=90 offsetY=2 resSpace=153 resDateSpace=185;
+			ButtonKingdomOv: x=1245 y=197 graphic=IAM002L.DEF playerColoured=1;
+			ButtonUnderground: x=1245 y=229 graphic=IAM010L.DEF playerColoured=1 additionalDefs=(IAM003L.DEF);
+			ButtonQuestLog: x=1245 y=261 graphic=IAM004L.DEF playerColoured=1;
+			ButtonSleepWake: x=1245 y=293 graphic=IAM005L.DEF playerColoured=1;
+			ButtonMoveHero: x=1245 y=326 graphic=IAM006L.DEF playerColoured=1;
+			ButtonSpellbook: x=1245 y=359 graphic=IAM007L.DEF playerColoured=1;
+			ButtonAdvOptions: x=1245 y=392 graphic=IAM008L.DEF playerColoured=1;
+			ButtonSysOptions: x=1245 y=425 graphic=IAM009L.DEF playerColoured=1;
+			ButtonNextHero: x=1245 y=491 graphic=IAM000.DEF playerColoured=1;
+			ButtonEndTurn: x=1245 y=524 graphic=IAM001.DEF playerColoured=1;
+		};
+	}
 	1440x900 //setting specific for this resolution
 	{
 		AdventureMap
@@ -174,13 +203,13 @@ GUISettings
 			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=AdvMap1440x900.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;
 			Overview: pics=4 size=6 graphic=OvCast6.pcx;
-			ResDataBar: x=0 y=875 graphic=ZResBar6.pcx offsetX=100 offsetY=2 resSpace=155 resDateSpace=242;
+			Statusbar: x=8 y=855 graphic=AdRollvr1440.pcx;
+			ResDataBar: x=0 y=875 graphic=ZResBar1440.pcx offsetX=100 offsetY=2 resSpace=155 resDateSpace=238;
 			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;
@@ -204,13 +233,13 @@ GUISettings
 			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=AdvMap1600x1200.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;
 			Overview: pics=4 size=8 graphic=OvCast8.pcx;
-			ResDataBar: x=0 y=1175 graphic=ZResBar7.pcx offsetX=65 offsetY=2 resSpace=192 resDateSpace=210;
+			Statusbar: x=285 y=1155 graphic=AdRollvr1600.pcx;
+			ResDataBar: x=0 y=1175 graphic=ZResBar1600.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;
@@ -234,13 +263,13 @@ GUISettings
 			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; 
+			background=AdvMap1680x1050.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; 
+			Statusbar: x=8 y=1005 graphic=AdRollvr1680.pcx; 
+			ResDataBar: x=0 y=1025 graphic=ZResBar1680.pcx offsetX=67 offsetY=2 resSpace=192 resDateSpace=288; 
 			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; 

+ 2 - 2
hch/CObjectHandler.cpp

@@ -48,7 +48,7 @@ std::map <ui8, std::set <ui8> > CGKeys::playerKeyMap;
 std::map <si32, std::vector<si32> > CGMagi::eyelist;
 BankConfig CGPyramid::pyramidConfig;
 ui8 CGObelisk::obeliskCount; //how many obelisks are on map
-std::map<ui8, ui8> CGObelisk::visited; //map: color_id => how many obelisks has been visited
+std::map<ui8, ui8> CGObelisk::visited; //map: team_id => how many obelisks has been visited
 
 std::vector<const CArtifact *> CGTownInstance::merchantArtifacts;
 std::vector<int> CGTownInstance::universitySkills;
@@ -931,7 +931,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
 		if( cb->getPlayerRelations(tempOwner, h->tempOwner)) //our or ally hero
 		{
 			//exchange
-			cb->heroExchange(id, h->id);
+			cb->heroExchange(h->id, id);
 		}
 		else //battle
 		{

+ 1 - 1
lib/CGameState.h

@@ -453,7 +453,7 @@ public:
 	int getDate(int mode=0) const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & scenarioOps & seed & currentPlayer & day & map & players & hpool & globalEffects & campaign;
+		h & scenarioOps & seed & currentPlayer & day & map & players & teams & hpool & globalEffects & campaign;
 		h & villages & forts & capitols;
 		if(!h.saving)
 		{

+ 37 - 19
server/CGameHandler.cpp

@@ -1890,7 +1890,7 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
 
 				if( getPlayerRelations(dh->tempOwner, h->tempOwner)) 
 				{
-					heroExchange(dh->id, h->id);
+					heroExchange(h->id, dh->id);
 					return true;
 				}
 				startBattleI(h, dh);
@@ -2355,7 +2355,7 @@ void CGameHandler::heroExchange(si32 hero1, si32 hero2)
 	ui8 player1 = getHero(hero1)->tempOwner;
 	ui8 player2 = getHero(hero2)->tempOwner;
 
-	if(player1 == player2)//TODO: allies
+	if( getPlayerRelations( player1, player2))
 	{
 		OpenWindow hex;
 		hex.window = OpenWindow::EXCHANGE_WINDOW;
@@ -2464,7 +2464,7 @@ void CGameHandler::close()
 	//exit(0);
 }
 
-bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, si32 val )
+bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, si32 val, ui8 player )
 {
 	CArmedInstance *s1 = static_cast<CArmedInstance*>(gs->map->objects[id1]),
 		*s2 = static_cast<CArmedInstance*>(gs->map->objects[id2]);
@@ -2479,6 +2479,13 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
 
 	if(what==1) //swap
 	{
+		if ( (s1->tempOwner != player && S1.slots[p1].count)
+		  || (s2->tempOwner != player && S2.slots[p2].count))
+		{
+			complain("Can't take troops from another player!");
+			return false;
+		}
+		
 		std::swap(S1.slots[p1],S2.slots[p2]); //swap slots
 
 		//if one of them is empty, remove entry
@@ -2489,11 +2496,9 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
 	}
 	else if(what==2)//merge
 	{
-		if(S1.slots[p1].type != S2.slots[p2].type) //not same creature
-		{
-			complain("Cannot merge different creatures stacks!");
+		if (( S1.slots[p1].type != S2.slots[p2].type && complain("Cannot merge different creatures stacks!"))
+			|| (s1->tempOwner != player && S2.slots[p2].count) && complain("Can't take troops from another player!"))
 			return false; 
-		}
 
 		S2.slots[p2].count += S1.slots[p1].count;
 		S1.slots.erase(p1);
@@ -2533,6 +2538,13 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
 			S1.slots[p1].count -= val;
 		}
 
+		if ( (s1->tempOwner != player && S1.slots[p1].count < s1->getArmy().getAmount(p1) )
+		  || (s2->tempOwner != player && S2.slots[p2].count < s2->getArmy().getAmount(p2) ) )
+		{
+			complain("Can't move troops of another player!");
+			return false;
+		}
+
 		if(!S1.slots[p1].count) //if we've moved all creatures
 			S1.slots.erase(p1);
 	}
@@ -2960,7 +2972,7 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot,
 	CGHeroInstance *destHero = gs->getHero(destHeroID);
 
 	// Make sure exchange is even possible between the two heroes.
-	if ((distance(srcHero->pos,destHero->pos) > 1.5 )|| (srcHero->tempOwner != destHero->tempOwner))
+	if (distance(srcHero->pos,destHero->pos) > 1.5 )
 		return false;
 
 	const CArtifact *srcArtifact = srcHero->getArt(srcSlot);
@@ -2971,6 +2983,12 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot,
 		complain("No artifact to swap!");
 		return false;
 	}
+	
+	if (destArtifact && srcHero->tempOwner != destHero->tempOwner)
+	{
+		complain("Can't take artifact from hero of another player!");
+		return false;
+	}
 
 	SetHeroArtifacts sha;
 	sha.hid = srcHeroID;
@@ -3032,19 +3050,19 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot,
 
 		sha.setArtAtPos(destSlot, srcHero->getArtAtPos(srcSlot));
 	}
-	sendAndApply(&sha);
 	if (srcHeroID != destHeroID) 
 	{
 		// Exchange between two different heroes.
-		sha.hid = destHeroID;
-		sha.artifacts = destHero->artifacts;
-		sha.artifWorn = destHero->artifWorn;
-		sha.setArtAtPos(destSlot, srcArtifact ? srcArtifact->id : -1);
+		SetHeroArtifacts sha2;
+		sha2.hid = destHeroID;
+		sha2.artifacts = destHero->artifacts;
+		sha2.artifWorn = destHero->artifWorn;
+		sha2.setArtAtPos(destSlot, srcArtifact ? srcArtifact->id : -1);
 		if (!destFits)
-			sha.setArtAtPos(sha.artifacts.size() + 19, destHero->getArtAtPos(destSlot));
-		sendAndApply(&sha);
+			sha2.setArtAtPos(sha2.artifacts.size() + 19, destHero->getArtAtPos(destSlot));
+		sendAndApply(&sha2);
 	}
-
+	sendAndApply(&sha);
 	return true;
 }
 
@@ -4523,19 +4541,19 @@ void CGameHandler::checkLossVictory( ui8 player )
 	peg.victory = vic;
 	sendAndApply(&peg);
 
-	if(vic > 0) //one player won -> all enemies lost  //TODO: allies
+	if(vic > 0) //one player won -> all enemies lost
 	{
 		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)
+			if(i->first < PLAYER_LIMIT && i->first != player)//FIXME: skip already eliminated players?
 			{
 				iw.player = i->first;
 				sendAndApply(&iw);
 
 				peg.player = i->first;
-				peg.victory = false;
+				peg.victory = getPlayerRelations(player, i->first) == 1; // ally of winner
 				sendAndApply(&peg);
 			}
 		}

+ 1 - 1
server/CGameHandler.h

@@ -188,7 +188,7 @@ public:
 	bool buildStructure(si32 tid, si32 bid);
 	bool razeStructure(si32 tid, si32 bid);
 	bool disbandCreature( si32 id, ui8 pos );
-	bool arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, si32 val );
+	bool arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, si32 val, ui8 player);
 	void save(const std::string &fname);
 	void close();
 	void handleTimeEvents();

+ 5 - 4
server/NetPacksServer.cpp

@@ -69,7 +69,7 @@ bool CastleTeleportHero::applyGh( CGameHandler *gh )
 bool ArrangeStacks::applyGh( CGameHandler *gh )
 {
 	//checks for owning in the gh func
-	return gh->arrangeStacks(id1,id2,what,p1,p2,val);
+	return gh->arrangeStacks(id1,id2,what,p1,p2,val,gh->getPlayerAt(c));
 }
 
 bool DisbandCreature::applyGh( CGameHandler *gh )
@@ -97,14 +97,15 @@ bool UpgradeCreature::applyGh( CGameHandler *gh )
 
 bool GarrisonHeroSwap::applyGh( CGameHandler *gh )
 {
-	ERROR_IF_NOT_OWNS(tid);
+	const CGTownInstance * town = gh->getTown(tid);
+	if (!PLAYER_OWNS(tid) && !( town->garrisonHero && PLAYER_OWNS(town->garrisonHero->id) ) )
+		ERROR_AND_RETURN;//neither town nor garrisoned hero (if present) is ours 
 	return gh->garrisonSwap(tid);
 }
 
 bool ExchangeArtifacts::applyGh( CGameHandler *gh )
 {
-	ERROR_IF_NOT_OWNS(hid1);
-	ERROR_IF_NOT_OWNS(hid2);
+	ERROR_IF_NOT_OWNS(hid1);//second hero can be ally
 	return gh->swapArtifacts(hid1,hid2,slot1,slot2);
 }