Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix object picking up animation, fix object remove from map and fix restoration of the object type for the tile #8949

Merged
merged 37 commits into from
Jul 21, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
1f4fa83
Fix artifact picking up animation when it is set to the bottom layer …
Districh-ru Jul 10, 2024
bb3a940
Make IWYU happy
Districh-ru Jul 10, 2024
174fde4
Use the same get UID approach for all objects fade out animation
Districh-ru Jul 10, 2024
6e7eb52
Fix incorrect included header
Districh-ru Jul 10, 2024
65a27c9
Reduce code duplication
Districh-ru Jul 12, 2024
adef3d4
Restore object type after action object pick up
Districh-ru Jul 12, 2024
d5911f3
Fix jail upper tiles restoration after remove
Districh-ru Jul 12, 2024
9ea10fe
Also check the bottom layer when removing the action object (campaign…
Districh-ru Jul 12, 2024
ab6c643
Rename: setAsEmpty() -> updateObjectType()
Districh-ru Jul 13, 2024
ba65a24
Remove `updateEmpty()` method. Use its code in the only place where i…
Districh-ru Jul 13, 2024
c8e9065
Remove invalid assertion - monsters can be recruited from other objec…
Districh-ru Jul 13, 2024
8766745
Fix radar update after removing an object.
Districh-ru Jul 13, 2024
0ade01f
Merge branch 'master' into pr/8949
ihhub Jul 14, 2024
45b1e6f
Expand the comment
ihhub Jul 14, 2024
dbb09ff
Update logic
ihhub Jul 14, 2024
30d8f30
Update logic
ihhub Jul 14, 2024
1717be4
Rename function to reflect what it does
ihhub Jul 14, 2024
ffa303d
Add an extra check
ihhub Jul 14, 2024
680b6a7
Update logic
ihhub Jul 14, 2024
23a532e
Add extra boat directions to properly get object type by boat ICN id …
Districh-ru Jul 14, 2024
3b1d772
Update logic
ihhub Jul 14, 2024
4cd3a6d
Remove a comment
ihhub Jul 14, 2024
b982293
Remove unused variable
ihhub Jul 14, 2024
eadfc19
Add a TODO comment
ihhub Jul 14, 2024
fbcc0e7
Use revert indexing for objects
ihhub Jul 14, 2024
d1f3266
Add an assertion
ihhub Jul 14, 2024
ee886a0
Update logic
ihhub Jul 14, 2024
5429369
Add const
ihhub Jul 14, 2024
f66bb3a
Minot speed-up in removeObjectFromMapByUID()
Districh-ru Jul 14, 2024
97e2d52
Combine scoutTileOnRadar() with runActionObjectFadeOutAnumation()
Districh-ru Jul 14, 2024
f0e31ed
Make sure to set interactive action object type first
ihhub Jul 14, 2024
9904e80
Fix logic
ihhub Jul 14, 2024
eacd614
Fix the condition
ihhub Jul 14, 2024
ca44335
Update logic
Districh-ru Jul 14, 2024
1e56bde
Revert "Update logic"
Districh-ru Jul 14, 2024
5395477
Address comments
Districh-ru Jul 14, 2024
4efee5f
Merge branch 'master' into fix-artifact-pickup
Districh-ru Jul 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/fheroes2/ai/ai_hero_action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ namespace
setMonsterCountOnTile( tile, 0 );

removeObjectSprite( tile );
tile.setAsEmpty();
tile.updateObjectType();
}
}

Expand Down Expand Up @@ -1401,7 +1401,7 @@ namespace
// Remove genie lamp sprite if no genies are available to hire.
if ( MP2::OBJ_GENIE_LAMP == objectType && ( availableTroopCount == recruitTroopCount ) ) {
removeObjectSprite( tile );
tile.setAsEmpty();
tile.updateObjectType();
}
}

Expand Down Expand Up @@ -1502,7 +1502,7 @@ namespace

if ( kingdom.IsVisitTravelersTent( getColorFromTile( tile ) ) ) {
removeObjectSprite( tile );
tile.setAsEmpty();
tile.updateObjectType();
}
}

Expand Down Expand Up @@ -1661,7 +1661,7 @@ namespace
Maps::Tiles & tile = world.GetTiles( tileIndex );

removeObjectSprite( tile );
tile.setAsEmpty();
tile.updateObjectType();

Heroes * prisoner = world.FromJailHeroes( tileIndex );

Expand Down Expand Up @@ -2219,7 +2219,7 @@ namespace AI
}
else {
removeObjectSprite( tileSource );
tileSource.setAsEmpty();
tileSource.updateObjectType();
}

Maps::Tiles & tileDest = world.GetTiles( boatDestinationIndex );
Expand Down
2 changes: 1 addition & 1 deletion src/fheroes2/gui/interface_gamearea.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1205,6 +1205,6 @@ Interface::ObjectFadingOutInfo::~ObjectFadingOutInfo()

if ( tile.GetObject() == type ) {
removeObjectSprite( tile );
tile.setAsEmpty();
tile.updateObjectType();
}
}
100 changes: 70 additions & 30 deletions src/fheroes2/heroes/heroes_action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <cstddef>
#include <cstdint>
#include <initializer_list>
#include <list>
#include <memory>
#include <ostream>
#include <string>
Expand Down Expand Up @@ -59,6 +60,7 @@
#include "localevent.h"
#include "logging.h"
#include "m82.h"
#include "map_object_info.h"
#include "maps.h"
#include "maps_objects.h"
#include "maps_tiles.h"
Expand Down Expand Up @@ -218,6 +220,36 @@ namespace
I.setRedraw( Interface::REDRAW_RADAR );
}

void runActionObjectFadeOutAnumation( const Maps::Tiles & tile, const MP2::MapObjectType objectType )
{
uint32_t objectUID = 0;

if ( Maps::getObjectTypeByIcn( tile.getObjectIcnType(), tile.GetObjectSpriteIndex() ) == objectType ) {
objectUID = tile.GetObjectUID();
}
else {
// In maps made by the original map editor the action object can be in the bottom layer addons.
for ( const Maps::TilesAddon & addon : tile.getBottomLayerAddons() ) {
if ( Maps::getObjectTypeByIcn( addon._objectIcnType, addon._imageIndex ) == objectType ) {
objectUID = addon._uid;
break;
}
}
}

assert( objectUID != 0 );

Interface::AdventureMap::Get().getGameArea().runSingleObjectAnimation(
std::make_shared<Interface::ObjectFadingOutInfo>( objectUID, tile.GetIndex(), objectType ) );
}

void scoutTileOnRadar( const int32_t tileIndex )
{
Interface::AdventureMap & I = Interface::AdventureMap::Get();
I.getRadar().SetRenderArea( { { Maps::GetPoint( tileIndex ) }, { 1, 1 } } );
I.setRedraw( Interface::REDRAW_RADAR );
}

void RecruitMonsterFromTile( Heroes & hero, Maps::Tiles & tile, const std::string & msg, const Troop & troop, bool remove )
{
if ( !hero.GetArmy().CanJoinTroop( troop ) )
Expand All @@ -231,8 +263,10 @@ namespace

setMonsterCountOnTile( tile, 0 );

Interface::AdventureMap::Get().getGameArea().runSingleObjectAnimation(
std::make_shared<Interface::ObjectFadingOutInfo>( tile.GetObjectUID(), tile.GetIndex(), tile.GetObject() ) );
runActionObjectFadeOutAnumation( tile, tile.GetObject() );

// Update the position of recruited monster on radar.
scoutTileOnRadar( tile.GetIndex() );
}
else {
setMonsterCountOnTile( tile, troop.GetCount() - recruit );
Expand Down Expand Up @@ -421,8 +455,12 @@ namespace

setMonsterCountOnTile( tile, 0 );
ihhub marked this conversation as resolved.
Show resolved Hide resolved

Interface::AdventureMap::Get().getGameArea().runSingleObjectAnimation(
std::make_shared<Interface::ObjectFadingOutInfo>( tile.GetObjectUID(), tile.GetIndex(), tile.GetObject() ) );
assert( tile.GetObject() == MP2::OBJ_MONSTER );

runActionObjectFadeOutAnumation( tile, MP2::OBJ_MONSTER );

// Update the position of defeated monster on radar.
scoutTileOnRadar( dst_index );
}

// Clear the hero's attacked monster tile index
Expand Down Expand Up @@ -701,16 +739,12 @@ namespace

Game::PlayPickupSound();

I.getGameArea().runSingleObjectAnimation( std::make_shared<Interface::ObjectFadingOutInfo>( tile.GetObjectUID(), tile.GetIndex(), tile.GetObject() ) );
runActionObjectFadeOutAnumation( tile, objectType );

resetObjectInfoOnTile( tile );

if ( objectType == MP2::OBJ_RESOURCE ) {
// Update the position of picked up resource on radar to remove its mark.
const fheroes2::Point resourcePosition = Maps::GetPoint( dst_index );
I.getRadar().SetRenderArea( { resourcePosition.x, resourcePosition.y, 1, 1 } );
I.setRedraw( Interface::REDRAW_RADAR );
}
// Update the position of picked up resource on radar to remove its mark.
scoutTileOnRadar( dst_index );
}

void ActionToObjectResource( const Heroes & hero, const MP2::MapObjectType objectType, int32_t dst_index )
Expand Down Expand Up @@ -910,10 +944,12 @@ namespace

Game::PlayPickupSound();

Interface::AdventureMap::Get().getGameArea().runSingleObjectAnimation(
std::make_shared<Interface::ObjectFadingOutInfo>( tile.GetObjectUID(), tile.GetIndex(), tile.GetObject() ) );
runActionObjectFadeOutAnumation( tile, objectType );

resetObjectInfoOnTile( tile );

// Update the position of picked up object on radar.
scoutTileOnRadar( dst_index );
}

void ActionToShrine( Heroes & hero, int32_t dst_index )
Expand Down Expand Up @@ -1537,10 +1573,12 @@ namespace

Game::PlayPickupSound();

Interface::AdventureMap::Get().getGameArea().runSingleObjectAnimation(
std::make_shared<Interface::ObjectFadingOutInfo>( tile.GetObjectUID(), tile.GetIndex(), tile.GetObject() ) );
runActionObjectFadeOutAnumation( tile, objectType );

resetObjectInfoOnTile( tile );

// Update the position of picked up object on radar.
scoutTileOnRadar( dst_index );
}

void ActionToArtifact( Heroes & hero, int32_t dst_index )
Expand Down Expand Up @@ -1718,17 +1756,14 @@ namespace
if ( result && hero.PickupArtifact( art ) ) {
Game::PlayPickupSound();

Interface::AdventureMap & I = Interface::AdventureMap::Get();
assert( tile.GetObject() == MP2::OBJ_ARTIFACT );

I.getGameArea().runSingleObjectAnimation( std::make_shared<Interface::ObjectFadingOutInfo>( tile.GetObjectUID(), tile.GetIndex(), tile.GetObject() ) );
runActionObjectFadeOutAnumation( tile, MP2::OBJ_ARTIFACT );

resetObjectInfoOnTile( tile );

const fheroes2::Point artifactPosition = Maps::GetPoint( dst_index );

// Update the position of picked up artifact on radar to remove its mark.
I.getRadar().SetRenderArea( { artifactPosition.x, artifactPosition.y, 1, 1 } );
I.setRedraw( Interface::REDRAW_RADAR );
scoutTileOnRadar( dst_index );
}
}

Expand Down Expand Up @@ -1835,10 +1870,12 @@ namespace

Game::PlayPickupSound();

Interface::AdventureMap::Get().getGameArea().runSingleObjectAnimation(
std::make_shared<Interface::ObjectFadingOutInfo>( tile.GetObjectUID(), tile.GetIndex(), tile.GetObject() ) );
runActionObjectFadeOutAnumation( tile, objectType );

resetObjectInfoOnTile( tile );

// Update the position of picked up chest on radar.
scoutTileOnRadar( dst_index );
}

void ActionToGenieLamp( Heroes & hero, const MP2::MapObjectType objectType, int32_t dst_index )
Expand Down Expand Up @@ -3271,10 +3308,7 @@ namespace
_( "In a dazzling display of daring, you break into the local jail and free the hero imprisoned there, who, in return, pledges loyalty to your cause." ),
Dialog::OK );

Interface::AdventureMap & adventureMapInterface = Interface::AdventureMap::Get();

adventureMapInterface.getGameArea().runSingleObjectAnimation(
std::make_shared<Interface::ObjectFadingOutInfo>( tile.GetObjectUID(), tile.GetIndex(), tile.GetObject() ) );
runActionObjectFadeOutAnumation( tile, objectType );

// TODO: add hero fading in animation together with jail animation.
Heroes * prisoner = world.FromJailHeroes( dst_index );
Expand All @@ -3283,7 +3317,11 @@ namespace
prisoner->Recruit( hero.GetColor(), Maps::GetPoint( dst_index ) );

// Update the kingdom heroes list including the scrollbar.
adventureMapInterface.GetIconsPanel().ResetIcons( ICON_HEROES );
Interface::AdventureMap::Get().GetIconsPanel().ResetIcons( ICON_HEROES );
}
else {
// Update the position of removed jail on radar.
scoutTileOnRadar( dst_index );
}
}
else {
Expand Down Expand Up @@ -3525,8 +3563,10 @@ namespace

AudioManager::PlaySound( M82::KILLFADE );

Interface::AdventureMap::Get().getGameArea().runSingleObjectAnimation(
std::make_shared<Interface::ObjectFadingOutInfo>( tile.GetObjectUID(), tile.GetIndex(), tile.GetObject() ) );
runActionObjectFadeOutAnumation( tile, objectType );

// Update the position of removed barrier on radar.
scoutTileOnRadar( dst_index );
}
else {
fheroes2::showStandardTextMessage(
Expand Down
47 changes: 34 additions & 13 deletions src/fheroes2/maps/maps_tiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "heroes.h"
#include "icn.h"
#include "logging.h"
#include "map_object_info.h"
#include "maps.h"
#include "maps_tiles_helper.h" // TODO: This file should not be included
#include "mounts.h"
Expand Down Expand Up @@ -480,7 +481,7 @@ void Maps::Tiles::setHero( Heroes * hero )
hero->setObjectTypeUnderHero( MP2::OBJ_NONE );
}
else {
setAsEmpty();
updateObjectType();
}

_occupantHeroId = Heroes::UNKNOWN;
Expand Down Expand Up @@ -1453,24 +1454,43 @@ void Maps::Tiles::updateTileObjectIcnIndex( Maps::Tiles & tile, const uint32_t u
tile._updateRoadFlag();
}

void Maps::Tiles::updateEmpty()
void Maps::Tiles::updateObjectType()
{
if ( _mainObjectType == MP2::OBJ_NONE ) {
setAsEmpty();
// After removing an object there could be some other object part in the main addon.
const MP2::MapObjectType objectType = Maps::getObjectTypeByIcn( _mainAddon._objectIcnType, _mainAddon._imageIndex );
if ( objectType != MP2::OBJ_NONE ) {
SetObject( objectType );
return;
}

// Or object part can be in the top layer addons.
for ( const Maps::TilesAddon & addon : _addonTopLayer ) {
const MP2::MapObjectType objectType = Maps::getObjectTypeByIcn( addon._objectIcnType, addon._imageIndex );
ihhub marked this conversation as resolved.
Show resolved Hide resolved

if ( objectType != MP2::OBJ_NONE ) {
SetObject( objectType );
return;
}
}

// And sometimes even in the bottom layer addons.
for ( const Maps::TilesAddon & addon : _addonBottomLayer ) {
const MP2::MapObjectType objectType = Maps::getObjectTypeByIcn( addon._objectIcnType, addon._imageIndex );
ihhub marked this conversation as resolved.
Show resolved Hide resolved

if ( objectType != MP2::OBJ_NONE ) {
SetObject( objectType );
return;
}
}
}

void Maps::Tiles::setAsEmpty()
{
// If an object is removed we should validate if this tile a potential candidate to be a coast.
// Check if this tile is not water and it has neighbouring water tiles.
if ( isWater() ) {
SetObject( MP2::OBJ_NONE );
assert( objectType == MP2::OBJ_NONE );
SetObject( objectType );
return;
}

bool isCoast = false;

const Indexes tileIndices = Maps::getAroundIndexes( _index, 1 );
for ( const int tileIndex : tileIndices ) {
if ( tileIndex < 0 ) {
Expand All @@ -1479,12 +1499,13 @@ void Maps::Tiles::setAsEmpty()
}

if ( world.GetTiles( tileIndex ).isWater() ) {
isCoast = true;
break;
SetObject( MP2::OBJ_COAST );
return;
}
}

SetObject( isCoast ? MP2::OBJ_COAST : MP2::OBJ_NONE );
assert( objectType == MP2::OBJ_NONE );
SetObject( objectType );
}

uint32_t Maps::Tiles::getObjectIdByObjectIcnType( const MP2::ObjectIcnType objectIcnType ) const
Expand Down
10 changes: 5 additions & 5 deletions src/fheroes2/maps/maps_tiles.h
Original file line number Diff line number Diff line change
Expand Up @@ -340,11 +340,11 @@ namespace Maps
Heroes * getHero() const;
void setHero( Heroes * hero );

// If tile is empty (MP2::OBJ_NONE) then verify whether it is a coast and update the tile if needed.
void updateEmpty();

// Set tile to coast MP2::OBJ_COAST) if it's near water or to empty (MP2::OBJ_NONE)
void setAsEmpty();
// Set tile's object type according to the object's sprite if there is any, otherwise
// it is set to coast (MP2::OBJ_COAST) if it's near water or to empty (MP2::OBJ_NONE).
// This method works perfectly only on Resurrection (.fh2m) maps.
// It might not work properly on the original maps due to small differences in object types.
void updateObjectType();

uint32_t getObjectIdByObjectIcnType( const MP2::ObjectIcnType objectIcnType ) const;

Expand Down
Loading
Loading