Pārlūkot izejas kodu

- bugfixing:
-- fixed #942 and #898
-- removed dublicated code in dwelling loading, #900 is fixed
-- fixed roads rendering for #895

Ivan Savenko 13 gadi atpakaļ
vecāks
revīzija
46f48f0676

+ 1 - 0
client/CAdvmapInterface.cpp

@@ -1074,6 +1074,7 @@ townList(ADVOPT.tlistSize,ADVOPT.tlistX,ADVOPT.tlistY,ADVOPT.tlistAU,ADVOPT.tlis
 
 
 	setPlayer(LOCPLINT->playerID);
+	underground.block(!CGI->mh->map->twoLevel);
 }
 
 CAdvMapInt::~CAdvMapInt()

+ 1 - 1
client/CKingdomInterface.cpp

@@ -507,7 +507,7 @@ void CKingdomInterface::generateObjectsList(const std::vector<const CGObjectInst
 			OwnedObjectInfo &info = visibleObjects[object->subID];
 			if (info.count++ == 0)
 			{
-				info.hoverText = CGI->creh->creatures[CGI->objh->cregens[object->subID]]->namePl;
+				info.hoverText = CGI->creh->creatures[CGI->objh->cregens.find(object->subID)->second]->namePl;
 				info.imageID = object->subID;
 			}
 		}

+ 1 - 0
client/CPlayerInterface.cpp

@@ -2144,6 +2144,7 @@ void CPlayerInterface::acceptTurn()
 	else
 		adventureInt->select(towns.front());
 
+	adventureInt->updateNextHero(NULL);
 	adventureInt->showAll(screen);
 
 	if(settings["session"]["autoSkip"].Bool() && !LOCPLINT->shiftPressed())

+ 26 - 6
client/mapHandler.cpp

@@ -498,23 +498,43 @@ void CMapHandler::terrainRect( int3 top_tile, ui8 anim, const std::vector< std::
 			sr.h=sr.w=32;
 
 			//blit terrain with river/road
-			if(tile.terbitmap) { //if custom terrain graphic - use it
+			if(tile.terbitmap)
+			{ //if custom terrain graphic - use it
 				SDL_Rect temp_rect = genRect(sr.h, sr.w, 0, 0);
 				CSDL_Ext::blitSurface(tile.terbitmap, &temp_rect, extSurf, &sr);
-			} else //use default terrain graphic
+			}
+			else //use default terrain graphic
+			{
 				blitterWithRotation(terrainGraphics[tinfo.tertype][tinfo.terview],rtile, extSurf, sr, tinfo.siodmyTajemniczyBajt%4);
+			}
 			if(tinfo.nuine) //print river if present
+			{
 				blitterWithRotationAndAlpha(staticRiverDefs[tinfo.nuine-1]->ourImages[tinfo.rivDir].bitmap,rtile, extSurf, sr, (tinfo.siodmyTajemniczyBajt>>2)%4);
-			if(tinfo.malle) //print road if present
-				blitterWithRotationAndAlpha(roadDefs[tinfo.malle-1]->ourImages[tinfo.roadDir].bitmap,rtile, extSurf, sr, (tinfo.siodmyTajemniczyBajt>>4)%4);
+			}
+
+			//Roads are shifted by 16 pixels to bottom. We have to draw both parts separately
+			if (pos.y > 0 && map->terrain[pos.x][pos.y-1][pos.z].malle)
+			{ //part from top tile
+				const TerrainTile &topTile = map->terrain[pos.x][pos.y-1][pos.z];
+				Rect source(0, 16, 32, 16);
+				Rect dest(sr.x, sr.y, sr.w, sr.h/2);
+				blitterWithRotationAndAlpha(roadDefs[topTile.malle-1]->ourImages[topTile.roadDir].bitmap, source, extSurf, dest, (topTile.siodmyTajemniczyBajt>>4)%4);
+			}
+
+			if(tinfo.malle) //print road from this tile
+			{
+				Rect source(0, 0, 32, 32);
+				Rect dest(sr.x, sr.y+16, sr.w, sr.h/2);
+				blitterWithRotationAndAlpha(roadDefs[tinfo.malle-1]->ourImages[tinfo.roadDir].bitmap, source, extSurf, dest, (tinfo.siodmyTajemniczyBajt>>4)%4);
+			}
 
 			//blit objects
 			const std::vector < std::pair<const CGObjectInstance*,SDL_Rect> > &objects = tile.objects;
 			for(int h=0; h < objects.size(); ++h)
 			{
 				const CGObjectInstance *obj = objects[h].first;
-                if (!graphics->getDef(obj))
-                    processDef(obj->defInfo);
+				if (!graphics->getDef(obj))
+					processDef(obj->defInfo);
 
 				ui8 color = obj->tempOwner;
 

+ 50 - 81
lib/CGameState.cpp

@@ -591,100 +591,69 @@ std::pair<int,int> CGameState::pickObject (CGObjectInstance *obj)
 		return std::pair<int,int>(54, VLC->creh->pickRandomMonster(boost::ref(ran), 6));
 	case 164: //random monster lvl7
 		return std::pair<int,int>(54, VLC->creh->pickRandomMonster(boost::ref(ran), 7));
-	case 216: //random dwelling
+	case 216: //random dwellings
+	case 217:
+	case 218:
 		{
-			int faction = ran()%GameConstants::F_NUMBER;
 			CGDwelling * dwl = static_cast<CGDwelling*>(obj);
-			CCreGen2ObjInfo* info = static_cast<CCreGen2ObjInfo*>(dwl->info);
-			if (info->asCastle)
+			int faction;
+
+			//if castle alignment available
+			if (auto info = dynamic_cast<CCreGenAsCastleInfo*>(dwl->info))
 			{
-				for(ui32 i=0;i<map->objects.size();i++)
+				faction = ran()%GameConstants::F_NUMBER;
+				if (info->asCastle)
 				{
-					if(map->objects[i]->ID==77 && dynamic_cast<CGTownInstance*>(map->objects[i].get())->identifier == info->identifier)
+					for(ui32 i=0;i<map->objects.size();i++)
 					{
-						randomizeObject(map->objects[i]); //we have to randomize the castle first
-						faction = map->objects[i]->subID;
-						break;
-					}
-					else if(map->objects[i]->ID==GameConstants::TOWNI_TYPE && dynamic_cast<CGTownInstance*>(map->objects[i].get())->identifier == info->identifier)
-					{
-						faction = map->objects[i]->subID;
-						break;
+						if(map->objects[i]->ID==77 && dynamic_cast<CGTownInstance*>(map->objects[i].get())->identifier == info->identifier)
+						{
+							randomizeObject(map->objects[i]); //we have to randomize the castle first
+							faction = map->objects[i]->subID;
+							break;
+						}
+						else if(map->objects[i]->ID==GameConstants::TOWNI_TYPE && dynamic_cast<CGTownInstance*>(map->objects[i].get())->identifier == info->identifier)
+						{
+							faction = map->objects[i]->subID;
+							break;
+						}
 					}
 				}
-			}
-			else
-			{
-				while((!(info->castles[0]&(1<<faction))))
-				{
-					if((faction>7) && (info->castles[1]&(1<<(faction-8))))
-						break;
-					faction = ran()%GameConstants::F_NUMBER;
-				}
-			}
-			int level = ((info->maxLevel-info->minLevel) ? (ran()%(info->maxLevel-info->minLevel)+info->minLevel) : (info->minLevel));
-			int cid = VLC->townh->towns[faction].basicCreatures[level];
-			for(ui32 i=0;i<VLC->objh->cregens.size();i++)
-				if(VLC->objh->cregens[i]==cid)
-					return std::pair<int,int>(17,i);
-			tlog3 << "Cannot find a dwelling for creature "<< cid << std::endl;
-			return std::pair<int,int>(17,0);
-			delete dwl->info;
-			dwl->info = NULL;
-		}
-	case 217:
-		{
-			int faction = ran()%GameConstants::F_NUMBER;
-			CGDwelling * dwl = static_cast<CGDwelling*>(obj);
-			CCreGenObjInfo* info = static_cast<CCreGenObjInfo*>(dwl->info);
-			if (info->asCastle)
-			{
-				for(ui32 i=0;i<map->objects.size();i++)
+				else
 				{
-					if(map->objects[i]->ID==77 && dynamic_cast<CGTownInstance*>(map->objects[i].get())->identifier == info->identifier)
+					while((!(info->castles[0]&(1<<faction))))
 					{
-						randomizeObject(map->objects[i]); //we have to randomize the castle first
-						faction = map->objects[i]->subID;
-						break;
-					}
-					else if(map->objects[i]->ID==GameConstants::TOWNI_TYPE && dynamic_cast<CGTownInstance*>(map->objects[i].get())->identifier == info->identifier)
-					{
-						faction = map->objects[i]->subID;
-						break;
+						if((faction>7) && (info->castles[1]&(1<<(faction-8))))
+							break;
+						faction = ran()%GameConstants::F_NUMBER;
 					}
 				}
 			}
-			else
-			{
-				while((!(info->castles[0]&(1<<faction))))
-				{
-					if((faction>7) && (info->castles[1]&(1<<(faction-8))))
-						break;
-					faction = ran()%GameConstants::F_NUMBER;
-				}
-			}
-			int cid = VLC->townh->towns[faction].basicCreatures[obj->subID];
-			for(ui32 i=0;i<VLC->objh->cregens.size();i++)
-				if(VLC->objh->cregens[i]==cid)
-					return std::pair<int,int>(17,i);
-			tlog3 << "Cannot find a dwelling for creature "<<cid <<std::endl;
-			return std::pair<int,int>(17,0);
-			delete dwl->info;
-			dwl->info = NULL;
-		}
-	case 218:
-		{
-			CGDwelling * dwl = static_cast<CGDwelling*>(obj);
-			CCreGen3ObjInfo* info = static_cast<CCreGen3ObjInfo*>(dwl->info);
-			int level = ((info->maxLevel-info->minLevel) ? (ran()%(info->maxLevel-info->minLevel)+info->minLevel) : (info->minLevel));
-			int cid = VLC->townh->towns[obj->subID].basicCreatures[level];
-			for(ui32 i=0;i<VLC->objh->cregens.size();i++)
-				if(VLC->objh->cregens[i]==cid)
-					return std::pair<int,int>(17,i);
-			tlog3 << "Cannot find a dwelling for creature "<<cid <<std::endl;
-			return std::pair<int,int>(17,0);
+			else // castle alignment fixed
+				faction = obj->subID;
+
+			int level;
+
+			//if level set to range
+			if (auto info = dynamic_cast<CCreGenLeveledInfo*>(dwl->info))
+				level = ((info->maxLevel-info->minLevel) ? (ran()%(info->maxLevel-info->minLevel)+info->minLevel) : (info->minLevel));
+			else // fixed level
+				level = obj->subID;
+
 			delete dwl->info;
-			dwl->info = NULL;
+			dwl->info = nullptr;
+
+			std::pair<int,int> result(-1, -1);
+			int cid = VLC->townh->towns[faction].basicCreatures[level];
+
+			//NOTE: this will pick last dwelling with this creature (Mantis #900)
+			//check for block map equality is better but more complex solution
+			BOOST_FOREACH(auto &iter, VLC->objh->cregens)
+				if (iter.second == cid)
+					result = std::pair<int,int>(17, iter.first);
+
+			tlog3 << "Cannot find a dwelling for creature "<< cid << std::endl;
+			return result;
 		}
 	}
 	return std::pair<int,int>(-1,-1);

+ 0 - 5
lib/CObjectHandler.cpp

@@ -155,11 +155,6 @@ static void readBankLevel(const JsonNode &level, BankConfig &bc)
 void CObjectHandler::loadObjects()
 {
 	tlog5 << "\t\tReading cregens \n";
-	cregens.resize(110); //TODO: hardcoded value - change
-	for(size_t i=0; i < cregens.size(); ++i)
-	{
-		cregens[i]=-1;
-	}
 
 	const JsonNode config(GameConstants::DATA_DIR + "/config/dwellings.json");
 	BOOST_FOREACH(const JsonNode &dwelling, config["dwellings"].Vector())

+ 7 - 12
lib/CObjectHandler.h

@@ -412,30 +412,25 @@ class DLL_LINKAGE CSpecObjInfo
 {
 public:
 	virtual ~CSpecObjInfo(){};
+	ui8 player; //owner
 };
 
-class DLL_LINKAGE CCreGenObjInfo : public CSpecObjInfo
+class DLL_LINKAGE CCreGenAsCastleInfo : public virtual CSpecObjInfo
 {
 public:
-	ui8 player; //owner
 	bool asCastle;
 	ui32 identifier;
 	ui8 castles[2]; //allowed castles
 };
-class DLL_LINKAGE CCreGen2ObjInfo : public CSpecObjInfo
+
+class DLL_LINKAGE CCreGenLeveledInfo : public virtual CSpecObjInfo
 {
 public:
-	ui8 player; //owner
-	bool asCastle;
-	ui32 identifier;
-	ui8 castles[2]; //allowed castles
 	ui8 minLevel, maxLevel; //minimal and maximal level of creature in dwelling: <0, 6>
 };
-class DLL_LINKAGE CCreGen3ObjInfo : public CSpecObjInfo
+
+class DLL_LINKAGE CCreGenLeveledCastleInfo : public CCreGenAsCastleInfo, public CCreGenLeveledInfo
 {
-public:
-	ui8 player; //owner
-	ui8 minLevel, maxLevel; //minimal and maximal level of creature in dwelling: <0, 6>
 };
 
 class DLL_LINKAGE CGDwelling : public CArmedInstance
@@ -1318,7 +1313,7 @@ struct BankConfig
 class DLL_LINKAGE CObjectHandler
 {
 public:
-	std::vector<si32> cregens; //type 17. dwelling subid -> creature ID
+	std::map<si32, si32> cregens; //type 17. dwelling subid -> creature ID
 	std::map <ui32, std::vector < ConstTransitivePtr<BankConfig> > > banksInfo; //[index][preset]
 	std::map <ui32, std::string> creBanksNames; //[crebank index] -> name of this creature bank
 	std::vector<ui32> resVals; //default values of resources in gold

+ 29 - 44
lib/map.cpp

@@ -1675,60 +1675,45 @@ void Mapa::readObjects( const ui8 * bufor, int &i)
 				grailRadious = read_le_u32(bufor + i); i+=4;
 				continue;
 			}
-		case 217:
+		//dwellings
+		case 216: //same as castle + level range
+		case 217: //same as castle
+		case 218: //level range
 			{
 				nobj = new CGDwelling();
-				CCreGenObjInfo * spec = new CCreGenObjInfo;
-				spec->player = read_le_u32(bufor + i); i+=4;
-				spec->identifier =  read_le_u32(bufor + i); i+=4;
-				if(!spec->identifier)
-				{
-					spec->asCastle = false;
-					spec->castles[0] = bufor[i]; ++i;
-					spec->castles[1] = bufor[i]; ++i;
-				}
-				else
+				CSpecObjInfo * spec = nullptr;
+				switch(defInfo->id)
 				{
-					spec->asCastle = true;
+					break; case 216: spec = new CCreGenLeveledCastleInfo;
+					break; case 217: spec = new CCreGenAsCastleInfo;
+					break; case 218: spec = new CCreGenLeveledInfo;
 				}
-				nobj->setOwner(spec->player);
-				static_cast<CGDwelling*>(nobj)->info = spec;
-				break;
-			}
-		case 216:
-			{
-				nobj = new CGDwelling();
-				CCreGen2ObjInfo * spec = new CCreGen2ObjInfo;
+
 				spec->player = read_le_u32(bufor + i); i+=4;
-				spec->identifier =  read_le_u32(bufor + i); i+=4;
-				if(!spec->identifier)
+				//216 and 217
+				if (auto castleSpec = dynamic_cast<CCreGenAsCastleInfo*>(spec))
 				{
-					spec->asCastle = false;
-					spec->castles[0] = bufor[i]; ++i;
-					spec->castles[1] = bufor[i]; ++i;
+					castleSpec->identifier =  read_le_u32(bufor + i); i+=4;
+					if(!castleSpec->identifier)
+					{
+						castleSpec->asCastle = false;
+						castleSpec->castles[0] = bufor[i]; ++i;
+						castleSpec->castles[1] = bufor[i]; ++i;
+					}
+					else
+					{
+						castleSpec->asCastle = true;
+					}
 				}
 				else
+					i+=3; //only for 218
+
+				//216 and 218
+				if (auto lvlSpec = dynamic_cast<CCreGenLeveledInfo*>(spec))
 				{
-					spec->asCastle = true;
+					lvlSpec->minLevel = std::max(bufor[i], ui8(1)); ++i;
+					lvlSpec->maxLevel = std::min(bufor[i], ui8(7)); ++i;
 				}
-				spec->minLevel = bufor[i]; ++i;
-				spec->maxLevel = bufor[i]; ++i;
-				nobj->setOwner(spec->player);
-				static_cast<CGDwelling*>(nobj)->info = spec;
-				break;
-			}
-		case 218:
-			{
-				nobj = new CGDwelling();
-				CCreGen3ObjInfo * spec = new CCreGen3ObjInfo;
-				spec->player = bufor[i]; ++i;
-				i+=3;
-				spec->minLevel = bufor[i]; ++i;
-				spec->maxLevel = bufor[i]; ++i;
-				if(spec->maxLevel>7)
-					spec->maxLevel = 7;
-				if(spec->minLevel<1)
-					spec->minLevel = 1;
 				nobj->setOwner(spec->player);
 				static_cast<CGDwelling*>(nobj)->info = spec;
 				break;