1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-06 09:09:40 +02:00

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
This commit is contained in:
Ivan Savenko
2025-05-27 18:38:44 +03:00
parent f9e88557ca
commit 24def2ed16
11 changed files with 93 additions and 16 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 B

View File

@@ -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",

View File

@@ -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();
}

View File

@@ -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);

View File

@@ -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());
}

View File

@@ -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

View File

@@ -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"
}
]
},

View File

@@ -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);

View File

@@ -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;

View File

@@ -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");