mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Implemented View Earth / View Air spells
This commit is contained in:
		| @@ -489,7 +489,7 @@ void AIGateway::showMarketWindow(const IMarket * market, const CGHeroInstance * | ||||
| 	NET_EVENT_HANDLER; | ||||
| } | ||||
|  | ||||
| void AIGateway::showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions) | ||||
| void AIGateway::showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) | ||||
| { | ||||
| 	//TODO: AI support for ViewXXX spell | ||||
| 	LOG_TRACE(logAi); | ||||
|   | ||||
| @@ -165,7 +165,7 @@ public: | ||||
| 	void buildChanged(const CGTownInstance * town, BuildingID buildingID, int what) override; | ||||
| 	void heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bool gain) override; | ||||
| 	void showMarketWindow(const IMarket * market, const CGHeroInstance * visitor) override; | ||||
| 	void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions) override; | ||||
| 	void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) override; | ||||
| 	boost::optional<BattleAction> makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState) override; | ||||
|  | ||||
| 	void battleStart(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool side) override; | ||||
|   | ||||
| @@ -572,7 +572,7 @@ void VCAI::showMarketWindow(const IMarket * market, const CGHeroInstance * visit | ||||
| 	NET_EVENT_HANDLER; | ||||
| } | ||||
|  | ||||
| void VCAI::showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions) | ||||
| void VCAI::showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) | ||||
| { | ||||
| 	//TODO: AI support for ViewXXX spell | ||||
| 	LOG_TRACE(logAi); | ||||
|   | ||||
| @@ -198,7 +198,7 @@ public: | ||||
| 	void buildChanged(const CGTownInstance * town, BuildingID buildingID, int what) override; | ||||
| 	void heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bool gain) override; | ||||
| 	void showMarketWindow(const IMarket * market, const CGHeroInstance * visitor) override; | ||||
| 	void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions) override; | ||||
| 	void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) override; | ||||
|  | ||||
| 	void battleStart(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool side) override; | ||||
| 	void battleEnd(const BattleResult * br) override; | ||||
|   | ||||
| @@ -1829,7 +1829,7 @@ void CPlayerInterface::showPuzzleMap() | ||||
|  | ||||
| void CPlayerInterface::viewWorldMap() | ||||
| { | ||||
| 	adventureInt->changeMode(EAdvMapMode::WORLD_VIEW); | ||||
| 	adventureInt->openWorldView(); | ||||
| } | ||||
|  | ||||
| void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellID) | ||||
| @@ -1843,14 +1843,6 @@ void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellI | ||||
| 		paths.erasePath(caster); | ||||
|  | ||||
| 	const spells::Spell * spell = CGI->spells()->getByIndex(spellID); | ||||
|  | ||||
| 	if(spellID == SpellID::VIEW_EARTH) | ||||
| 	{ | ||||
| 		//TODO: implement on server side | ||||
| 		const auto level = caster->getSpellSchoolLevel(spell); | ||||
| 		adventureInt->worldViewOptions.showAllTerrain = (level > 2); | ||||
| 	} | ||||
|  | ||||
| 	auto castSoundPath = spell->getCastSound(); | ||||
| 	if(!castSoundPath.empty()) | ||||
| 		CCS->soundh->playSound(castSoundPath); | ||||
| @@ -2369,14 +2361,10 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path) | ||||
| 	setMovementStatus(false); | ||||
| } | ||||
|  | ||||
| void CPlayerInterface::showWorldViewEx(const std::vector<ObjectPosInfo>& objectPositions) | ||||
| void CPlayerInterface::showWorldViewEx(const std::vector<ObjectPosInfo>& objectPositions, bool showTerrain) | ||||
| { | ||||
| 	EVENT_HANDLER_CALLED_BY_CLIENT; | ||||
| 	//TODO: showWorldViewEx | ||||
|  | ||||
| 	std::copy(objectPositions.begin(), objectPositions.end(), std::back_inserter(adventureInt->worldViewOptions.iconPositions)); | ||||
|  | ||||
| 	viewWorldMap(); | ||||
| 	adventureInt->openWorldView(objectPositions, showTerrain ); | ||||
| } | ||||
|  | ||||
| void CPlayerInterface::updateAmbientSounds(bool resetAll) | ||||
|   | ||||
| @@ -210,7 +210,7 @@ public: | ||||
| 	void showComp(const Component &comp, std::string message) override; //display component in the advmapint infobox | ||||
| 	void saveGame(BinarySerializer & h, const int version) override; //saving | ||||
| 	void loadGame(BinaryDeserializer & h, const int version) override; //loading | ||||
| 	void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions) override; | ||||
| 	void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) override; | ||||
|  | ||||
| 	//for battles | ||||
| 	void actionFinished(const BattleAction& action) override;//occurs AFTER action taken by active stack or by the hero | ||||
|   | ||||
| @@ -883,7 +883,7 @@ void ApplyClientNetPackVisitor::visitAdvmapSpellCast(AdvmapSpellCast & pack) | ||||
|  | ||||
| void ApplyClientNetPackVisitor::visitShowWorldViewEx(ShowWorldViewEx & pack) | ||||
| { | ||||
| 	callOnlyThatInterface(cl, pack.player, &CGameInterface::showWorldViewEx, pack.objectPositions); | ||||
| 	callOnlyThatInterface(cl, pack.player, &CGameInterface::showWorldViewEx, pack.objectPositions, pack.showTerrain); | ||||
| } | ||||
|  | ||||
| void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack) | ||||
|   | ||||
| @@ -236,7 +236,7 @@ CAdvMapInt::CAdvMapInt(): | ||||
|  | ||||
| 	activeMapPanel = panelMain; | ||||
|  | ||||
| 	changeMode(EAdvMapMode::NORMAL); | ||||
| 	exitWorldView(); | ||||
|  | ||||
| 	underground->block(!CGI->mh->getMap()->twoLevel); | ||||
| 	questlog->block(!CGI->mh->getMap()->quests.size()); | ||||
| @@ -252,7 +252,7 @@ void CAdvMapInt::fshowOverview() | ||||
|  | ||||
| void CAdvMapInt::fworldViewBack() | ||||
| { | ||||
| 	changeMode(EAdvMapMode::NORMAL); | ||||
| 	exitWorldView(); | ||||
|  | ||||
| 	auto hero = curHero(); | ||||
| 	if (hero) | ||||
| @@ -262,17 +262,17 @@ void CAdvMapInt::fworldViewBack() | ||||
| void CAdvMapInt::fworldViewScale1x() | ||||
| { | ||||
| 	// TODO set corresponding scale button to "selected" mode | ||||
| 	changeMode(EAdvMapMode::WORLD_VIEW, 7); // 7 pixels per tile | ||||
| 	openWorldView(7); | ||||
| } | ||||
|  | ||||
| void CAdvMapInt::fworldViewScale2x() | ||||
| { | ||||
| 	changeMode(EAdvMapMode::WORLD_VIEW, 11); // 11 pixels per tile | ||||
| 	openWorldView(11); | ||||
| } | ||||
|  | ||||
| void CAdvMapInt::fworldViewScale4x() | ||||
| { | ||||
| 	changeMode(EAdvMapMode::WORLD_VIEW, 16); // 16 pixels per tile | ||||
| 	openWorldView(16); | ||||
| } | ||||
|  | ||||
| void CAdvMapInt::fswitchLevel() | ||||
| @@ -666,7 +666,7 @@ void CAdvMapInt::centerOn(const CGObjectInstance * obj, bool fade) | ||||
|  | ||||
| void CAdvMapInt::keyReleased(const SDL_Keycode &key) | ||||
| { | ||||
| 	if (mode == EAdvMapMode::WORLD_VIEW) | ||||
| 	if (mode != EAdvMapMode::NORMAL) | ||||
| 		return; | ||||
|  | ||||
| 	switch (key) | ||||
| @@ -694,7 +694,7 @@ void CAdvMapInt::keyReleased(const SDL_Keycode &key) | ||||
|  | ||||
| void CAdvMapInt::keyPressed(const SDL_Keycode & key) | ||||
| { | ||||
| 	if (mode == EAdvMapMode::WORLD_VIEW) | ||||
| 	if (mode != EAdvMapMode::NORMAL) | ||||
| 		return; | ||||
|  | ||||
| 	const CGHeroInstance *h = curHero(); //selected hero | ||||
| @@ -1460,62 +1460,49 @@ void CAdvMapInt::quickCombatUnlock() | ||||
| 		activate(); | ||||
| } | ||||
|  | ||||
| void CAdvMapInt::changeMode(EAdvMapMode newMode) | ||||
| void CAdvMapInt::exitWorldView() | ||||
| { | ||||
| 	changeMode(newMode, 11); | ||||
| 	mode = EAdvMapMode::NORMAL; | ||||
|  | ||||
| 	panelMain->activate(); | ||||
| 	panelWorldView->deactivate(); | ||||
| 	activeMapPanel = panelMain; | ||||
|  | ||||
| 	townList->activate(); | ||||
| 	heroList->activate(); | ||||
| 	infoBar->activate(); | ||||
|  | ||||
| 	redraw(); | ||||
| 	terrain->setTileSize(32); | ||||
| 	terrain->setTerrainVisibility(false); | ||||
| 	terrain->setOverlayVisibility({}); | ||||
| } | ||||
|  | ||||
| void CAdvMapInt::changeMode(EAdvMapMode newMode, int tileSize) | ||||
| void CAdvMapInt::openWorldView(int tileSize) | ||||
| { | ||||
| 	if (mode != newMode) | ||||
| 	{ | ||||
| 		mode = newMode; | ||||
| 	mode = EAdvMapMode::WORLD_VIEW; | ||||
| 	panelMain->deactivate(); | ||||
| 	panelWorldView->activate(); | ||||
|  | ||||
| 		switch (mode) | ||||
| 		{ | ||||
| 		case EAdvMapMode::NORMAL: | ||||
| 			panelMain->activate(); | ||||
| 			panelWorldView->deactivate(); | ||||
| 			activeMapPanel = panelMain; | ||||
| 	activeMapPanel = panelWorldView; | ||||
|  | ||||
| 			townList->activate(); | ||||
| 			heroList->activate(); | ||||
| 			infoBar->activate(); | ||||
| 	townList->deactivate(); | ||||
| 	heroList->deactivate(); | ||||
| 	infoBar->showSelection(); // to prevent new day animation interfering world view mode | ||||
| 	infoBar->deactivate(); | ||||
|  | ||||
| 			worldViewOptions.clear(); | ||||
|  | ||||
| 			break; | ||||
| 		case EAdvMapMode::WORLD_VIEW: | ||||
| 			panelMain->deactivate(); | ||||
| 			panelWorldView->activate(); | ||||
|  | ||||
| 			activeMapPanel = panelWorldView; | ||||
|  | ||||
| 			townList->deactivate(); | ||||
| 			heroList->deactivate(); | ||||
| 			infoBar->showSelection(); // to prevent new day animation interfering world view mode | ||||
| 			infoBar->deactivate(); | ||||
|  | ||||
|  | ||||
| 			break; | ||||
| 		} | ||||
| 		redraw(); | ||||
| 	} | ||||
|  | ||||
| 	if(mode == EAdvMapMode::NORMAL) | ||||
| 		terrain->setTileSize(32); | ||||
| 	if(mode == EAdvMapMode::WORLD_VIEW) | ||||
| 		terrain->setTileSize(tileSize); | ||||
| 	redraw(); | ||||
| 	terrain->setTileSize(tileSize); | ||||
| } | ||||
|  | ||||
| CAdvMapInt::WorldViewOptions::WorldViewOptions() | ||||
| void CAdvMapInt::openWorldView() | ||||
| { | ||||
| 	clear(); | ||||
| 	openWorldView(11); | ||||
| } | ||||
|  | ||||
| void CAdvMapInt::WorldViewOptions::clear() | ||||
| void CAdvMapInt::openWorldView(const std::vector<ObjectPosInfo>& objectPositions, bool showTerrain) | ||||
| { | ||||
| 	showAllTerrain = false; | ||||
|  | ||||
| 	iconPositions.clear(); | ||||
| 	openWorldView(11); | ||||
| 	terrain->setTerrainVisibility(showTerrain); | ||||
| 	terrain->setOverlayVisibility(objectPositions); | ||||
| } | ||||
|   | ||||
| @@ -61,21 +61,12 @@ private: | ||||
| 	enum EDirections {LEFT=1, RIGHT=2, UP=4, DOWN=8}; | ||||
| 	enum EGameStates {NA, INGAME, WAITING}; | ||||
|  | ||||
| 	struct WorldViewOptions | ||||
| 	{ | ||||
| 		bool showAllTerrain; //for expert viewEarth | ||||
| 		std::vector<ObjectPosInfo> iconPositions; | ||||
| 		WorldViewOptions(); | ||||
| 		void clear(); | ||||
| 	}; | ||||
|  | ||||
| 	bool swipeEnabled; | ||||
| 	bool swipeMovementRequested; | ||||
| 	Point swipeTargetPosition; | ||||
|  | ||||
| 	EGameStates state; | ||||
| 	EAdvMapMode mode; | ||||
| 	WorldViewOptions worldViewOptions; | ||||
|  | ||||
| 	/// Currently selected object, can be town, hero or null | ||||
| 	const CArmedInstance *selection; | ||||
| @@ -211,9 +202,17 @@ public: | ||||
| 	/// returs visible section of game map, in tiles | ||||
| 	Rect terrainAreaTiles() const; | ||||
|  | ||||
| 	/// changes current adventure map mode; used to switch between default view and world view; scale is ignored if EAdvMapMode == NORMAL | ||||
| 	void changeMode(EAdvMapMode newMode); | ||||
| 	void changeMode(EAdvMapMode newMode, int tileSize); | ||||
| 	/// exits currently opened world view mode and returns to normal map | ||||
| 	void exitWorldView(); | ||||
|  | ||||
| 	/// opens world view at default scale | ||||
| 	void openWorldView(); | ||||
|  | ||||
| 	/// opens world view at specific scale | ||||
| 	void openWorldView(int tileSize); | ||||
|  | ||||
| 	/// opens world view with specific info, e.g. after View Earth/Air is shown | ||||
| 	void openWorldView(const std::vector<ObjectPosInfo>& objectPositions, bool showTerrain); | ||||
| }; | ||||
|  | ||||
| extern std::shared_ptr<CAdvMapInt> adventureInt; | ||||
|   | ||||
| @@ -29,7 +29,7 @@ CAdventureOptions::CAdventureOptions() | ||||
| 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); | ||||
|  | ||||
| 	viewWorld = std::make_shared<CButton>(Point(24, 23), "ADVVIEW.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_v); | ||||
| 	viewWorld->addCallback(std::bind(&CPlayerInterface::viewWorldMap, LOCPLINT)); | ||||
| 	viewWorld->addCallback( [] { LOCPLINT->viewWorldMap(); }); | ||||
|  | ||||
| 	exit = std::make_shared<CButton>(Point(204, 313), "IOK6432.DEF", CButton::tooltip(), std::bind(&CAdventureOptions::close, this), SDLK_RETURN); | ||||
| 	exit->assignedKeys.insert(SDLK_ESCAPE); | ||||
|   | ||||
| @@ -240,3 +240,14 @@ void CTerrainRect::setTileSize(int sizePixels) | ||||
| { | ||||
| 	renderer->getController()->setTileSize(Point(sizePixels, sizePixels)); | ||||
| } | ||||
|  | ||||
|  | ||||
| void CTerrainRect::setTerrainVisibility(bool showAllTerrain) | ||||
| { | ||||
| 	renderer->getController()->setTerrainVisibility(showAllTerrain); | ||||
| } | ||||
|  | ||||
| void CTerrainRect::setOverlayVisibility(const std::vector<ObjectPosInfo> & objectPositions) | ||||
| { | ||||
| 	renderer->getController()->setOverlayVisibility(objectPositions); | ||||
| } | ||||
|   | ||||
| @@ -14,6 +14,7 @@ | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_BEGIN | ||||
| struct CGPath; | ||||
| struct ObjectPosInfo; | ||||
| VCMI_LIB_NAMESPACE_END | ||||
|  | ||||
| class MapView; | ||||
| @@ -51,6 +52,9 @@ public: | ||||
| 	void setLevel(int level); | ||||
| 	void setTileSize(int sizePixels); | ||||
|  | ||||
| 	void setTerrainVisibility(bool showAllTerrain); | ||||
| 	void setOverlayVisibility(const std::vector<ObjectPosInfo> & objectPositions); | ||||
|  | ||||
| 	Point getViewCenter(); | ||||
| 	int getLevel(); | ||||
|  | ||||
|   | ||||
| @@ -53,11 +53,14 @@ public: | ||||
| 	virtual Point objectImageOffset(ObjectInstanceID objectID, const int3 & coordinates) const = 0; | ||||
|  | ||||
| 	/// returns object animation transparency. IF set to 0, object will not be visible | ||||
| 	virtual double objectTransparency(ObjectInstanceID objectID) const = 0; | ||||
| 	virtual double objectTransparency(ObjectInstanceID objectID, const int3 &coordinates) const = 0; | ||||
|  | ||||
| 	/// returns animation frame for selected object | ||||
| 	virtual size_t objectImageIndex(ObjectInstanceID objectID, size_t groupSize) const = 0; | ||||
|  | ||||
| 	/// returns index of image for overlay on specific tile, or numeric_limits::max if none | ||||
| 	virtual size_t overlayImageIndex(const int3 & coordinates) const = 0; | ||||
|  | ||||
| 	/// returns animation frame for terrain | ||||
| 	virtual size_t terrainImageIndex(size_t groupSize) const = 0; | ||||
|  | ||||
|   | ||||
| @@ -444,7 +444,7 @@ void MapRendererObjects::renderImage(const IMapRendererContext & context, Canvas | ||||
| 	if(!image) | ||||
| 		return; | ||||
|  | ||||
| 	auto transparency = static_cast<uint8_t>(std::round(255 * context.objectTransparency(object->id))); | ||||
| 	auto transparency = static_cast<uint8_t>(std::round(255 * context.objectTransparency(object->id, coordinates))); | ||||
|  | ||||
| 	if (transparency == 0) | ||||
| 		return; | ||||
| @@ -507,7 +507,7 @@ void MapRendererDebug::renderTile(const IMapRendererContext & context, Canvas & | ||||
| 		{ | ||||
| 			const auto * object = context.getObject(objectID); | ||||
|  | ||||
| 			if (context.objectTransparency(objectID) > 0) | ||||
| 			if (context.objectTransparency(objectID, coordinates) > 0) | ||||
| 			{ | ||||
| 				visitable |= object->visitableAt(coordinates.x, coordinates.y); | ||||
| 				blockable |= object->blockingAt(coordinates.x, coordinates.y); | ||||
|   | ||||
| @@ -66,6 +66,8 @@ const CGObjectInstance * MapRendererContext::getObject(ObjectInstanceID objectID | ||||
|  | ||||
| bool MapRendererContext::isVisible(const int3 & coordinates) const | ||||
| { | ||||
| 	if (showAllTerrain) | ||||
| 		return LOCPLINT->cb->isInTheMap(coordinates); | ||||
| 	return LOCPLINT->cb->isVisible(coordinates) || settings["session"]["spectate"].Bool(); | ||||
| } | ||||
|  | ||||
| @@ -253,11 +255,11 @@ Point MapRendererContext::objectImageOffset(ObjectInstanceID objectID, const int | ||||
| 	return Point(offsetTiles) * Point(32, 32); | ||||
| } | ||||
|  | ||||
| double MapRendererContext::objectTransparency(ObjectInstanceID objectID) const | ||||
| double MapRendererContext::objectTransparency(ObjectInstanceID objectID, const int3 & coordinates) const | ||||
| { | ||||
| 	const CGObjectInstance * object = getObject(objectID); | ||||
|  | ||||
| 	if(object && object->ID == Obj::HERO) | ||||
| 	if(object->ID == Obj::HERO) | ||||
| 	{ | ||||
| 		const auto * hero = dynamic_cast<const CGHeroInstance *>(object); | ||||
|  | ||||
| @@ -268,6 +270,12 @@ double MapRendererContext::objectTransparency(ObjectInstanceID objectID) const | ||||
| 			return 0; | ||||
| 	} | ||||
|  | ||||
| 	if(showAllTerrain) | ||||
| 	{ | ||||
| 		if(object->isVisitable() && !LOCPLINT->cb->isVisible(coordinates)) | ||||
| 			return 0; | ||||
| 	} | ||||
|  | ||||
| 	if(fadeOutAnimation && objectID == fadeOutAnimation->target) | ||||
| 		return 1.0 - fadeOutAnimation->progress; | ||||
|  | ||||
| @@ -276,3 +284,69 @@ double MapRendererContext::objectTransparency(ObjectInstanceID objectID) const | ||||
|  | ||||
| 	return 1.0; | ||||
| } | ||||
|  | ||||
| size_t MapRendererContext::selectOverlayImageForObject(const ObjectPosInfo & object) const | ||||
| { | ||||
| 	size_t ownerIndex = PlayerColor::PLAYER_LIMIT.getNum() * static_cast<size_t>(EWorldViewIcon::ICONS_PER_PLAYER); | ||||
|  | ||||
| 	if(object.owner.isValidPlayer()) | ||||
| 		ownerIndex = object.owner.getNum() * static_cast<size_t>(EWorldViewIcon::ICONS_PER_PLAYER); | ||||
|  | ||||
| 	switch(object.id) | ||||
| 	{ | ||||
| 		case Obj::MONOLITH_ONE_WAY_ENTRANCE: | ||||
| 		case Obj::MONOLITH_ONE_WAY_EXIT: | ||||
| 		case Obj::MONOLITH_TWO_WAY: | ||||
| 			return ownerIndex + static_cast<size_t>(EWorldViewIcon::TELEPORT); | ||||
| 		case Obj::SUBTERRANEAN_GATE: | ||||
| 			return ownerIndex + static_cast<size_t>(EWorldViewIcon::GATE); | ||||
| 		case Obj::ARTIFACT: | ||||
| 			return ownerIndex + static_cast<size_t>(EWorldViewIcon::ARTIFACT); | ||||
| 		case Obj::TOWN: | ||||
| 			return ownerIndex + static_cast<size_t>(EWorldViewIcon::TOWN); | ||||
| 		case Obj::HERO: | ||||
| 			return ownerIndex + static_cast<size_t>(EWorldViewIcon::HERO); | ||||
| 		case Obj::MINE: | ||||
| 			return ownerIndex + static_cast<size_t>(EWorldViewIcon::MINE_WOOD) + object.subId; | ||||
| 		case Obj::RESOURCE: | ||||
| 			return ownerIndex + static_cast<size_t>(EWorldViewIcon::RES_WOOD) + object.subId; | ||||
| 	} | ||||
| 	return std::numeric_limits<size_t>::max(); | ||||
| } | ||||
|  | ||||
| size_t MapRendererContext::overlayImageIndex(const int3 & coordinates) const | ||||
| { | ||||
| 	for(const auto & entry : additionalOverlayIcons) | ||||
| 	{ | ||||
| 		if(entry.pos != coordinates) | ||||
| 			continue; | ||||
|  | ||||
| 		size_t iconIndex = selectOverlayImageForObject(entry); | ||||
|  | ||||
| 		if(iconIndex != std::numeric_limits<size_t>::max()) | ||||
| 			return iconIndex; | ||||
| 	} | ||||
|  | ||||
| 	if(!isVisible(coordinates)) | ||||
| 		return std::numeric_limits<size_t>::max(); | ||||
|  | ||||
| 	for(const auto & objectID : getObjects(coordinates)) | ||||
| 	{ | ||||
| 		const auto * object = getObject(objectID); | ||||
|  | ||||
| 		if(!object->visitableAt(coordinates.x, coordinates.y)) | ||||
| 			continue; | ||||
|  | ||||
| 		ObjectPosInfo info; | ||||
| 		info.pos = coordinates; | ||||
| 		info.id = object->ID; | ||||
| 		info.subId = object->subID; | ||||
| 		info.owner = object->tempOwner; | ||||
|  | ||||
| 		size_t iconIndex = selectOverlayImageForObject(info); | ||||
|  | ||||
| 		if(iconIndex != std::numeric_limits<size_t>::max()) | ||||
| 			return iconIndex; | ||||
| 	} | ||||
| 	return std::numeric_limits<size_t>::max(); | ||||
| } | ||||
|   | ||||
| @@ -14,6 +14,10 @@ | ||||
| #include "../lib/int3.h" | ||||
| #include "../lib/GameConstants.h" | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_BEGIN | ||||
| struct ObjectPosInfo; | ||||
| VCMI_LIB_NAMESPACE_END | ||||
|  | ||||
| class MapObjectsSorter | ||||
| { | ||||
| 	const IMapRendererContext & context; | ||||
| @@ -39,6 +43,33 @@ struct FadingAnimationState | ||||
| 	double progress; | ||||
| }; | ||||
|  | ||||
| // from VwSymbol.def | ||||
| enum class EWorldViewIcon | ||||
| { | ||||
| 	TOWN = 0, | ||||
| 	HERO = 1, | ||||
| 	ARTIFACT = 2, | ||||
| 	TELEPORT = 3, | ||||
| 	GATE = 4, | ||||
| 	MINE_WOOD = 5, | ||||
| 	MINE_MERCURY = 6, | ||||
| 	MINE_STONE = 7, | ||||
| 	MINE_SULFUR = 8, | ||||
| 	MINE_CRYSTAL = 9, | ||||
| 	MINE_GEM = 10, | ||||
| 	MINE_GOLD = 11, | ||||
| 	RES_WOOD = 12, | ||||
| 	RES_MERCURY = 13, | ||||
| 	RES_STONE = 14, | ||||
| 	RES_SULFUR = 15, | ||||
| 	RES_CRYSTAL = 16, | ||||
| 	RES_GEM = 17, | ||||
| 	RES_GOLD = 18, | ||||
|  | ||||
| 	ICONS_PER_PLAYER = 19, | ||||
| 	ICONS_TOTAL = 19 * 9 // 8 players + neutral set at the end | ||||
| }; | ||||
|  | ||||
| class MapRendererContext : public IMapRendererContext | ||||
| { | ||||
| 	friend class MapViewController; | ||||
| @@ -54,7 +85,12 @@ class MapRendererContext : public IMapRendererContext | ||||
| 	boost::optional<FadingAnimationState> fadeOutAnimation; | ||||
| 	boost::optional<FadingAnimationState> fadeInAnimation; | ||||
|  | ||||
| 	std::vector<ObjectPosInfo> additionalOverlayIcons; | ||||
|  | ||||
| 	bool worldViewModeActive = false; | ||||
| 	bool showAllTerrain = false; | ||||
|  | ||||
| 	size_t selectOverlayImageForObject(const ObjectPosInfo & objectID) const; | ||||
|  | ||||
| public: | ||||
| 	MapRendererContext(); | ||||
| @@ -74,9 +110,10 @@ public: | ||||
|  | ||||
| 	size_t objectGroupIndex(ObjectInstanceID objectID) const override; | ||||
| 	Point objectImageOffset(ObjectInstanceID objectID, const int3 & coordinates) const override; | ||||
| 	double objectTransparency(ObjectInstanceID objectID) const override; | ||||
| 	double objectTransparency(ObjectInstanceID objectID, const int3 &coordinates) const override; | ||||
| 	size_t objectImageIndex(ObjectInstanceID objectID, size_t groupSize) const override; | ||||
| 	size_t terrainImageIndex(size_t groupSize) const override; | ||||
| 	size_t overlayImageIndex(const int3 & coordinates) const override; | ||||
| //	Point getTileSize() const override; | ||||
|  | ||||
| 	bool showOverlay() const override; | ||||
|   | ||||
| @@ -26,13 +26,12 @@ MapViewCache::MapViewCache(const std::shared_ptr<MapViewModel> & model) | ||||
| 	: model(model) | ||||
| 	, mapRenderer(new MapRenderer()) | ||||
| 	, iconsStorage(new CAnimation("VwSymbol")) | ||||
| 	, intermediate(new Canvas(Point(32,32))) | ||||
| 	, intermediate(new Canvas(Point(32, 32))) | ||||
| 	, terrain(new Canvas(model->getCacheDimensionsPixels())) | ||||
| { | ||||
| 	iconsStorage->preload(); | ||||
| 	for (size_t i = 0; i < iconsStorage->size(); ++i) | ||||
| 	for(size_t i = 0; i < iconsStorage->size(); ++i) | ||||
| 		iconsStorage->getImage(i)->setBlitMode(EImageBlitMode::COLORKEY); | ||||
|  | ||||
| } | ||||
|  | ||||
| Canvas MapViewCache::getTile(const int3 & coordinates) | ||||
| @@ -42,40 +41,10 @@ Canvas MapViewCache::getTile(const int3 & coordinates) | ||||
|  | ||||
| std::shared_ptr<IImage> MapViewCache::getOverlayImageForTile(const std::shared_ptr<MapRendererContext> & context, const int3 & coordinates) | ||||
| { | ||||
| 	if (!context->isVisible(coordinates)) | ||||
| 		return nullptr; | ||||
| 	size_t imageIndex = context->overlayImageIndex(coordinates); | ||||
|  | ||||
| 	for(const auto & objectID : context->getObjects(coordinates)) | ||||
| 	{ | ||||
| 		const auto * object = context->getObject(objectID); | ||||
|  | ||||
| 		if (!object->visitableAt(coordinates.x, coordinates.y)) | ||||
| 			continue; | ||||
|  | ||||
| 		size_t ownerIndex = PlayerColor::PLAYER_LIMIT.getNum() * static_cast<size_t>(EWorldViewIcon::ICONS_PER_PLAYER); | ||||
| 		if (object->tempOwner.isValidPlayer()) | ||||
| 			ownerIndex = object->tempOwner.getNum() * static_cast<size_t>(EWorldViewIcon::ICONS_PER_PLAYER); | ||||
|  | ||||
| 		switch (object->ID) | ||||
| 		{ | ||||
| 			case Obj::MONOLITH_ONE_WAY_ENTRANCE: | ||||
| 			case Obj::MONOLITH_ONE_WAY_EXIT: | ||||
| 			case Obj::MONOLITH_TWO_WAY: | ||||
| 				return iconsStorage->getImage(ownerIndex + static_cast<size_t>(EWorldViewIcon::TELEPORT)); | ||||
| 			case Obj::SUBTERRANEAN_GATE: | ||||
| 				return iconsStorage->getImage(ownerIndex + static_cast<size_t>(EWorldViewIcon::GATE)); | ||||
| 			case Obj::ARTIFACT: | ||||
| 				return iconsStorage->getImage(ownerIndex + static_cast<size_t>(EWorldViewIcon::ARTIFACT)); | ||||
| 			case Obj::TOWN: | ||||
| 				return iconsStorage->getImage(ownerIndex + static_cast<size_t>(EWorldViewIcon::TOWN)); | ||||
| 			case Obj::HERO: | ||||
| 				return iconsStorage->getImage(ownerIndex + static_cast<size_t>(EWorldViewIcon::HERO)); | ||||
| 			case Obj::MINE: | ||||
| 				return iconsStorage->getImage(ownerIndex + static_cast<size_t>(EWorldViewIcon::MINE_WOOD) + object->subID); | ||||
| 			case Obj::RESOURCE: | ||||
| 				return iconsStorage->getImage(ownerIndex + static_cast<size_t>(EWorldViewIcon::RES_WOOD) + object->subID); | ||||
| 		} | ||||
| 	} | ||||
| 	if(imageIndex < iconsStorage->size()) | ||||
| 		return iconsStorage->getImage(imageIndex); | ||||
| 	return nullptr; | ||||
| } | ||||
|  | ||||
| @@ -115,9 +84,17 @@ void MapViewCache::render(const std::shared_ptr<MapRendererContext> & context, C | ||||
| 			Canvas source = getTile(tile); | ||||
| 			Rect targetRect = model->getTargetTileArea(tile); | ||||
| 			target.draw(source, targetRect.topLeft()); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 			if (context->showOverlay()) | ||||
| 	if (context->showOverlay()) | ||||
| 	{ | ||||
| 		for(int y = dimensions.top(); y < dimensions.bottom(); ++y) | ||||
| 		{ | ||||
| 			for(int x = dimensions.left(); x < dimensions.right(); ++x) | ||||
| 			{ | ||||
| 				int3 tile(x, y, model->getLevel()); | ||||
| 				Rect targetRect = model->getTargetTileArea(tile); | ||||
| 				auto overlay = getOverlayImageForTile(context, tile); | ||||
|  | ||||
| 				if (overlay) | ||||
|   | ||||
| @@ -21,33 +21,6 @@ class MapRendererContext; | ||||
| //class MapViewController; | ||||
| class MapViewModel; | ||||
|  | ||||
| // from VwSymbol.def | ||||
| enum class EWorldViewIcon | ||||
| { | ||||
| 	TOWN = 0, | ||||
| 	HERO = 1, | ||||
| 	ARTIFACT = 2, | ||||
| 	TELEPORT = 3, | ||||
| 	GATE = 4, | ||||
| 	MINE_WOOD = 5, | ||||
| 	MINE_MERCURY = 6, | ||||
| 	MINE_STONE = 7, | ||||
| 	MINE_SULFUR = 8, | ||||
| 	MINE_CRYSTAL = 9, | ||||
| 	MINE_GEM = 10, | ||||
| 	MINE_GOLD = 11, | ||||
| 	RES_WOOD = 12, | ||||
| 	RES_MERCURY = 13, | ||||
| 	RES_STONE = 14, | ||||
| 	RES_SULFUR = 15, | ||||
| 	RES_CRYSTAL = 16, | ||||
| 	RES_GEM = 17, | ||||
| 	RES_GOLD = 18, | ||||
|  | ||||
| 	ICONS_PER_PLAYER = 19, | ||||
| 	ICONS_TOTAL = 19 * 9 // 8 players + neutral set at the end | ||||
| }; | ||||
|  | ||||
| /// Class responsible for rendering of entire map view | ||||
| /// uses rendering parameters provided by owner class | ||||
| class MapViewCache | ||||
|   | ||||
| @@ -17,6 +17,7 @@ | ||||
| #include "../../lib/CConfigHandler.h" | ||||
| #include "../../lib/mapObjects/CGHeroInstance.h" | ||||
| #include "../../lib/mapObjects/MiscObjects.h" | ||||
| #include "../../lib/spells/ViewSpellInt.h" | ||||
|  | ||||
| void MapViewController::setViewCenter(const int3 & position) | ||||
| { | ||||
| @@ -185,3 +186,14 @@ bool MapViewController::hasOngoingAnimations() | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| void MapViewController::setTerrainVisibility(bool showAllTerrain) | ||||
| { | ||||
| 	context->showAllTerrain = showAllTerrain; | ||||
| } | ||||
|  | ||||
| void MapViewController::setOverlayVisibility(const std::vector<ObjectPosInfo> & objectPositions) | ||||
| { | ||||
| 	context->additionalOverlayIcons = objectPositions; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -13,7 +13,9 @@ | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_BEGIN | ||||
| class Point; | ||||
| struct ObjectPosInfo; | ||||
| VCMI_LIB_NAMESPACE_END | ||||
|  | ||||
| class MapViewModel; | ||||
| class MapRendererContext; | ||||
|  | ||||
| @@ -42,4 +44,8 @@ public: | ||||
| 	void setViewCenter(const Point & position, int level); | ||||
| 	void setTileSize(const Point & tileSize); | ||||
| 	void update(uint32_t timeDelta); | ||||
|  | ||||
| 	void setTerrainVisibility(bool showAllTerrain); | ||||
| 	void setOverlayVisibility(const std::vector<ObjectPosInfo> & objectPositions); | ||||
|  | ||||
| }; | ||||
|   | ||||
| @@ -107,7 +107,7 @@ public: | ||||
| 	virtual void showMapObjectSelectDialog(QueryID askID, const Component & icon, const MetaString & title, const MetaString & description, const std::vector<ObjectInstanceID> & objects) = 0; | ||||
| 	virtual void finish(){}; //if for some reason we want to end | ||||
|  | ||||
| 	virtual void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions){}; | ||||
| 	virtual void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain){}; | ||||
|  | ||||
| 	virtual boost::optional<BattleAction> makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState) | ||||
| 	{ | ||||
|   | ||||
| @@ -1908,12 +1908,14 @@ protected: | ||||
| struct DLL_LINKAGE ShowWorldViewEx : public CPackForClient | ||||
| { | ||||
| 	PlayerColor player; | ||||
| 	bool showTerrain; // TODO: send terrain state | ||||
|  | ||||
| 	std::vector<ObjectPosInfo> objectPositions; | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler & h, const int version) | ||||
| 	{ | ||||
| 		h & player; | ||||
| 		h & showTerrain; | ||||
| 		h & objectPositions; | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -585,6 +585,7 @@ ESpellCastResult ViewMechanics::applyAdventureEffects(SpellCastEnvironment * env | ||||
| 				pack.objectPositions.push_back(posInfo); | ||||
| 		} | ||||
| 	} | ||||
| 	pack.showTerrain = showTerrain(spellLevel); | ||||
|  | ||||
| 	env->apply(&pack); | ||||
|  | ||||
| @@ -602,6 +603,11 @@ bool ViewAirMechanics::filterObject(const CGObjectInstance * obj, const int32_t | ||||
| 	return (obj->ID == Obj::ARTIFACT) || (spellLevel > 1 && obj->ID == Obj::HERO) || (spellLevel > 2 && obj->ID == Obj::TOWN); | ||||
| } | ||||
|  | ||||
| bool ViewAirMechanics::showTerrain(const int32_t spellLevel) const | ||||
| { | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| ///ViewEarthMechanics | ||||
| ViewEarthMechanics::ViewEarthMechanics(const CSpell * s): | ||||
| 	ViewMechanics(s) | ||||
| @@ -613,5 +619,9 @@ bool ViewEarthMechanics::filterObject(const CGObjectInstance * obj, const int32_ | ||||
| 	return (obj->ID == Obj::RESOURCE) || (spellLevel > 1 && obj->ID == Obj::MINE); | ||||
| } | ||||
|  | ||||
| bool ViewEarthMechanics::showTerrain(const int32_t spellLevel) const | ||||
| { | ||||
| 	return spellLevel > 2; | ||||
| } | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_END | ||||
|   | ||||
| @@ -82,6 +82,7 @@ public: | ||||
| protected: | ||||
| 	ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override; | ||||
| 	virtual bool filterObject(const CGObjectInstance * obj, const int32_t spellLevel) const = 0; | ||||
| 	virtual bool showTerrain(const int32_t spellLevel) const = 0; | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE ViewAirMechanics : public ViewMechanics | ||||
| @@ -90,6 +91,7 @@ public: | ||||
| 	ViewAirMechanics(const CSpell * s); | ||||
| protected: | ||||
| 	bool filterObject(const CGObjectInstance * obj, const int32_t spellLevel) const override; | ||||
| 	bool showTerrain(const int32_t spellLevel) const override; | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE ViewEarthMechanics : public ViewMechanics | ||||
| @@ -98,6 +100,7 @@ public: | ||||
| 	ViewEarthMechanics(const CSpell * s); | ||||
| protected: | ||||
| 	bool filterObject(const CGObjectInstance * obj, const int32_t spellLevel) const override; | ||||
| 	bool showTerrain(const int32_t spellLevel) const override; | ||||
| }; | ||||
|  | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user