浏览代码

* fixed crash when there was no sabegames in Games/ subfolder
* fixed crash when loading map with a mine belonging to human player
* fixed crash on moving hero into town garrison
* fixed r-click infowindow for towns
* new sight radious calculation. Works as OH3 for heroes, towns and probably all objects. (to be tested)

Michał W. Urbańczyk 16 年之前
父节点
当前提交
d6283fd1ca
共有 11 个文件被更改,包括 118 次插入66 次删除
  1. 2 2
      CAdvmapInterface.cpp
  2. 1 1
      CCallback.cpp
  3. 52 45
      CGameState.cpp
  4. 2 0
      CPlayerInterface.cpp
  5. 43 9
      hch/CObjectHandler.cpp
  6. 10 2
      hch/CObjectHandler.h
  7. 1 1
      lib/Connection.cpp
  8. 2 2
      lib/Connection.h
  9. 1 0
      lib/RegisterTypes.cpp
  10. 2 2
      lib/VCMI_lib.vcproj
  11. 2 2
      server/CGameHandler.cpp

+ 2 - 2
CAdvmapInterface.cpp

@@ -468,9 +468,9 @@ void CTerrainRect::clickRight(tribool down)
 		}
 	case 98:
 		{
-			if(!vstd::contains(graphics->townWins,obj->subID))
+			if(!vstd::contains(graphics->townWins,obj->id))
 			{
-				tlog3 << "Warning - no infowin for town " << obj->subID << std::endl;
+				tlog3 << "Warning - no infowin for town " << obj->id << std::endl;
 				break;
 			}
 			CInfoPopup * ip = new CInfoPopup(graphics->townWins[obj->id],

+ 1 - 1
CCallback.cpp

@@ -601,7 +601,7 @@ bool CCallback::battleCanShoot(int ID, int dest)
 void CCallback::swapGarrisonHero( const CGTownInstance *town )
 {
 	if(town->tempOwner != player) return;
-	*cl->serv << ui16(508) << si32(town->id);
+	*cl->serv << &GarrisonHeroSwap(town->id);
 }
 
 void CCallback::buyArtifact(const CGHeroInstance *hero, int aid)

+ 52 - 45
CGameState.cpp

@@ -997,20 +997,39 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
 			for(int h=0; h<map->height; ++h)
 				for(int v=0; v<map->twoLevel+1; ++v)
 					k->second.fogOfWarMap[g][h][v] = 0;
-		for(int xd=0; xd<map->width; ++xd) //revealing part of map around heroes
+
+		BOOST_FOREACH(CGObjectInstance *obj, map->objects)
 		{
-			for(int yd=0; yd<map->height; ++yd)
+			if(obj->tempOwner != k->first) continue; //not a flagged object
+
+			int3 objCenter = obj->getSightCenter();
+			int radious = obj->getSightRadious();
+
+			for (int xd = std::max<int>(objCenter.x - radious , 0); xd <= std::min<int>(objCenter.x + radious, map->width - 1); xd++)
 			{
-				for(int ch=0; ch<k->second.heroes.size(); ++ch)
+				for (int yd = std::max<int>(objCenter.y - radious, 0); yd <= std::min<int>(objCenter.y + radious, map->height - 1); yd++)
 				{
-					int deltaX = (k->second.heroes[ch]->getPosition(false).x-xd)*(k->second.heroes[ch]->getPosition(false).x-xd);
-					int deltaY = (k->second.heroes[ch]->getPosition(false).y-yd)*(k->second.heroes[ch]->getPosition(false).y-yd);
-					if(deltaX+deltaY<k->second.heroes[ch]->getSightDistance()*k->second.heroes[ch]->getSightDistance())
-						k->second.fogOfWarMap[xd][yd][k->second.heroes[ch]->getPosition(false).z] = 1;
+					double distance = objCenter.dist2d(int3(xd,yd,objCenter.z)) - 0.5;
+					if(distance <= radious)
+						k->second.fogOfWarMap[xd][yd][objCenter.z] = 1;
 				}
 			}
 		}
 
+		//for(int xd=0; xd<map->width; ++xd) //revealing part of map around heroes
+		//{
+		//	for(int yd=0; yd<map->height; ++yd)
+		//	{
+		//		for(int ch=0; ch<k->second.heroes.size(); ++ch)
+		//		{
+		//			int deltaX = (k->second.heroes[ch]->getPosition(false).x-xd)*(k->second.heroes[ch]->getPosition(false).x-xd);
+		//			int deltaY = (k->second.heroes[ch]->getPosition(false).y-yd)*(k->second.heroes[ch]->getPosition(false).y-yd);
+		//			if(deltaX+deltaY<k->second.heroes[ch]->getSightDistance()*k->second.heroes[ch]->getSightDistance())
+		//				k->second.fogOfWarMap[xd][yd][k->second.heroes[ch]->getPosition(false).z] = 1;
+		//		}
+		//	}
+		//}
+
 		//starting bonus
 		if(si->playerInfos[k->second.serial].bonus==brandom)
 			si->playerInfos[k->second.serial].bonus = ran()%3;
@@ -1125,19 +1144,19 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
 	{
 		if(k->first==-1 || k->first==255)
 			continue;
-		for(int xd=0; xd<map->width; ++xd) //revealing part of map around towns
-		{
-			for(int yd=0; yd<map->height; ++yd)
-			{
-				for(int ch=0; ch<k->second.towns.size(); ++ch)
-				{
-					int deltaX = (k->second.towns[ch]->pos.x-xd)*(k->second.towns[ch]->pos.x-xd);
-					int deltaY = (k->second.towns[ch]->pos.y-yd)*(k->second.towns[ch]->pos.y-yd);
-					if(deltaX+deltaY<k->second.towns[ch]->getSightDistance()*k->second.towns[ch]->getSightDistance())
-						k->second.fogOfWarMap[xd][yd][k->second.towns[ch]->pos.z] = 1;
-				}
-			}
-		}
+	//	for(int xd=0; xd<map->width; ++xd) //revealing part of map around towns
+	//	{
+	//		for(int yd=0; yd<map->height; ++yd)
+	//		{
+	//			for(int ch=0; ch<k->second.towns.size(); ++ch)
+	//			{
+	//				int deltaX = (k->second.towns[ch]->pos.x-xd)*(k->second.towns[ch]->pos.x-xd);
+	//				int deltaY = (k->second.towns[ch]->pos.y-yd)*(k->second.towns[ch]->pos.y-yd);
+	//				if(deltaX+deltaY<k->second.towns[ch]->getSightDistance()*k->second.towns[ch]->getSightDistance())
+	//					k->second.fogOfWarMap[xd][yd][k->second.towns[ch]->pos.z] = 1;
+	//			}
+	//		}
+	//	}
 
 		//init visiting and garrisoned heroes
 		for(int l=0; l<k->second.heroes.size();l++)
@@ -1307,33 +1326,21 @@ float CGameState::getMarketEfficiency( int player, int mode/*=0*/ )
 }
 
 std::set<int3> CGameState::tilesToReveal(int3 pos, int radious, int player) const
-{		
+{
 	std::set<int3> ret;
-	int xbeg = pos.x - radious - 2;
-	if(xbeg < 0)
-		xbeg = 0;
-	int xend = pos.x + radious + 2;
-	if(xend >= map->width)
-		xend = map->width;
-	int ybeg = pos.y - radious - 2;
-	if(ybeg < 0)
-		ybeg = 0;
-	int yend = pos.y + radious + 2;
-	if(yend >= map->height)
-		yend = map->height;
-	for(int xd=xbeg; xd<xend; ++xd) //revealing part of map around heroes
-	{
-		for(int yd=ybeg; yd<yend; ++yd)
+	if(player >= PLAYER_LIMIT)
+	{
+		tlog1 << "Illegal call to tilesToReveal!\n";
+		return ret;
+	}
+
+	for (int xd = std::max<int>(pos.x - radious , 0); xd <= std::min<int>(pos.x + radious, map->width); xd++)
+	{
+		for (int yd = std::max<int>(pos.y - radious, 0); std::min<int>(yd <= pos.y + radious, map->height); yd++)
 		{
-			int deltaX = (pos.x-xd)*(pos.x-xd);
-			int deltaY = (pos.y-yd)*(pos.y-yd);
-			if(deltaX+deltaY<radious*radious)
-			{
-				if(player<0 || players.find(player)->second.fogOfWarMap[xd][yd][pos.z]==0)
-				{
-					ret.insert(int3(xd,yd,pos.z));
-				}
-			}
+			double distance = pos.dist2d(int3(xd,yd,pos.z)) - 0.5;
+			if(distance <= radious  &&  (player<0 || players.find(player)->second.fogOfWarMap[xd][yd][pos.z]==0))
+				ret.insert(int3(xd,yd,pos.z));
 		}
 	}
 	return ret;

+ 2 - 0
CPlayerInterface.cpp

@@ -1943,6 +1943,8 @@ void CPlayerInterface::heroMovePointsChanged(const CGHeroInstance * hero)
 void CPlayerInterface::receivedResource(int type, int val)
 {
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
+	if(!curint)
+		return;
 	if(curint==adventureInt  ||  screen->h > 600  ||  screen->w > 800)
 		adventureInt->resdatabar.draw();
 	if(curint==castleInt && !curint->subInt)

+ 43 - 9
hch/CObjectHandler.cpp

@@ -139,14 +139,21 @@ int CGObjectInstance::getWidth() const//returns width of object graphic in tiles
 }
 int CGObjectInstance::getHeight() const //returns height of object graphic in tiles
 {
-	return defInfo->width;
+	return defInfo->height;
 }
 bool CGObjectInstance::visitableAt(int x, int y) const //returns true if object is visitable at location (x, y) form left top tile of image (x, y in tiles)
 {
-	if(x<0 || y<0 || x>=getWidth() || y>=getHeight() || defInfo==NULL)
+	if(defInfo==NULL)
+	{
+		tlog2 << "Warning: VisitableAt for obj "<<id<<": NULL defInfo!\n";
 		return false;
-	if((defInfo->visitMap[y+6-getHeight()] >> (7-(8-getWidth()+x) )) & 1)
+	}
+
+	if((defInfo->visitMap[y] >> (7-x) ) & 1)
+	{
 		return true;
+	}
+
 	return false;
 }
 bool CGObjectInstance::blockingAt(int x, int y) const
@@ -204,6 +211,21 @@ void CGObjectInstance::setProperty( ui8 what, ui32 val )
 void CGObjectInstance::setPropertyDer( ui8 what, ui32 val )
 {}
 
+int3 CGObjectInstance::getSightCenter() const
+{
+	//return vistiable tile if possible
+	for(int i=0; i < 8; i++)
+		for(int j=0; j < 6; j++)
+			if(visitableAt(i,j))
+				return(pos + int3(i-7, j-5, 0));
+	return pos;
+}
+
+int CGObjectInstance::getSightRadious() const
+{
+	return 3;
+}
+
 int lowestSpeed(const CGHeroInstance * chi)
 {
 	if(!chi->army.slots.size())
@@ -288,10 +310,6 @@ int3 CGHeroInstance::getPosition(bool h3m) const //h3m=true - returns position o
 		return convertPosition(pos,false);
 	}
 }
-int CGHeroInstance::getSightDistance() const //returns sight distance of this hero
-{
-	return 5 + getSecSkillLevel(3); //default + scouting
-}
 
 si32 CGHeroInstance::manaLimit() const
 {
@@ -729,9 +747,20 @@ void CGHeroInstance::setPropertyDer( ui8 what, ui32 val )
 	if(what == 3)
 		army.slots[0].second = val;
 }
-int CGTownInstance::getSightDistance() const //returns sight distance
+
+int3 CGHeroInstance::getSightCenter() const
+{
+	return getPosition(false);
+}
+
+int CGHeroInstance::getSightRadious() const
+{
+	return 5 + getSecSkillLevel(3); //default + scouting
+}
+
+int CGTownInstance::getSightRadious() const //returns sight distance
 {
-	return 10;
+	return 5;
 }
 int CGTownInstance::fortLevel() const //0 - none, 1 - fort, 2 - citadel, 3 - castle
 {
@@ -870,6 +899,11 @@ void CGTownInstance::initObj()
 	hoverName = toString(ms);
 }
 
+int3 CGTownInstance::getSightCenter() const
+{
+	return pos - int3(2,0,0);
+}
+
 void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const
 {
 	if(visitors.find(h->id)==visitors.end())

+ 10 - 2
hch/CObjectHandler.h

@@ -107,6 +107,8 @@ public:
 	ui8 tempOwner;
 	ui8 blockVisit; //if non-zero then blocks the tile but is visitable from neighbouring tile
 
+	virtual int3 getSightCenter() const; //"center" tile from which the sight distance is calculated
+	virtual int getSightRadious() const; //sight distance (should be used if player-owned structure)
 	int getOwner() const;
 	void setOwner(int ow);
 	int getWidth() const; //returns width of object graphic in tiles
@@ -206,6 +208,10 @@ public:
 			type = VLC->heroh->heroes[subID];
 		//visitied town pointer will be restored by map serialization method
 	}
+	//////////////////////////////////////////////////////////////////////////
+
+	int3 getSightCenter() const; //"center" tile from which the sight distance is calculated
+	int getSightRadious() const; //sight distance (should be used if player-owned structure)
 
 	//////////////////////////////////////////////////////////////////////////
 	const HeroBonus *getBonus(int from, int id) const;
@@ -216,7 +222,6 @@ public:
 	unsigned int getAdditiveMoveBonus() const;
 	float getMultiplicativeMoveBonus() const;
 	int3 getPosition(bool h3m) const; //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation'
-	int getSightDistance() const; //returns sight distance of this hero
 	si32 manaLimit() const; //maximum mana value for this hero (basically 10*knowledge)
 	bool canWalkOnSea() const;
 	int getCurrentLuck(int stack=-1, bool town=false) const;
@@ -294,9 +299,12 @@ public:
 
 	//////////////////////////////////////////////////////////////////////////
 
+	int3 getSightCenter() const; //"center" tile from which the sight distance is calculated
+	int getSightRadious() const; //returns sight distance
+
+	//////////////////////////////////////////////////////////////////////////
 
 	bool needsLastStack() const;
-	int getSightDistance() const; //returns sight distance
 	int fortLevel() const; //0 - none, 1 - fort, 2 - citadel, 3 - castle
 	int hallLevel() const; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol
 	int mageGuildLevel() const; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol

+ 1 - 1
lib/Connection.cpp

@@ -197,7 +197,7 @@ int CLoadFile::read( const void * data, unsigned size )
 
 CTypeList::CTypeList()
 {
-
+	registerTypes(*this);
 }
 
 ui16 CTypeList::registerType( const type_info *type )

+ 2 - 2
lib/Connection.h

@@ -56,7 +56,7 @@ enum SerializationLvl
 
 struct TypeComparer
 {
-	bool operator()(const type_info *a, const type_info *b)
+	bool operator()(const type_info *a, const type_info *b) const
 	{
 		return a->before(*b);
 	}
@@ -69,7 +69,7 @@ class DLL_EXPORT CTypeList
 public:
 	CTypeList();
 	ui16 registerType(const type_info *type);
-	template <typename T> ui16 registerType(const T * t)
+	template <typename T> ui16 registerType(const T * t = NULL)
 	{
 		return registerType(getTypeInfo(t));
 	}

+ 1 - 0
lib/RegisterTypes.cpp

@@ -16,4 +16,5 @@ void foofoofoo()
 	registerTypes((COSer<CConnection>&)*ccc);
 	registerTypes((CSaveFile&)*ccc);
 	registerTypes((CLoadFile&)*ccc);
+	registerTypes((CTypeList&)*ccc);
 }

+ 2 - 2
lib/VCMI_lib.vcproj

@@ -140,7 +140,7 @@
 				Name="VCLinkerTool"
 				AdditionalDependencies="zdll.lib"
 				Version=""
-				AdditionalLibraryDirectories=""
+				AdditionalLibraryDirectories="../../libs;"
 				GenerateDebugInformation="false"
 				OptimizeReferences="2"
 				EnableCOMDATFolding="2"
@@ -225,7 +225,7 @@
 				Name="VCLinkerTool"
 				AdditionalDependencies="zdll.lib"
 				Version=""
-				AdditionalLibraryDirectories=""
+				AdditionalLibraryDirectories="../../libs;"
 				GenerateDebugInformation="true"
 				GenerateMapFile="true"
 				OptimizeReferences="2"

+ 2 - 2
server/CGameHandler.cpp

@@ -1229,7 +1229,7 @@ void CGameHandler::moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker)
 			{
 				obj->onHeroLeave(h);
 			}
-			tmh.fowRevealed = gs->tilesToReveal(h->convertPosition(dst,false),h->getSightDistance(),h->tempOwner);
+			tmh.fowRevealed = gs->tilesToReveal(h->getSightCenter()+(tmh.end-tmh.start),h->getSightRadious(),h->tempOwner);
 			sendAndApply(&tmh);
 			tlog5 << "Moved to " <<tmh.end<<std::endl;
 
@@ -1256,7 +1256,7 @@ void CGameHandler::moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker)
 			}
 		}
 		tmh.result = instant+1;
-		tmh.fowRevealed = gs->tilesToReveal(h->convertPosition(dst,false),h->getSightDistance(),h->tempOwner);
+		tmh.fowRevealed = gs->tilesToReveal(h->getSightCenter()+(tmh.end-tmh.start),h->getSightRadious(),h->tempOwner);
 		sendAndApply(&tmh);
 	}
 }