1
0
mirror of https://github.com/vcmi/vcmi.git synced 2026-05-22 09:55:17 +02:00
Files
vcmi/lib/mapObjects/IObjectInterface.cpp
T
Andrej Dudenhefner 410d2c0623 add aviation
- add EPathfindingLayer `AVIATE` (different from `AIR`, can hover over free land and water)
- add transitions: `LAND` <-> `AVIATE` <-> `AIR` (cannot stop over obstacle)
- add layer specification to `MoveHero` destination handling
- add path finder `AVIATE` rules
- add node storage `AVIATE` specifications
- add adventure map aviation interactions
- add EAdventureState `DISEMBARKING`
- add disembark shortcut Shift+D for `ADVENTURE_DISEMBARK`
- add cursor icons for aviation under CC-BY-SA license
- correct move point generation / consumption
- can buy an airship from Airship Yard on land and coast at fixed cost
- add localization
2026-04-21 10:47:10 +02:00

170 lines
4.2 KiB
C++

/*
* IObjectInterface.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#include "StdInc.h"
#include "IObjectInterface.h"
#include "CGTownInstance.h"
#include "MiscObjects.h"
#include "../TerrainHandler.h"
#include "../callback/IGameInfoCallback.h"
#include "../callback/IGameEventCallback.h"
#include "CGHeroInstance.h"
#include "../mapping/TerrainTile.h"
#include "../networkPacks/PacksForClient.h"
VCMI_LIB_NAMESPACE_BEGIN
void IObjectInterface::showInfoDialog(IGameEventCallback & gameEvents, const ui32 txtID, const ui16 soundID, EInfoWindowMode mode) const
{
InfoWindow iw;
iw.soundID = soundID;
iw.player = getOwner();
iw.type = mode;
iw.text.appendLocalString(EMetaText::ADVOB_TXT,txtID);
gameEvents.sendAndApply(iw);
}
///IObjectInterface
void IObjectInterface::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
{}
void IObjectInterface::onHeroLeave(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
{}
void IObjectInterface::newTurn(IGameEventCallback & gameEvents, IGameRandomizer & gameRandomizer) const
{}
void IObjectInterface::initObj(IGameRandomizer & gameRandomizer)
{}
void IObjectInterface::pickRandomObject(IGameRandomizer & gameRandomizer)
{}
void IObjectInterface::setProperty(ObjProperty what, ObjPropertyID identifier)
{}
bool IObjectInterface::wasVisited (PlayerColor player) const
{
return false;
}
bool IObjectInterface::wasVisited (const CGHeroInstance * h) const
{
return false;
}
void IObjectInterface::postInit()
{}
void IObjectInterface::preInit()
{}
void IObjectInterface::battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance *hero, const BattleResult &result) const
{}
void IObjectInterface::blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const
{}
void IObjectInterface::garrisonDialogClosed(IGameEventCallback & gameEvents, const CGHeroInstance *hero) const
{}
void IObjectInterface::heroLevelUpDone(IGameEventCallback & gameEvents, const CGHeroInstance *hero) const
{}
int3 IBoatGenerator::bestLocation() const
{
std::vector<int3> offsets;
getOutOffsets(offsets);
for (auto & offset : offsets)
{
int3 targetTile = getObject()->visitablePos() + offset;
const TerrainTile *tile = getObject()->cb->getTile(targetTile, false);
if(!tile)
continue; // tile not visible / outside the map
if(getBoatLayer() == EPathfindingLayer::SAIL && !tile->isWater())
continue;
if (tile->blocked())
continue;
if (tile->visitable())
{
bool hasBoat = false;
for (auto const & objectID : tile->visitableObjects)
{
const auto * object = getObject()->cb->getObj(objectID);
if (object->ID == Obj::BOAT || object->ID == Obj::HERO)
hasBoat = true;
}
if (!hasBoat)
continue; // tile is blocked, but not by boat -> check next potential position
}
return targetTile;
}
return int3 (-1,-1,-1);
}
IBoatGenerator::EGeneratorState IBoatGenerator::shipyardStatus() const
{
int3 tile = bestLocation();
if(!tile.isValid())
return TILE_BLOCKED; //no available water
const TerrainTile *t = getObject()->cb->getTile(tile);
if(!t)
return TILE_BLOCKED; //no available water
if(t->blockingObjects.empty())
return GOOD; //OK
auto blockerObject = getObject()->cb->getObjInstance(t->blockingObjects.front());
if(blockerObject->ID == Obj::BOAT || blockerObject->ID == Obj::HERO)
return BOAT_ALREADY_BUILT; //blocked with boat
return TILE_BLOCKED; //blocked
}
void IBoatGenerator::getProblemText(MetaString &out, const CGHeroInstance *visitor) const
{
switch(shipyardStatus())
{
case BOAT_ALREADY_BUILT:
out.appendLocalString(EMetaText::GENERAL_TXT, 51);
break;
case TILE_BLOCKED:
if(visitor)
{
out.appendLocalString(EMetaText::GENERAL_TXT, 134);
out.replaceRawString(visitor->getNameTranslated());
}
else
out.appendLocalString(EMetaText::ADVOB_TXT, 189);
break;
case NO_WATER:
logGlobal->error("Shipyard without water at tile %s! ", getObject()->anchorPos().toString());
return;
}
}
void IShipyard::getBoatCost(TResources & cost) const
{
cost[EGameResID::WOOD] = 10;
cost[EGameResID::GOLD] = 1000;
}
VCMI_LIB_NAMESPACE_END