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

Added dynamic interface option #9413

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
28 changes: 19 additions & 9 deletions src/fheroes2/dialog/dialog_interface_settings.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2023 - 2024 *
* Copyright (C) 2023 - 2025 *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
Expand Down Expand Up @@ -63,18 +63,28 @@ namespace
void drawInterfaceType( const fheroes2::Rect & optionRoi )
{
const Settings & conf = Settings::Get();
const bool isEvilInterface = conf.isEvilInterfaceEnabled();
const fheroes2::Sprite & interfaceThemeIcon = fheroes2::AGG::GetICN( ICN::SPANEL, isEvilInterface ? 17 : 16 );
const InterfaceType interfaceType = conf.getInterfaceType();

const fheroes2::Sprite * interfaceThemeIcon;
std::string value;
if ( isEvilInterface ) {
value = _( "Evil" );
}
else {
switch ( interfaceType ) {
case DYNAMIC:
interfaceThemeIcon = &fheroes2::AGG::GetICN( ICN::SPANEL, 15 );
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can make uint32_t icnIndex; and then set its value by the interfaceType and then use it in
const fheroes2::Sprite & interfaceThemeIcon = fheroes2::AGG::GetICN( ICN::SPANEL, icnIndex );
Doing this we will not duplicate the GetICN() call code and will not make a pointer to Sprite.
What do you think?

value = _( "Dynamic" );
break;
case GOOD:
interfaceThemeIcon = &fheroes2::AGG::GetICN( ICN::SPANEL, 16 );
value = _( "Good" );
break;
case EVIL:
interfaceThemeIcon = &fheroes2::AGG::GetICN( ICN::SPANEL, 17 );
value = _( "Evil" );
break;
default:
assert( 0 );
}

fheroes2::drawOption( optionRoi, interfaceThemeIcon, _( "Interface Type" ), std::move( value ), fheroes2::UiOptionTextWidth::TWO_ELEMENTS_ROW );
fheroes2::drawOption( optionRoi, *interfaceThemeIcon, _( "Interface Type" ), std::move( value ), fheroes2::UiOptionTextWidth::TWO_ELEMENTS_ROW );
}

void drawInterfacePresence( const fheroes2::Rect & optionRoi )
Expand Down Expand Up @@ -287,7 +297,7 @@ namespace fheroes2
windowType = showConfigurationWindow( saveConfiguration );
break;
case SelectedWindow::InterfaceType:
conf.setEvilInterface( !conf.isEvilInterfaceEnabled() );
conf.setInterfaceType( static_cast<InterfaceType>( ( conf.getInterfaceType() + 1 ) % ( InterfaceType::DYNAMIC + 1 ) ) );
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be more consistent with the other code we can add InterfaceType::COUNT as a last item of InterfaceType enumeration and use it here instead of ( InterfaceType::DYNAMIC + 1 ).

updateUI();
saveConfiguration = true;

Expand Down
4 changes: 2 additions & 2 deletions src/fheroes2/game/game_campaign.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2020 - 2024 *
* Copyright (C) 2020 - 2025 *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
Expand Down Expand Up @@ -1307,7 +1307,7 @@ fheroes2::GameMode Game::SelectCampaignScenario( const fheroes2::GameMode prevMo
const std::vector<Campaign::ScenarioData> & scenarios = campaignData.getAllScenarios();
const Campaign::ScenarioData & scenario = scenarios[currentScenarioInfoId.scenarioId];

const fheroes2::GameInterfaceTypeRestorer gameInterfaceRestorer( chosenCampaignID != Campaign::ROLAND_CAMPAIGN );
const fheroes2::GameInterfaceTypeRestorer gameInterfaceRestorer( chosenCampaignID == Campaign::ROLAND_CAMPAIGN ? InterfaceType::GOOD : InterfaceType::EVIL );

if ( !allowToRestart ) {
playCurrentScenarioVideo();
Expand Down
11 changes: 8 additions & 3 deletions src/fheroes2/game/game_startgame.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2019 - 2024 *
* Copyright (C) 2019 - 2025 *
* *
* Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 *
* Copyright (C) 2009 by Andrey Afletdinov <[email protected]> *
Expand Down Expand Up @@ -784,6 +784,13 @@ fheroes2::GameMode Interface::AdventureMap::StartGame()
// Reset environment sounds and music theme at the beginning of the human turn
AudioManager::ResetAudio();

conf.SetCurrentColor( playerColor );
if ( conf.getInterfaceType() == InterfaceType::DYNAMIC ) {
reset();
redraw( Interface::REDRAW_RADAR );
redraw( Interface::REDRAW_ALL & ( ~Interface::REDRAW_RADAR ) );
}
Comment on lines +788 to +792
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In single-player game the race of the player is never changed so should we do this (reset(); and radar redraw) only for the Hot Seat game?
And for the single-player game do only reset(); after the line 737.
What do you think?


if ( isHotSeatGame ) {
_iconsPanel.hideIcons( ICON_ANY );
_statusPanel.Reset();
Expand All @@ -804,8 +811,6 @@ fheroes2::GameMode Interface::AdventureMap::StartGame()
Game::DialogPlayers( playerColor, "", _( "%{color} player's turn." ) );
}

conf.SetCurrentColor( playerColor );

kingdom.ActionBeforeTurn();

_iconsPanel.showIcons( ICON_ANY );
Expand Down
16 changes: 8 additions & 8 deletions src/fheroes2/gui/ui_tool.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2020 - 2024 *
* Copyright (C) 2020 - 2025 *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
Expand Down Expand Up @@ -296,19 +296,19 @@ namespace fheroes2
Display::instance().changePalette( palette );
}

GameInterfaceTypeRestorer::GameInterfaceTypeRestorer( const bool isEvilInterface_ )
: isEvilInterface( isEvilInterface_ )
, isOriginalEvilInterface( Settings::Get().isEvilInterfaceEnabled() )
GameInterfaceTypeRestorer::GameInterfaceTypeRestorer( const InterfaceType interfaceType_ )
: interfaceType( interfaceType_ )
, originalInterfaceType( Settings::Get().getInterfaceType() )
{
if ( isEvilInterface != isOriginalEvilInterface ) {
Settings::Get().setEvilInterface( isEvilInterface );
if ( interfaceType != originalInterfaceType ) {
Settings::Get().setInterfaceType( interfaceType_ );
}
}

GameInterfaceTypeRestorer::~GameInterfaceTypeRestorer()
{
if ( isEvilInterface != isOriginalEvilInterface ) {
Settings::Get().setEvilInterface( isOriginalEvilInterface );
if ( interfaceType != originalInterfaceType ) {
Settings::Get().setInterfaceType( originalInterfaceType );
}
}

Expand Down
9 changes: 5 additions & 4 deletions src/fheroes2/gui/ui_tool.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2020 - 2024 *
* Copyright (C) 2020 - 2025 *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
Expand Down Expand Up @@ -31,6 +31,7 @@

#include "image.h"
#include "math_base.h"
#include "settings.h"
#include "timing.h"
#include "ui_base.h"
#include "ui_text.h"
Expand Down Expand Up @@ -174,16 +175,16 @@ namespace fheroes2
struct GameInterfaceTypeRestorer
{
GameInterfaceTypeRestorer() = delete;
explicit GameInterfaceTypeRestorer( const bool isEvilInterface_ );
explicit GameInterfaceTypeRestorer( const InterfaceType interfaceType_ );

GameInterfaceTypeRestorer( const GameInterfaceTypeRestorer & ) = delete;

~GameInterfaceTypeRestorer();

GameInterfaceTypeRestorer & operator=( const GameInterfaceTypeRestorer & ) = delete;

const bool isEvilInterface;
const bool isOriginalEvilInterface;
const InterfaceType interfaceType;
const InterfaceType originalInterfaceType;
};

// Fade display image colors to grayscale part of default game palette.
Expand Down
81 changes: 65 additions & 16 deletions src/fheroes2/system/settings.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2019 - 2024 *
* Copyright (C) 2019 - 2025 *
* *
* Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 *
* Copyright (C) 2009 by Andrey Afletdinov <[email protected]> *
Expand Down Expand Up @@ -36,6 +36,7 @@
#include "game.h"
#include "game_io.h"
#include "logging.h"
#include "race.h"
#include "render_processor.h"
#include "save_format_version.h"
#include "screen.h"
Expand Down Expand Up @@ -235,8 +236,17 @@ bool Settings::Read( const std::string & filePath )
setBattleShowTurnOrder( config.StrParams( "battle turn order" ) == "on" );
}

if ( config.Exists( "use evil interface" ) ) {
setEvilInterface( config.StrParams( "use evil interface" ) == "on" );
if ( config.Exists( "interface type" ) ) {
const std::string interfaceType = config.StrParams( "interface type" );
if ( interfaceType == "Good" ) {
setInterfaceType( InterfaceType::GOOD );
}
else if ( interfaceType == "Evil" ) {
setInterfaceType( InterfaceType::EVIL );
}
else {
setInterfaceType( InterfaceType::DYNAMIC );
}
Districh-ru marked this conversation as resolved.
Show resolved Hide resolved
}

if ( config.Exists( "hide interface" ) ) {
Expand Down Expand Up @@ -432,8 +442,20 @@ std::string Settings::String() const
os << std::endl << "# show turn order during battle: on/off" << std::endl;
os << "battle turn order = " << ( _gameOptions.Modes( GAME_BATTLE_SHOW_TURN_ORDER ) ? "on" : "off" ) << std::endl;

os << std::endl << "# use evil interface style: on/off" << std::endl;
os << "use evil interface = " << ( _gameOptions.Modes( GAME_EVIL_INTERFACE ) ? "on" : "off" ) << std::endl;
os << std::endl << "# interface type (Good/Evil/Dynamic)" << std::endl;
switch ( _interfaceType ) {
case GOOD:
os << "interface type = Good" << std::endl;
break;
case EVIL:
os << "interface type = Evil" << std::endl;
break;
case DYNAMIC:
os << "interface type = Dynamic" << std::endl;
break;
default:
assert( 0 );
}

os << std::endl << "# hide interface elements on the adventure map: on/off" << std::endl;
os << "hide interface = " << ( _gameOptions.Modes( GAME_HIDE_INTERFACE ) ? "on" : "off" ) << std::endl;
Expand Down Expand Up @@ -816,16 +838,6 @@ void Settings::setHideInterface( const bool enable )
}
}

void Settings::setEvilInterface( const bool enable )
{
if ( enable ) {
_gameOptions.SetModes( GAME_EVIL_INTERFACE );
}
else {
_gameOptions.ResetModes( GAME_EVIL_INTERFACE );
}
}

void Settings::setScreenScalingTypeNearest( const bool enable )
{
if ( enable ) {
Expand Down Expand Up @@ -883,9 +895,46 @@ bool Settings::isHideInterfaceEnabled() const
return _gameOptions.Modes( GAME_HIDE_INTERFACE );
}

void Settings::setInterfaceType( InterfaceType type )
{
assert( type >= InterfaceType::GOOD && type <= InterfaceType::DYNAMIC );
_interfaceType = type;
}

InterfaceType Settings::getInterfaceType() const
{
return _interfaceType;
}

bool Settings::isEvilInterfaceEnabled() const
{
return _gameOptions.Modes( GAME_EVIL_INTERFACE );
switch ( _interfaceType ) {
case InterfaceType::GOOD:
return false;
case InterfaceType::EVIL:
return true;
case InterfaceType::DYNAMIC: {
Player * player = Settings::Get().GetPlayers().GetCurrent();
if ( !player )
return false;

if ( player->isControlHuman() ) {
const int race = player->GetRace();
return race == Race::WRLK || race == Race::NECR || race == Race::BARB;
felix642 marked this conversation as resolved.
Show resolved Hide resolved
}

// Keep the UI of the last player during the AI turn
for ( auto iter = Settings::Get().GetPlayers().rbegin(); iter < Settings::Get().GetPlayers().rend(); ++iter ) {
if ( *iter && ( *iter )->isControlHuman() ) {
const int race = ( *iter )->GetRace();
return race == Race::WRLK || race == Race::NECR || race == Race::BARB;
}
}
return false;
}
default:
assert( 0 );
}
}

bool Settings::isEditorAnimationEnabled() const
Expand Down
12 changes: 11 additions & 1 deletion src/fheroes2/system/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ enum class ZoomLevel : uint8_t
ZoomLevel3 = 3, // Max zoom, but should only exists for debug builds
};

enum InterfaceType : uint8_t
{
GOOD = 0,
EVIL = 1,
DYNAMIC = 2,
};

class Settings
{
public:
Expand Down Expand Up @@ -191,6 +198,9 @@ class Settings
bool isHideInterfaceEnabled() const;
bool isEvilInterfaceEnabled() const;

void setInterfaceType( InterfaceType type );
InterfaceType getInterfaceType() const;

bool isEditorAnimationEnabled() const;
bool isEditorPassabilityEnabled() const;

Expand Down Expand Up @@ -252,7 +262,6 @@ class Settings
void setAutoSaveAtBeginningOfTurn( const bool enable );
void setBattleDamageInfo( const bool enable );
void setHideInterface( const bool enable );
void setEvilInterface( const bool enable );
void setScreenScalingTypeNearest( const bool enable );

void SetSoundVolume( int v );
Expand Down Expand Up @@ -379,6 +388,7 @@ class Settings
int ai_speed;
int scroll_speed;
int battle_speed;
InterfaceType _interfaceType;

int game_type;
ZoomLevel _viewWorldZoomLevel{ ZoomLevel::ZoomLevel1 };
Expand Down
Loading