1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Implemented View Earth / View Air spells

This commit is contained in:
Ivan Savenko 2023-02-21 14:38:08 +02:00
parent ec6f19ea18
commit 11e4d84749
24 changed files with 243 additions and 157 deletions

View File

@ -489,7 +489,7 @@ void AIGateway::showMarketWindow(const IMarket * market, const CGHeroInstance *
NET_EVENT_HANDLER; 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 //TODO: AI support for ViewXXX spell
LOG_TRACE(logAi); LOG_TRACE(logAi);

View File

@ -165,7 +165,7 @@ public:
void buildChanged(const CGTownInstance * town, BuildingID buildingID, int what) override; void buildChanged(const CGTownInstance * town, BuildingID buildingID, int what) override;
void heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bool gain) override; void heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bool gain) override;
void showMarketWindow(const IMarket * market, const CGHeroInstance * visitor) 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; 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; void battleStart(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool side) override;

View File

@ -572,7 +572,7 @@ void VCAI::showMarketWindow(const IMarket * market, const CGHeroInstance * visit
NET_EVENT_HANDLER; 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 //TODO: AI support for ViewXXX spell
LOG_TRACE(logAi); LOG_TRACE(logAi);

View File

@ -198,7 +198,7 @@ public:
void buildChanged(const CGTownInstance * town, BuildingID buildingID, int what) override; void buildChanged(const CGTownInstance * town, BuildingID buildingID, int what) override;
void heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bool gain) override; void heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bool gain) override;
void showMarketWindow(const IMarket * market, const CGHeroInstance * visitor) 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 battleStart(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool side) override;
void battleEnd(const BattleResult * br) override; void battleEnd(const BattleResult * br) override;

View File

@ -1829,7 +1829,7 @@ void CPlayerInterface::showPuzzleMap()
void CPlayerInterface::viewWorldMap() void CPlayerInterface::viewWorldMap()
{ {
adventureInt->changeMode(EAdvMapMode::WORLD_VIEW); adventureInt->openWorldView();
} }
void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellID) void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellID)
@ -1843,14 +1843,6 @@ void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellI
paths.erasePath(caster); paths.erasePath(caster);
const spells::Spell * spell = CGI->spells()->getByIndex(spellID); 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(); auto castSoundPath = spell->getCastSound();
if(!castSoundPath.empty()) if(!castSoundPath.empty())
CCS->soundh->playSound(castSoundPath); CCS->soundh->playSound(castSoundPath);
@ -2369,14 +2361,10 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
setMovementStatus(false); 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; EVENT_HANDLER_CALLED_BY_CLIENT;
//TODO: showWorldViewEx adventureInt->openWorldView(objectPositions, showTerrain );
std::copy(objectPositions.begin(), objectPositions.end(), std::back_inserter(adventureInt->worldViewOptions.iconPositions));
viewWorldMap();
} }
void CPlayerInterface::updateAmbientSounds(bool resetAll) void CPlayerInterface::updateAmbientSounds(bool resetAll)

View File

@ -210,7 +210,7 @@ public:
void showComp(const Component &comp, std::string message) override; //display component in the advmapint infobox 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 saveGame(BinarySerializer & h, const int version) override; //saving
void loadGame(BinaryDeserializer & h, const int version) override; //loading 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 //for battles
void actionFinished(const BattleAction& action) override;//occurs AFTER action taken by active stack or by the hero void actionFinished(const BattleAction& action) override;//occurs AFTER action taken by active stack or by the hero

View File

@ -883,7 +883,7 @@ void ApplyClientNetPackVisitor::visitAdvmapSpellCast(AdvmapSpellCast & pack)
void ApplyClientNetPackVisitor::visitShowWorldViewEx(ShowWorldViewEx & 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) void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack)

View File

@ -236,7 +236,7 @@ CAdvMapInt::CAdvMapInt():
activeMapPanel = panelMain; activeMapPanel = panelMain;
changeMode(EAdvMapMode::NORMAL); exitWorldView();
underground->block(!CGI->mh->getMap()->twoLevel); underground->block(!CGI->mh->getMap()->twoLevel);
questlog->block(!CGI->mh->getMap()->quests.size()); questlog->block(!CGI->mh->getMap()->quests.size());
@ -252,7 +252,7 @@ void CAdvMapInt::fshowOverview()
void CAdvMapInt::fworldViewBack() void CAdvMapInt::fworldViewBack()
{ {
changeMode(EAdvMapMode::NORMAL); exitWorldView();
auto hero = curHero(); auto hero = curHero();
if (hero) if (hero)
@ -262,17 +262,17 @@ void CAdvMapInt::fworldViewBack()
void CAdvMapInt::fworldViewScale1x() void CAdvMapInt::fworldViewScale1x()
{ {
// TODO set corresponding scale button to "selected" mode // TODO set corresponding scale button to "selected" mode
changeMode(EAdvMapMode::WORLD_VIEW, 7); // 7 pixels per tile openWorldView(7);
} }
void CAdvMapInt::fworldViewScale2x() void CAdvMapInt::fworldViewScale2x()
{ {
changeMode(EAdvMapMode::WORLD_VIEW, 11); // 11 pixels per tile openWorldView(11);
} }
void CAdvMapInt::fworldViewScale4x() void CAdvMapInt::fworldViewScale4x()
{ {
changeMode(EAdvMapMode::WORLD_VIEW, 16); // 16 pixels per tile openWorldView(16);
} }
void CAdvMapInt::fswitchLevel() void CAdvMapInt::fswitchLevel()
@ -666,7 +666,7 @@ void CAdvMapInt::centerOn(const CGObjectInstance * obj, bool fade)
void CAdvMapInt::keyReleased(const SDL_Keycode &key) void CAdvMapInt::keyReleased(const SDL_Keycode &key)
{ {
if (mode == EAdvMapMode::WORLD_VIEW) if (mode != EAdvMapMode::NORMAL)
return; return;
switch (key) switch (key)
@ -694,7 +694,7 @@ void CAdvMapInt::keyReleased(const SDL_Keycode &key)
void CAdvMapInt::keyPressed(const SDL_Keycode & key) void CAdvMapInt::keyPressed(const SDL_Keycode & key)
{ {
if (mode == EAdvMapMode::WORLD_VIEW) if (mode != EAdvMapMode::NORMAL)
return; return;
const CGHeroInstance *h = curHero(); //selected hero const CGHeroInstance *h = curHero(); //selected hero
@ -1460,62 +1460,49 @@ void CAdvMapInt::quickCombatUnlock()
activate(); 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 = EAdvMapMode::WORLD_VIEW;
{ panelMain->deactivate();
mode = newMode; panelWorldView->activate();
switch (mode) activeMapPanel = panelWorldView;
{
case EAdvMapMode::NORMAL:
panelMain->activate();
panelWorldView->deactivate();
activeMapPanel = panelMain;
townList->activate(); townList->deactivate();
heroList->activate(); heroList->deactivate();
infoBar->activate(); infoBar->showSelection(); // to prevent new day animation interfering world view mode
infoBar->deactivate();
worldViewOptions.clear(); redraw();
terrain->setTileSize(tileSize);
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);
} }
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; openWorldView(11);
terrain->setTerrainVisibility(showTerrain);
iconPositions.clear(); terrain->setOverlayVisibility(objectPositions);
} }

View File

@ -61,21 +61,12 @@ private:
enum EDirections {LEFT=1, RIGHT=2, UP=4, DOWN=8}; enum EDirections {LEFT=1, RIGHT=2, UP=4, DOWN=8};
enum EGameStates {NA, INGAME, WAITING}; enum EGameStates {NA, INGAME, WAITING};
struct WorldViewOptions
{
bool showAllTerrain; //for expert viewEarth
std::vector<ObjectPosInfo> iconPositions;
WorldViewOptions();
void clear();
};
bool swipeEnabled; bool swipeEnabled;
bool swipeMovementRequested; bool swipeMovementRequested;
Point swipeTargetPosition; Point swipeTargetPosition;
EGameStates state; EGameStates state;
EAdvMapMode mode; EAdvMapMode mode;
WorldViewOptions worldViewOptions;
/// Currently selected object, can be town, hero or null /// Currently selected object, can be town, hero or null
const CArmedInstance *selection; const CArmedInstance *selection;
@ -211,9 +202,17 @@ public:
/// returs visible section of game map, in tiles /// returs visible section of game map, in tiles
Rect terrainAreaTiles() const; Rect terrainAreaTiles() const;
/// changes current adventure map mode; used to switch between default view and world view; scale is ignored if EAdvMapMode == NORMAL /// exits currently opened world view mode and returns to normal map
void changeMode(EAdvMapMode newMode); void exitWorldView();
void changeMode(EAdvMapMode newMode, int tileSize);
/// 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; extern std::shared_ptr<CAdvMapInt> adventureInt;

View File

@ -29,7 +29,7 @@ CAdventureOptions::CAdventureOptions()
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
viewWorld = std::make_shared<CButton>(Point(24, 23), "ADVVIEW.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_v); 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 = std::make_shared<CButton>(Point(204, 313), "IOK6432.DEF", CButton::tooltip(), std::bind(&CAdventureOptions::close, this), SDLK_RETURN);
exit->assignedKeys.insert(SDLK_ESCAPE); exit->assignedKeys.insert(SDLK_ESCAPE);

View File

@ -240,3 +240,14 @@ void CTerrainRect::setTileSize(int sizePixels)
{ {
renderer->getController()->setTileSize(Point(sizePixels, 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);
}

View File

@ -14,6 +14,7 @@
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
struct CGPath; struct CGPath;
struct ObjectPosInfo;
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END
class MapView; class MapView;
@ -51,6 +52,9 @@ public:
void setLevel(int level); void setLevel(int level);
void setTileSize(int sizePixels); void setTileSize(int sizePixels);
void setTerrainVisibility(bool showAllTerrain);
void setOverlayVisibility(const std::vector<ObjectPosInfo> & objectPositions);
Point getViewCenter(); Point getViewCenter();
int getLevel(); int getLevel();

View File

@ -53,11 +53,14 @@ public:
virtual Point objectImageOffset(ObjectInstanceID objectID, const int3 & coordinates) const = 0; virtual Point objectImageOffset(ObjectInstanceID objectID, const int3 & coordinates) const = 0;
/// returns object animation transparency. IF set to 0, object will not be visible /// 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 /// returns animation frame for selected object
virtual size_t objectImageIndex(ObjectInstanceID objectID, size_t groupSize) const = 0; 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 /// returns animation frame for terrain
virtual size_t terrainImageIndex(size_t groupSize) const = 0; virtual size_t terrainImageIndex(size_t groupSize) const = 0;

View File

@ -444,7 +444,7 @@ void MapRendererObjects::renderImage(const IMapRendererContext & context, Canvas
if(!image) if(!image)
return; 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) if (transparency == 0)
return; return;
@ -507,7 +507,7 @@ void MapRendererDebug::renderTile(const IMapRendererContext & context, Canvas &
{ {
const auto * object = context.getObject(objectID); const auto * object = context.getObject(objectID);
if (context.objectTransparency(objectID) > 0) if (context.objectTransparency(objectID, coordinates) > 0)
{ {
visitable |= object->visitableAt(coordinates.x, coordinates.y); visitable |= object->visitableAt(coordinates.x, coordinates.y);
blockable |= object->blockingAt(coordinates.x, coordinates.y); blockable |= object->blockingAt(coordinates.x, coordinates.y);

View File

@ -66,6 +66,8 @@ const CGObjectInstance * MapRendererContext::getObject(ObjectInstanceID objectID
bool MapRendererContext::isVisible(const int3 & coordinates) const bool MapRendererContext::isVisible(const int3 & coordinates) const
{ {
if (showAllTerrain)
return LOCPLINT->cb->isInTheMap(coordinates);
return LOCPLINT->cb->isVisible(coordinates) || settings["session"]["spectate"].Bool(); 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); 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); const CGObjectInstance * object = getObject(objectID);
if(object && object->ID == Obj::HERO) if(object->ID == Obj::HERO)
{ {
const auto * hero = dynamic_cast<const CGHeroInstance *>(object); const auto * hero = dynamic_cast<const CGHeroInstance *>(object);
@ -268,6 +270,12 @@ double MapRendererContext::objectTransparency(ObjectInstanceID objectID) const
return 0; return 0;
} }
if(showAllTerrain)
{
if(object->isVisitable() && !LOCPLINT->cb->isVisible(coordinates))
return 0;
}
if(fadeOutAnimation && objectID == fadeOutAnimation->target) if(fadeOutAnimation && objectID == fadeOutAnimation->target)
return 1.0 - fadeOutAnimation->progress; return 1.0 - fadeOutAnimation->progress;
@ -276,3 +284,69 @@ double MapRendererContext::objectTransparency(ObjectInstanceID objectID) const
return 1.0; 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();
}

View File

@ -14,6 +14,10 @@
#include "../lib/int3.h" #include "../lib/int3.h"
#include "../lib/GameConstants.h" #include "../lib/GameConstants.h"
VCMI_LIB_NAMESPACE_BEGIN
struct ObjectPosInfo;
VCMI_LIB_NAMESPACE_END
class MapObjectsSorter class MapObjectsSorter
{ {
const IMapRendererContext & context; const IMapRendererContext & context;
@ -39,6 +43,33 @@ struct FadingAnimationState
double progress; 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 class MapRendererContext : public IMapRendererContext
{ {
friend class MapViewController; friend class MapViewController;
@ -54,7 +85,12 @@ class MapRendererContext : public IMapRendererContext
boost::optional<FadingAnimationState> fadeOutAnimation; boost::optional<FadingAnimationState> fadeOutAnimation;
boost::optional<FadingAnimationState> fadeInAnimation; boost::optional<FadingAnimationState> fadeInAnimation;
std::vector<ObjectPosInfo> additionalOverlayIcons;
bool worldViewModeActive = false; bool worldViewModeActive = false;
bool showAllTerrain = false;
size_t selectOverlayImageForObject(const ObjectPosInfo & objectID) const;
public: public:
MapRendererContext(); MapRendererContext();
@ -74,9 +110,10 @@ public:
size_t objectGroupIndex(ObjectInstanceID objectID) const override; size_t objectGroupIndex(ObjectInstanceID objectID) const override;
Point objectImageOffset(ObjectInstanceID objectID, const int3 & coordinates) 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 objectImageIndex(ObjectInstanceID objectID, size_t groupSize) const override;
size_t terrainImageIndex(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; // Point getTileSize() const override;
bool showOverlay() const override; bool showOverlay() const override;

View File

@ -26,13 +26,12 @@ MapViewCache::MapViewCache(const std::shared_ptr<MapViewModel> & model)
: model(model) : model(model)
, mapRenderer(new MapRenderer()) , mapRenderer(new MapRenderer())
, iconsStorage(new CAnimation("VwSymbol")) , iconsStorage(new CAnimation("VwSymbol"))
, intermediate(new Canvas(Point(32,32))) , intermediate(new Canvas(Point(32, 32)))
, terrain(new Canvas(model->getCacheDimensionsPixels())) , terrain(new Canvas(model->getCacheDimensionsPixels()))
{ {
iconsStorage->preload(); 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); iconsStorage->getImage(i)->setBlitMode(EImageBlitMode::COLORKEY);
} }
Canvas MapViewCache::getTile(const int3 & coordinates) 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) std::shared_ptr<IImage> MapViewCache::getOverlayImageForTile(const std::shared_ptr<MapRendererContext> & context, const int3 & coordinates)
{ {
if (!context->isVisible(coordinates)) size_t imageIndex = context->overlayImageIndex(coordinates);
return nullptr;
for(const auto & objectID : context->getObjects(coordinates)) if(imageIndex < iconsStorage->size())
{ return iconsStorage->getImage(imageIndex);
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);
}
}
return nullptr; return nullptr;
} }
@ -115,9 +84,17 @@ void MapViewCache::render(const std::shared_ptr<MapRendererContext> & context, C
Canvas source = getTile(tile); Canvas source = getTile(tile);
Rect targetRect = model->getTargetTileArea(tile); Rect targetRect = model->getTargetTileArea(tile);
target.draw(source, targetRect.topLeft()); 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); auto overlay = getOverlayImageForTile(context, tile);
if (overlay) if (overlay)

View File

@ -21,33 +21,6 @@ class MapRendererContext;
//class MapViewController; //class MapViewController;
class MapViewModel; 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 /// Class responsible for rendering of entire map view
/// uses rendering parameters provided by owner class /// uses rendering parameters provided by owner class
class MapViewCache class MapViewCache

View File

@ -17,6 +17,7 @@
#include "../../lib/CConfigHandler.h" #include "../../lib/CConfigHandler.h"
#include "../../lib/mapObjects/CGHeroInstance.h" #include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/mapObjects/MiscObjects.h" #include "../../lib/mapObjects/MiscObjects.h"
#include "../../lib/spells/ViewSpellInt.h"
void MapViewController::setViewCenter(const int3 & position) void MapViewController::setViewCenter(const int3 & position)
{ {
@ -185,3 +186,14 @@ bool MapViewController::hasOngoingAnimations()
return false; return false;
} }
void MapViewController::setTerrainVisibility(bool showAllTerrain)
{
context->showAllTerrain = showAllTerrain;
}
void MapViewController::setOverlayVisibility(const std::vector<ObjectPosInfo> & objectPositions)
{
context->additionalOverlayIcons = objectPositions;
}

View File

@ -13,7 +13,9 @@
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
class Point; class Point;
struct ObjectPosInfo;
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END
class MapViewModel; class MapViewModel;
class MapRendererContext; class MapRendererContext;
@ -42,4 +44,8 @@ public:
void setViewCenter(const Point & position, int level); void setViewCenter(const Point & position, int level);
void setTileSize(const Point & tileSize); void setTileSize(const Point & tileSize);
void update(uint32_t timeDelta); void update(uint32_t timeDelta);
void setTerrainVisibility(bool showAllTerrain);
void setOverlayVisibility(const std::vector<ObjectPosInfo> & objectPositions);
}; };

View File

@ -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 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 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) virtual boost::optional<BattleAction> makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState)
{ {

View File

@ -1908,12 +1908,14 @@ protected:
struct DLL_LINKAGE ShowWorldViewEx : public CPackForClient struct DLL_LINKAGE ShowWorldViewEx : public CPackForClient
{ {
PlayerColor player; PlayerColor player;
bool showTerrain; // TODO: send terrain state
std::vector<ObjectPosInfo> objectPositions; std::vector<ObjectPosInfo> objectPositions;
template <typename Handler> void serialize(Handler & h, const int version) template <typename Handler> void serialize(Handler & h, const int version)
{ {
h & player; h & player;
h & showTerrain;
h & objectPositions; h & objectPositions;
} }

View File

@ -585,6 +585,7 @@ ESpellCastResult ViewMechanics::applyAdventureEffects(SpellCastEnvironment * env
pack.objectPositions.push_back(posInfo); pack.objectPositions.push_back(posInfo);
} }
} }
pack.showTerrain = showTerrain(spellLevel);
env->apply(&pack); 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); 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::ViewEarthMechanics(const CSpell * s): ViewEarthMechanics::ViewEarthMechanics(const CSpell * s):
ViewMechanics(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); 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 VCMI_LIB_NAMESPACE_END

View File

@ -82,6 +82,7 @@ public:
protected: protected:
ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override; ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
virtual bool filterObject(const CGObjectInstance * obj, const int32_t spellLevel) const = 0; 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 class DLL_LINKAGE ViewAirMechanics : public ViewMechanics
@ -90,6 +91,7 @@ public:
ViewAirMechanics(const CSpell * s); ViewAirMechanics(const CSpell * s);
protected: protected:
bool filterObject(const CGObjectInstance * obj, const int32_t spellLevel) const override; 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 class DLL_LINKAGE ViewEarthMechanics : public ViewMechanics
@ -98,6 +100,7 @@ public:
ViewEarthMechanics(const CSpell * s); ViewEarthMechanics(const CSpell * s);
protected: protected:
bool filterObject(const CGObjectInstance * obj, const int32_t spellLevel) const override; bool filterObject(const CGObjectInstance * obj, const int32_t spellLevel) const override;
bool showTerrain(const int32_t spellLevel) const override;
}; };