Skip to content

Commit

Permalink
Fix logic
Browse files Browse the repository at this point in the history
  • Loading branch information
ihhub committed Oct 19, 2024
1 parent 946a916 commit df38dcd
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 34 deletions.
4 changes: 2 additions & 2 deletions src/fheroes2/ai/ai_hero_action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1728,9 +1728,9 @@ namespace
if ( !hero.isObjectTypeVisited( objectType, Visit::GLOBAL ) ) {
hero.SetVisited( tileIndex, Visit::GLOBAL );

const MapsIndexes eyeMagiIndexes = Maps::GetObjectPositions( MP2::OBJ_EYE_OF_MAGI );
const auto eyeMagiIndexes = Maps::getObjectParts( MP2::OBJ_EYE_OF_MAGI );
const uint32_t distance = GameStatic::getFogDiscoveryDistance( GameStatic::FogDiscoveryType::MAGI_EYES );
for ( const int32_t index : eyeMagiIndexes ) {
for ( const auto& [index, objectPart] : eyeMagiIndexes ) {
Maps::ClearFog( index, distance, hero.GetColor() );
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/fheroes2/ai/ai_planner_hero.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1535,12 +1535,12 @@ double AI::Planner::getGeneralObjectValue( const Heroes & hero, const int32_t in
}
case MP2::OBJ_HUT_OF_MAGI: {
// TODO: cache Maps::GetObjectPositions() call as this is a very heavy operation.
const MapsIndexes eyeMagiIndexes = Maps::GetObjectPositions( MP2::OBJ_EYE_OF_MAGI );
const auto eyeMagiIndexes = Maps::getObjectParts( MP2::OBJ_EYE_OF_MAGI );
int fogCountToUncover = 0;
const int heroColor = hero.GetColor();
const int eyeViewDistance = GameStatic::getFogDiscoveryDistance( GameStatic::FogDiscoveryType::MAGI_EYES );

for ( const int32_t eyeIndex : eyeMagiIndexes ) {
for ( const auto& [eyeIndex, objectPart] : eyeMagiIndexes ) {
fogCountToUncover += Maps::getFogTileCountToBeRevealed( eyeIndex, eyeViewDistance, heroColor );
}

Expand Down
4 changes: 2 additions & 2 deletions src/fheroes2/heroes/heroes_action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3332,7 +3332,7 @@ namespace
if ( !hero.isObjectTypeVisited( objectType, Visit::GLOBAL ) ) {
hero.SetVisited( dst_index, Visit::GLOBAL );

const MapsIndexes eyeMagiIndexes = Maps::GetObjectPositions( MP2::OBJ_EYE_OF_MAGI );
const auto eyeMagiIndexes = Maps::getObjectParts( MP2::OBJ_EYE_OF_MAGI );
if ( !eyeMagiIndexes.empty() ) {
Interface::AdventureMap & I = Interface::AdventureMap::Get();

Expand All @@ -3344,7 +3344,7 @@ namespace
bool skipAnimation = false;
fheroes2::Rect radarRenderArea;

for ( const int32_t eyeIndex : eyeMagiIndexes ) {
for ( const auto& [eyeIndex, objectPart] : eyeMagiIndexes ) {
Maps::ClearFog( eyeIndex, scoutRange, hero.GetColor() );

const fheroes2::Point eyePosition = Maps::GetPoint( eyeIndex );
Expand Down
13 changes: 11 additions & 2 deletions src/fheroes2/maps/maps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -479,9 +479,18 @@ bool Maps::doesObjectExistOnMap( const MP2::MapObjectType objectType )
return false;
}

Maps::Indexes Maps::GetObjectPositions( const MP2::MapObjectType objectType )
std::vector<std::pair<int32_t, const Maps::TilesAddon *>> Maps::getObjectParts( const MP2::MapObjectType objectType )
{
return MapsIndexesObject( objectType, true );
std::vector<std::pair<int32_t, const TilesAddon *>> result;
const int32_t size = static_cast<int32_t>( world.getSize() );
for ( int32_t idx = 0; idx < size; ++idx ) {
const Maps::TilesAddon * objectPart = getObjectPartByType( world.GetTiles( idx ), objectType );
if ( objectPart != nullptr ) {
result.emplace_back( idx, objectPart );
}
}

return result;
}

Maps::Indexes Maps::GetObjectPositions( int32_t center, const MP2::MapObjectType objectType, bool ignoreHeroes )
Expand Down
4 changes: 3 additions & 1 deletion src/fheroes2/maps/maps.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ using MapsIndexes = std::vector<int32_t>;

namespace Maps
{
struct TilesAddon;

enum mapsize_t : int
{
ZERO = 0,
Expand Down Expand Up @@ -89,7 +91,7 @@ namespace Maps
bool doesObjectExistOnMap( const MP2::MapObjectType objectType );

// This function always ignores heroes.
Indexes GetObjectPositions( const MP2::MapObjectType objectType );
std::vector<std::pair<int32_t, const TilesAddon *>> getObjectParts( const MP2::MapObjectType objectType );

Indexes GetObjectPositions( int32_t center, const MP2::MapObjectType objectType, bool ignoreHeroes );

Expand Down
15 changes: 14 additions & 1 deletion src/fheroes2/maps/maps_tiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -532,8 +532,21 @@ void Maps::Tiles::setHero( Heroes * hero )
hero = getHero();

if ( hero ) {
SetObject( hero->getObjectTypeUnderHero() );
const MP2::MapObjectType type = hero->getObjectTypeUnderHero();
hero->setObjectTypeUnderHero( MP2::OBJ_NONE );
// While updating the main object type when a hero moves away from a tile we can have 3 situations:
// - the underlying object type is MP2::OBJ_NONE. In this case we should update the tile object type.
// - the underlying object type is MP2::OBJ_NONE:
// - if the object exists then we do nothing.
// - if the object doesn't exist then we have to update the tile object type.
//
// The last case can happen only when a hero boards a boat which is under another sea object, like whirlpool.
if ( ( type == MP2::OBJ_NONE ) || !doesTileContainObjectType( *this, type ) ) {
updateObjectType();
}
else {
SetObject( type );
}
}
else {
updateObjectType();
Expand Down
48 changes: 48 additions & 0 deletions src/fheroes2/maps/maps_tiles_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1593,6 +1593,54 @@ namespace Maps
return 0;
}

bool doesTileContainObjectType( const Tiles & tile, const MP2::MapObjectType type )
{
MP2::MapObjectType objectType = getObjectTypeByIcn( tile.getMainObjectPart()._objectIcnType, tile.getMainObjectPart()._imageIndex );
if ( objectType == type ) {
return true;
}

for ( const auto & objectPart : tile.getBottomLayerAddons() ) {
objectType = getObjectTypeByIcn( objectPart._objectIcnType, objectPart._imageIndex );
if ( objectType == type ) {
return true;
}
}

for ( const auto & objectPart : tile.getTopLayerAddons() ) {
objectType = getObjectTypeByIcn( objectPart._objectIcnType, objectPart._imageIndex );
if ( objectType == type ) {
return true;
}
}

return false;
}

const TilesAddon * getObjectPartByType( const Tiles & tile, const MP2::MapObjectType type )
{
MP2::MapObjectType objectType = getObjectTypeByIcn( tile.getMainObjectPart()._objectIcnType, tile.getMainObjectPart()._imageIndex );
if ( objectType == type ) {
return &tile.getMainObjectPart();
}

for ( const auto & objectPart : tile.getBottomLayerAddons() ) {
objectType = getObjectTypeByIcn( objectPart._objectIcnType, objectPart._imageIndex );
if ( objectType == type ) {
return &objectPart;
}
}

for ( const auto & objectPart : tile.getTopLayerAddons() ) {
objectType = getObjectTypeByIcn( objectPart._objectIcnType, objectPart._imageIndex );
if ( objectType == type ) {
return &objectPart;
}
}

return nullptr;
}

Monster getMonsterFromTile( const Tiles & tile )
{
switch ( tile.GetObject( false ) ) {
Expand Down
5 changes: 5 additions & 0 deletions src/fheroes2/maps/maps_tiles_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ namespace MP2
namespace Maps
{
class Tiles;
struct TilesAddon;

struct ObjectInfo;

Expand Down Expand Up @@ -104,6 +105,10 @@ namespace Maps
int getColorFromBarrierSprite( const MP2::ObjectIcnType objectIcnType, const uint8_t icnIndex );
int getColorFromTravellerTentSprite( const MP2::ObjectIcnType objectIcnType, const uint8_t icnIndex );

bool doesTileContainObjectType( const Tiles & tile, const MP2::MapObjectType type );

const TilesAddon * getObjectPartByType( const Tiles & tile, const MP2::MapObjectType type );

Monster getMonsterFromTile( const Tiles & tile );

Artifact getArtifactFromTile( const Tiles & tile );
Expand Down
40 changes: 16 additions & 24 deletions src/fheroes2/world/world.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -792,8 +792,14 @@ MapsIndexes World::GetTeleportEndPoints( const int32_t index ) const
return result;
}

const Maps::TilesAddon * entranceObjectPart = Maps::getObjectPartByType( entranceTile, MP2::OBJ_STONE_LITHS );
if ( entranceObjectPart == nullptr ) {
assert( 0 );
return result;
}

// The type of destination stone liths must match the type of the source stone liths.
for ( const int32_t teleportIndex : _allTeleports.at( entranceTile.getMainObjectPart()._imageIndex ) ) {
for ( const int32_t teleportIndex : _allTeleports.at( entranceObjectPart->_imageIndex ) ) {
const Maps::Tiles & teleportTile = GetTiles( teleportIndex );

if ( teleportIndex == index || teleportTile.GetObject() != MP2::OBJ_STONE_LITHS || teleportTile.isWater() != entranceTile.isWater() ) {
Expand Down Expand Up @@ -829,24 +835,7 @@ MapsIndexes World::GetWhirlpoolEndPoints( const int32_t index ) const
return result;
}

const auto getWhirlPoolObjectPart = []( const Maps::Tiles & tile ) -> const Maps::TilesAddon * {
// The exit point from the destination whirlpool must match the entry point in the source whirlpool.
// A whirlpool can be as a main addon / object part or bottom part. This is important to get a proper object part.
if ( Maps::getObjectTypeByIcn( tile.getMainObjectPart()._objectIcnType, tile.getMainObjectPart()._imageIndex ) == MP2::OBJ_WHIRLPOOL ) {
return &tile.getMainObjectPart();
}

for ( const auto & part : tile.getBottomLayerAddons() ) {
if ( Maps::getObjectTypeByIcn( part._objectIcnType, part._imageIndex ) == MP2::OBJ_WHIRLPOOL ) {
return &part;
}
}

assert( 0 );
return nullptr;
};

const Maps::TilesAddon * entranceObjectPart = getWhirlPoolObjectPart( entranceTile );
const Maps::TilesAddon * entranceObjectPart = Maps::getObjectPartByType( entranceTile, MP2::OBJ_WHIRLPOOL );
if ( entranceObjectPart == nullptr ) {
return result;
}
Expand All @@ -857,7 +846,7 @@ MapsIndexes World::GetWhirlpoolEndPoints( const int32_t index ) const
continue;
}

const Maps::TilesAddon * destinationObjectPart = getWhirlPoolObjectPart( whirlpoolTile );
const Maps::TilesAddon * destinationObjectPart = Maps::getObjectPartByType( whirlpoolTile, MP2::OBJ_WHIRLPOOL );
if ( destinationObjectPart == nullptr ) {
continue;
}
Expand Down Expand Up @@ -1357,15 +1346,18 @@ void World::PostLoad( const bool setTilePassabilities, const bool updateUidCount
// Cache all tiles that that contain stone liths of a certain type (depending on object sprite index).
_allTeleports.clear();

for ( const int32_t index : Maps::GetObjectPositions( MP2::OBJ_STONE_LITHS ) ) {
_allTeleports[GetTiles( index ).getMainObjectPart()._imageIndex].push_back( index );
for ( const auto& [index, objectPart] : Maps::getObjectParts( MP2::OBJ_STONE_LITHS ) ) {
assert( objectPart != nullptr );
_allTeleports[objectPart->_imageIndex].push_back( index );
}

// Cache all tiles that contain a certain part of the whirlpool (depending on object sprite index).
_allWhirlpools.clear();

for ( const int32_t index : Maps::GetObjectPositions( MP2::OBJ_WHIRLPOOL ) ) {
_allWhirlpools[GetTiles( index ).getMainObjectPart()._imageIndex].push_back( index );
for ( const auto& [index, objectPart] : Maps::getObjectParts( MP2::OBJ_WHIRLPOOL ) ) {
assert( objectPart != nullptr );

_allWhirlpools[objectPart->_imageIndex].push_back( index );
}

resetPathfinder();
Expand Down

0 comments on commit df38dcd

Please sign in to comment.