Sfoglia il codice sorgente

Icons for heroes on minimap

VCMI will now show icons for all heroes on visible part of minimap to
help with readability on large maps

Old behavior can be enable via toggle in game settings menu
Ivan Savenko 4 mesi fa
parent
commit
24def2ed16

BIN
Mods/vcmi/Content/Sprites/minimapIcons/hero-overlay.png


BIN
Mods/vcmi/Content/Sprites/minimapIcons/hero.png


+ 2 - 0
Mods/vcmi/Content/config/english.json

@@ -342,6 +342,8 @@
 	"vcmi.adventureOptions.mapScrollSpeed6.help" : "Set the map scrolling speed to instantaneous.",
 	"vcmi.adventureOptions.hideBackground.hover" : "Hide Background",
 	"vcmi.adventureOptions.hideBackground.help" : "{Hide Background}\n\nHide the adventuremap in the background and show a texture instead.",
+	"vcmi.adventureOptions.minimapShowHeroes.hover" : "Show Heroes On Minimap",
+	"vcmi.adventureOptions.minimapShowHeroes.help" : "{Show Heroes On Minimap}\n\nShow addition icon for all heroes visible on minimap, making them more easy to see on large maps",
 
 	"vcmi.battleOptions.queueSizeLabel.hover" : "Show Turn Order Queue",
 	"vcmi.battleOptions.queueSizeNoneButton.hover" : "OFF",

+ 43 - 6
client/adventureMap/CMinimap.cpp

@@ -13,22 +13,25 @@
 
 #include "AdventureMapInterface.h"
 
-#include "../widgets/Images.h"
 #include "../CPlayerInterface.h"
 #include "../GameEngine.h"
 #include "../GameInstance.h"
 #include "../gui/MouseButton.h"
 #include "../gui/WindowHandler.h"
-#include "../render/Colors.h"
+#include "../render/CAnimation.h"
 #include "../render/Canvas.h"
+#include "../render/Colors.h"
 #include "../render/Graphics.h"
+#include "../render/IRenderHandler.h"
+#include "../widgets/Images.h"
 #include "../windows/InfoWindows.h"
 
-#include "../../lib/callback/CCallback.h"
-#include "../../lib/texts/CGeneralTextHandler.h"
+#include "../../lib/CConfigHandler.h"
 #include "../../lib/TerrainHandler.h"
+#include "../../lib/callback/CCallback.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"
 #include "../../lib/mapping/CMapDefines.h"
+#include "../../lib/texts/CGeneralTextHandler.h"
 
 ColorRGBA CMinimapInstance::getTileColor(const int3 & pos) const
 {
@@ -89,8 +92,9 @@ void CMinimapInstance::showAll(Canvas & to)
 }
 
 CMinimap::CMinimap(const Rect & position)
-	: CIntObject(LCLICK | SHOW_POPUP | DRAG | MOVE | GESTURE, position.topLeft()),
-	level(0)
+	: CIntObject(LCLICK | SHOW_POPUP | DRAG | MOVE | GESTURE, position.topLeft())
+	, heroIcon(ENGINE->renderHandler().loadImage(ImagePath::builtin("minimapIcons/hero"), EImageBlitMode::WITH_SHADOW_AND_FLAG_COLOR))
+	, level(0)
 {
 	OBJECT_CONSTRUCTION;
 
@@ -196,6 +200,22 @@ void CMinimap::showAll(Canvas & to)
 
 		Canvas clippedTarget(to, pos);
 		clippedTarget.drawBorderDashed(radar, Colors::PURPLE);
+
+		if (settings["adventure"]["minimapShowHeroes"].Bool())
+		{
+			static const auto image = ENGINE->renderHandler().loadImage(ImagePath::builtin("minimapIcons/hero"), EImageBlitMode::WITH_SHADOW_AND_FLAG_COLOR);
+
+			for (const auto objectID : visibleHeroes)
+			{
+				const auto * object = GAME->interface()->cb->getObj(objectID);
+
+				if (object->anchorPos().z != level)
+					continue;
+
+				image->setOverlayColor(graphics->playerColors[object->getOwner().getNum()]);
+				clippedTarget.draw(image, tileToPixels(object->visitablePos()) - image->dimensions() / 2);
+			}
+		}
 	}
 }
 
@@ -206,6 +226,7 @@ void CMinimap::update()
 
 	OBJECT_CONSTRUCTION;
 	minimap = std::make_shared<CMinimapInstance>(Point(0,0), pos.dimensions(), level);
+	updateVisibleHeroes();
 	redraw();
 }
 
@@ -240,6 +261,20 @@ void CMinimap::setAIRadar(bool on)
 	redraw();
 }
 
+void CMinimap::updateVisibleHeroes()
+{
+	visibleHeroes.clear();
+
+	for (const auto & player : PlayerColor::ALL_PLAYERS())
+	{
+		if (GAME->interface()->cb->getPlayerStatus(player, false) != EPlayerStatus::INGAME)
+			continue;
+
+		for (const auto & hero : GAME->interface()->cb->getHeroes(player))
+			visibleHeroes.push_back(hero->id);
+	}
+}
+
 void CMinimap::updateTiles(const std::unordered_set<int3> & positions)
 {
 	if(minimap)
@@ -247,5 +282,7 @@ void CMinimap::updateTiles(const std::unordered_set<int3> & positions)
 		for (auto const & tile : positions)
 			minimap->refreshTile(tile);
 	}
+
+	updateVisibleHeroes();
 	redraw();
 }

+ 5 - 0
client/adventureMap/CMinimap.h

@@ -17,6 +17,7 @@ VCMI_LIB_NAMESPACE_END
 
 class Canvas;
 class CMinimap;
+class IImage;
 
 class CMinimapInstance : public CIntObject
 {
@@ -40,6 +41,9 @@ class CMinimap : public CIntObject
 {
 	std::shared_ptr<CPicture> aiShield; //the graphic displayed during AI turn
 	std::shared_ptr<CMinimapInstance> minimap;
+	std::vector<ObjectInstanceID> visibleHeroes;
+	std::shared_ptr<IImage> heroIcon;
+
 	Rect screenArea;
 	int level;
 
@@ -48,6 +52,7 @@ class CMinimap : public CIntObject
 	void showPopupWindow(const Point & cursorPosition) override;
 	void hover(bool on) override;
 	void mouseDragged(const Point & cursorPosition, const Point & lastUpdateDistance) override;
+	void updateVisibleHeroes();
 
 	/// relocates center of adventure map screen to currently hovered tile
 	void moveAdvMapSelection(const Point & positionGlobal);

+ 14 - 4
client/windows/settings/AdventureOptionsTab.cpp

@@ -11,13 +11,15 @@
 
 #include "AdventureOptionsTab.h"
 
-#include "../../eventsSDL/InputHandler.h"
-#include "../../../lib/filesystem/ResourcePath.h"
 #include "../../GameEngine.h"
+#include "../../eventsSDL/InputHandler.h"
+#include "../../gui/WindowHandler.h"
 #include "../../widgets/Buttons.h"
-#include "../../widgets/TextControls.h"
 #include "../../widgets/Images.h"
-#include "CConfigHandler.h"
+#include "../../widgets/TextControls.h"
+
+#include "../../../lib/CConfigHandler.h"
+#include "../../../lib/filesystem/ResourcePath.h"
 
 static void setBoolSetting(std::string group, std::string field, bool value)
 {
@@ -146,6 +148,11 @@ AdventureOptionsTab::AdventureOptionsTab()
 	{
 		return setBoolSetting("adventure", "hideBackground", value);
 	});
+	addCallback("minimapShowHeroesChanged", [](bool value)
+	{
+		setBoolSetting("adventure", "minimapShowHeroes", value);
+		ENGINE->windows().totalRedraw();
+	});
 	build(config);
 
 	std::shared_ptr<CToggleGroup> playerHeroSpeedToggle = widget<CToggleGroup>("heroMovementSpeedPicker");
@@ -198,4 +205,7 @@ AdventureOptionsTab::AdventureOptionsTab()
 
 	std::shared_ptr<CToggleButton> hideBackgroundCheckbox = widget<CToggleButton>("hideBackgroundCheckbox");
 	hideBackgroundCheckbox->setSelected(settings["adventure"]["hideBackground"].Bool());
+
+	std::shared_ptr<CToggleButton> minimapShowHeroesCheckbox = widget<CToggleButton>("minimapShowHeroesCheckbox");
+	minimapShowHeroesCheckbox->setSelected(settings["adventure"]["minimapShowHeroes"].Bool());
 }

+ 6 - 1
config/schemas/settings.json

@@ -387,7 +387,7 @@
 			"type" : "object",
 			"additionalProperties" : false,
 			"default" : {},
-			"required" : [ "heroMoveTime", "enemyMoveTime", "scrollSpeedPixels", "heroReminder", "quickCombat", "objectAnimation", "terrainAnimation", "forceQuickCombat", "borderScroll", "leftButtonDrag", "rightButtonDrag", "smoothDragging", "backgroundDimLevel", "hideBackground", "backgroundDimSmallWindows", "tileZoom" ],
+			"required" : [ "heroMoveTime", "enemyMoveTime", "scrollSpeedPixels", "heroReminder", "quickCombat", "objectAnimation", "terrainAnimation", "forceQuickCombat", "borderScroll", "leftButtonDrag", "rightButtonDrag", "smoothDragging", "backgroundDimLevel", "hideBackground", "backgroundDimSmallWindows", "tileZoom", "minimapShowHeroes" ],
 			"properties" : {
 				"heroMoveTime" : {
 					"type" : "number",
@@ -452,6 +452,11 @@
 					"type" : "boolean",
 					"default" : false
 				},
+				"minimapShowHeroes" : {
+					"type" : "boolean",
+					"default" : true
+				},
+				
 				"tileZoom" : {
 					"type" : "number",
 					"default" : 32

+ 8 - 0
config/widgets/settings/adventureOptionsTab.json

@@ -302,6 +302,9 @@
 				},
 				{
 					"text": "vcmi.adventureOptions.hideBackground.hover"
+				},
+				{
+					"text": "vcmi.adventureOptions.minimapShowHeroes.hover"
 				}
 			]
 		},
@@ -334,6 +337,11 @@
 					"name": "hideBackgroundCheckbox",
 					"help": "vcmi.adventureOptions.hideBackground",
 					"callback": "hideBackgroundChanged"
+				},
+				{
+					"name": "minimapShowHeroesCheckbox",
+					"help": "vcmi.adventureOptions.minimapShowHeroes",
+					"callback": "minimapShowHeroesChanged"
 				}
 			]
 		},

+ 14 - 0
lib/callback/CGameInfoCallback.cpp

@@ -718,6 +718,20 @@ int CGameInfoCallback::getHeroCount( PlayerColor player, bool includeGarrisoned
 	return ret;
 }
 
+std::vector<const CGHeroInstance*> CGameInfoCallback::getHeroes(PlayerColor player) const
+{
+	std::vector<const CGHeroInstance*> ret;
+	const PlayerState *p = gameState().getPlayerState(player);
+	ERROR_RET_VAL_IF(!p, "No such player!", ret);
+
+	for(const auto & hero : p->getHeroes())
+	{
+		if(!getPlayerID().has_value() || isVisibleFor(hero, *getPlayerID()) || hero->getOwner() == getPlayerID())
+			ret.push_back(hero);
+	}
+	return ret;
+}
+
 bool CGameInfoCallback::isPlayerMakingTurn(PlayerColor player) const
 {
 	return gameState().actingPlayers.count(player);

+ 1 - 0
lib/callback/CGameInfoCallback.h

@@ -57,6 +57,7 @@ public:
 	//hero
 	const CGHeroInstance * getHero(ObjectInstanceID objid) const override;
 	int getHeroCount(PlayerColor player, bool includeGarrisoned) const override;
+	std::vector<const CGHeroInstance*> getHeroes(PlayerColor player) const;
 	bool getHeroInfo(const CGObjectInstance * hero, InfoAboutHero & dest, const CGObjectInstance * selectedObject = nullptr) const;
 	int32_t getSpellCost(const spells::Spell * sp, const CGHeroInstance * caster) const;
 	int64_t estimateSpellDamage(const CSpell * sp, const CGHeroInstance * hero) const;

+ 0 - 5
lib/gameState/CGameState.cpp

@@ -1163,9 +1163,6 @@ bool CGameState::isVisibleFor(int3 pos, PlayerColor player) const
 
 bool CGameState::isVisibleFor(const CGObjectInstance * obj, PlayerColor player) const
 {
-	if(!player)
-		return true;
-
 	//we should always see our own heroes - but sometimes not visible heroes cause crash :?
 	if (player == obj->tempOwner)
 		return true;
@@ -1189,8 +1186,6 @@ bool CGameState::isVisibleFor(const CGObjectInstance * obj, PlayerColor player)
 	return false;
 }
 
-
-
 EVictoryLossCheckResult CGameState::checkForVictoryAndLoss(const PlayerColor & player) const
 {
 	const MetaString messageWonSelf = MetaString::createFromTextID("core.genrltxt.659");