mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Correct placement of subterranean gates.
This commit is contained in:
		| @@ -8,7 +8,7 @@ | ||||
| 		{ | ||||
| 			"1" : | ||||
| 			{ | ||||
| 				"type" : "playerStart", "size" : 1, "owner" : 1, | ||||
| 				"type" : "playerStart", "size" : 2, "owner" : 1, | ||||
| 				"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true, | ||||
| 				"monsters" : "normal", | ||||
| 				"mines" : {"wood" : 1, "ore" : 1, "gems" : 1, "crystal" : 1, "sulfur" : 1, "mercury" : 1}, | ||||
| @@ -19,7 +19,7 @@ | ||||
| 			}, | ||||
| 			"2" : | ||||
| 			{ | ||||
| 				"type" : "playerStart", "size" : 1, "owner" : 2, | ||||
| 				"type" : "playerStart", "size" : 2, "owner" : 2, | ||||
| 				"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true, | ||||
| 				"monsters" : "normal", | ||||
| 				"minesLikeZone" : 1, | ||||
| @@ -27,7 +27,7 @@ | ||||
| 			}, | ||||
| 			"3" : | ||||
| 			{ | ||||
| 				"type" : "playerStart", "size" : 1, "owner" : 3, | ||||
| 				"type" : "playerStart", "size" : 2, "owner" : 3, | ||||
| 				"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true, | ||||
| 				"monsters" : "normal", | ||||
| 				"minesLikeZone" : 1, | ||||
| @@ -35,7 +35,7 @@ | ||||
| 			}, | ||||
| 			"4" : | ||||
| 			{ | ||||
| 				"type" : "playerStart", "size" : 1, "owner" : 4, | ||||
| 				"type" : "playerStart", "size" : 2, "owner" : 4, | ||||
| 				"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true, | ||||
| 				"monsters" : "normal", | ||||
| 				"minesLikeZone" : 1, | ||||
| @@ -43,7 +43,7 @@ | ||||
| 			}, | ||||
| 			"5" : | ||||
| 			{ | ||||
| 				"type" : "treasure", "size" : 2, "terrainTypes" : [ "sand" ], "matchTerrainToTown" : false, | ||||
| 				"type" : "treasure", "size" : 3, "terrainTypes" : [ "sand" ], "matchTerrainToTown" : false, | ||||
| 				"neutralTowns" : { "castles" : 1 }, | ||||
| 				"monsters" : "strong", | ||||
| 				"mines" : {"gold" : 2}, | ||||
| @@ -132,7 +132,7 @@ | ||||
| 		{ | ||||
| 			"1" : | ||||
| 			{ | ||||
| 				"type" : "playerStart", "size" : 3, "owner" : 1, | ||||
| 				"type" : "playerStart", "size" : 2, "owner" : 1, | ||||
| 				"playerTowns" : { "castles" : 1 }, | ||||
| 				"monsters" : "normal", | ||||
| 				"mines" : {"wood" : 1, "ore" : 1}, | ||||
| @@ -143,7 +143,7 @@ | ||||
| 			}, | ||||
| 			"2" : | ||||
| 			{ | ||||
| 				"type" : "playerStart", "size" : 3, "owner" : 2, | ||||
| 				"type" : "playerStart", "size" : 2, "owner" : 2, | ||||
| 				"playerTowns" : { "castles" : 1 }, | ||||
| 				"monsters" : "normal", | ||||
| 				"minesLikeZone" : 1, | ||||
| @@ -151,7 +151,7 @@ | ||||
| 			}, | ||||
| 			"3" : | ||||
| 			{ | ||||
| 				"type" : "playerStart", "size" : 3, "owner" : 3, | ||||
| 				"type" : "playerStart", "size" : 2, "owner" : 3, | ||||
| 				"playerTowns" : { "castles" : 1 }, | ||||
| 				"monsters" : "normal", | ||||
| 				"minesLikeZone" : 1, | ||||
|   | ||||
| @@ -241,21 +241,52 @@ void CMapGenerator::createConnections() | ||||
| 		auto otherZoneTiles = zoneB->getTileInfo(); | ||||
| 		//auto otherZoneCenter = zoneB->getPos(); | ||||
|  | ||||
| 		for (auto tile : tiles) | ||||
| 		if (zoneA->getPos().z == zoneB->getPos().z) | ||||
| 		{ | ||||
| 			foreach_neighbour (tile, [&guardPos, tile, &otherZoneTiles](int3 &pos) | ||||
| 			for (auto tile : tiles) | ||||
| 			{ | ||||
| 				if (vstd::contains(otherZoneTiles, pos)) | ||||
| 					guardPos = tile; | ||||
| 			}); | ||||
| 			if (guardPos.valid()) | ||||
| 				if (isBlocked(tile)) //tiles may be occupied by subterranean gates already placed | ||||
| 					continue; | ||||
| 				foreach_neighbour (tile, [&guardPos, tile, &otherZoneTiles, this](int3 &pos) | ||||
| 				{ | ||||
| 					if (vstd::contains(otherZoneTiles, pos) && !this->isBlocked(pos)) | ||||
| 						guardPos = tile; | ||||
| 				}); | ||||
| 				if (guardPos.valid()) | ||||
| 				{ | ||||
| 					setOccupied (guardPos, ETileType::FREE); //just in case monster is too weak to spawn | ||||
| 					zoneA->addMonster (this, guardPos, connection.getGuardStrength()); //TODO: set value according to template | ||||
| 					//zones can make paths only in their own area | ||||
| 					zoneA->crunchPath (this, guardPos, zoneA->getPos(), zoneA->getId(), zoneA->getFreePaths()); //make connection towards our zone center | ||||
| 					zoneB->crunchPath (this, guardPos, zoneB->getPos(), zoneB->getId(), zoneB->getFreePaths()); //make connection towards other zone center | ||||
| 					break; //we're done with this connection | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		else //create subterranean gates between two zones | ||||
| 		{	 | ||||
| 			//find point just in the middle | ||||
| 			int3 posA = zoneA->getPos(); | ||||
| 			int3 posB = zoneB->getPos(); | ||||
| 			float3 offset (posB.x - posA.x, posB.y - posA.y, 0); | ||||
|  | ||||
| 			offset /= posB.dist2d(posA); //get unit vector | ||||
| 			//use reduced size of underground zone - make sure gate does not stand on rock | ||||
| 			offset *= ((posA.z ? zoneA->getSize() : zoneB->getSize()) - 2); | ||||
| 			int3 tile = posA + int3(offset.x, offset.y, 0); | ||||
| 			int3 otherTile = tile; | ||||
| 			otherTile.z = posB.z; | ||||
|  | ||||
| 			if (vstd::contains(tiles, tile) && vstd::contains(otherZoneTiles, otherTile)) | ||||
| 			{ | ||||
| 				setOccupied (guardPos, ETileType::FREE); //just in case monster is too weak to spawn | ||||
| 				zoneA->addMonster (this, guardPos, connection.getGuardStrength()); //TODO: set value according to template | ||||
| 				//zones can make paths only in their own area | ||||
| 				zoneA->crunchPath (this, guardPos, zoneA->getPos(), zoneA->getId(), zoneA->getFreePaths()); //make connection towards our zone center | ||||
| 				zoneB->crunchPath (this, guardPos, zoneB->getPos(), zoneB->getId(), zoneB->getFreePaths()); //make connection towards other zone center | ||||
| 				break; //we're done with this connection | ||||
| 				auto gate1 = new CGTeleport; | ||||
| 				gate1->ID = Obj::SUBTERRANEAN_GATE; | ||||
| 				gate1->subID = 0; | ||||
| 				zoneA->placeAndGuardObject(this, gate1, tile, connection.getGuardStrength()); | ||||
| 				auto gate2 = new CGTeleport(*gate1); | ||||
| 				zoneB->placeAndGuardObject(this, gate2, otherTile, connection.getGuardStrength()); | ||||
|  | ||||
| 				continue; //we are done, go to next connection | ||||
| 			} | ||||
| 		} | ||||
| 		if (!guardPos.valid()) | ||||
|   | ||||
| @@ -354,8 +354,13 @@ std::set<int3> CRmgTemplateZone::getTileInfo () const | ||||
| 	return tileinfo; | ||||
| } | ||||
|  | ||||
| void CRmgTemplateZone::discardDistantTiles (int distance) | ||||
| void CRmgTemplateZone::discardDistantTiles (CMapGenerator* gen, int distance) | ||||
| { | ||||
| 	for (auto tile : tileinfo) | ||||
| 	{ | ||||
| 		if (tile.dist2d(this->pos) > distance) | ||||
| 			gen->setOccupied(tile, ETileType::USED); | ||||
| 	} | ||||
| 	vstd::erase_if (tileinfo, [distance, this](const int3 &tile) -> bool | ||||
| 	{ | ||||
| 		return tile.dist2d(this->pos) > distance; | ||||
| @@ -828,6 +833,12 @@ void CRmgTemplateZone::initTerrainType (CMapGenerator* gen) | ||||
| 		terrainType = *RandomGeneratorUtil::nextItem(terrainTypes, gen->rand); | ||||
|  | ||||
| 	//paint zone with matching terrain | ||||
|  | ||||
| 	paintZoneTerrain (gen, terrainType); | ||||
| } | ||||
|  | ||||
| void CRmgTemplateZone::paintZoneTerrain (CMapGenerator* gen, ETerrainType terrainType) | ||||
| { | ||||
| 	std::vector<int3> tiles; | ||||
| 	for (auto tile : tileinfo) | ||||
| 	{ | ||||
| @@ -1132,9 +1143,10 @@ void CRmgTemplateZone::checkAndPlaceObject(CMapGenerator* gen, CGObjectInstance* | ||||
|  | ||||
| 	if (object->appearance.id == Obj::NO_OBJ) | ||||
| 	{ | ||||
| 		auto templates = VLC->objtypeh->getHandlerFor(object->ID, object->subID)->getTemplates(gen->map->getTile(pos).terType); | ||||
| 		auto terrainType = gen->map->getTile(pos).terType; | ||||
| 		auto templates = VLC->objtypeh->getHandlerFor(object->ID, object->subID)->getTemplates(terrainType); | ||||
| 		if (templates.empty()) | ||||
| 			throw rmgException(boost::to_string(boost::format("Did not find graphics for object (%d,%d) at %s") %object->ID %object->subID %pos)); | ||||
| 			throw rmgException(boost::to_string(boost::format("Did not find graphics for object (%d,%d) at %s (terrain %d)") %object->ID %object->subID %pos %terrainType)); | ||||
| 	 | ||||
| 		object->appearance = templates.front(); | ||||
| 	} | ||||
| @@ -1168,6 +1180,12 @@ void CRmgTemplateZone::placeObject(CMapGenerator* gen, CGObjectInstance* object, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CRmgTemplateZone::placeAndGuardObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, si32 str) | ||||
| { | ||||
| 	placeObject(gen, object, pos); | ||||
| 	guardObject(gen, object, str); | ||||
| } | ||||
|  | ||||
| std::vector<int3> CRmgTemplateZone::getAccessibleOffsets (CMapGenerator* gen, CGObjectInstance* object) | ||||
| { | ||||
| 	//get all tiles from which this object can be accessed | ||||
|   | ||||
| @@ -128,7 +128,7 @@ public: | ||||
|  | ||||
| 	void addTile (const int3 &pos); | ||||
| 	std::set<int3> getTileInfo () const; | ||||
| 	void discardDistantTiles (int distance); | ||||
| 	void discardDistantTiles (CMapGenerator* gen, int distance); | ||||
|  | ||||
| 	void addRequiredObject(CGObjectInstance * obj, si32 guardStrength=0); | ||||
| 	bool addMonster(CMapGenerator* gen, int3 &pos, si32 strength); | ||||
| @@ -136,6 +136,7 @@ public: | ||||
| 	bool fill (CMapGenerator* gen); | ||||
| 	bool placeMines (CMapGenerator* gen); | ||||
| 	void initTownType (CMapGenerator* gen); | ||||
| 	void paintZoneTerrain (CMapGenerator* gen, ETerrainType terrainType); | ||||
| 	void initTerrainType (CMapGenerator* gen); | ||||
| 	void createBorder(CMapGenerator* gen); | ||||
| 	void fractalize(CMapGenerator* gen); | ||||
| @@ -155,6 +156,8 @@ public: | ||||
|  | ||||
| 	ObjectInfo getRandomObject (CMapGenerator* gen, ui32 value); | ||||
|  | ||||
| 	void placeAndGuardObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, si32 str); | ||||
|  | ||||
| private: | ||||
| 	//template info | ||||
| 	TRmgTemplateZoneId id; | ||||
|   | ||||
| @@ -247,7 +247,13 @@ void CZonePlacer::assignZones(shared_ptr<CMapGenOptions> mapGenOptions) | ||||
|  | ||||
| 		//TODO: similiar for islands | ||||
| 		if (zone.second->getPos().z) | ||||
| 			zone.second->discardDistantTiles(zone.second->getSize()); | ||||
| 		{ | ||||
| 			zone.second->discardDistantTiles(gen, zone.second->getSize()); | ||||
|  | ||||
| 			//make sure that terrain inside zone is not a rock | ||||
| 			//FIXME: reorder actions? | ||||
| 			zone.second->paintZoneTerrain (gen, ETerrainType::SUBTERRANEAN); | ||||
| 		} | ||||
| 	} | ||||
| 	logGlobal->infoStream() << "Finished zone colouring"; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user