Skip to content

Commit

Permalink
Add betrayal scenario support for original campaign (#4968)
Browse files Browse the repository at this point in the history
  • Loading branch information
ihhub authored Feb 7, 2022
1 parent 3dae29e commit 5e7e4ef
Show file tree
Hide file tree
Showing 12 changed files with 653 additions and 337 deletions.
372 changes: 219 additions & 153 deletions src/fheroes2/campaign/campaign_data.cpp

Large diffs are not rendered by default.

13 changes: 7 additions & 6 deletions src/fheroes2/campaign/campaign_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,24 @@ namespace Campaign
return _scenarios;
}

const std::vector<int> & getScenariosAfter( const int scenarioID ) const;
std::vector<int> getStartingScenarios() const;
static const std::vector<ScenarioInfoId> & getScenariosAfter( const ScenarioInfoId & scenarioInfo );
std::vector<ScenarioInfoId> getStartingScenarios() const;

bool isAllCampaignMapsPresent() const;
bool isLastScenario( const int scenarioID ) const;
bool isStartingScenario( const int scenarioID ) const;
bool isLastScenario( const Campaign::ScenarioInfoId & scenarioInfoId ) const;

void setCampaignID( const int campaignID );
void setCampaignDescription( const std::string & campaignDescription );
void setCampaignScenarios( const std::vector<ScenarioData> & scenarios );
void setCampaignScenarios( std::vector<ScenarioData> && scenarios );

static const CampaignData & getCampaignData( const int campaignID );

private:
int _campaignID;
std::string _campaignDescription;
std::vector<ScenarioData> _scenarios;

bool isStartingScenario( const ScenarioInfoId & scenarioInfo ) const;
};

struct CampaignAwardData
Expand Down Expand Up @@ -91,7 +92,7 @@ namespace Campaign

std::string ToString() const;

static std::vector<Campaign::CampaignAwardData> getCampaignAwardData( const int campaignID, const int scenarioID );
static std::vector<Campaign::CampaignAwardData> getCampaignAwardData( const ScenarioInfoId & scenarioInfo );
static std::vector<Campaign::CampaignAwardData> getExtraCampaignAwardData( const int campaignID );

static const char * getAllianceJoiningMessage( const int monsterId );
Expand Down
56 changes: 35 additions & 21 deletions src/fheroes2/campaign/campaign_savedata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,19 @@
#include "campaign_savedata.h"
#include "army.h"
#include "campaign_data.h"
#include "save_format_version.h"
#include "serialize.h"
#include <algorithm>
#include <cassert>

namespace Campaign
{
CampaignSaveData::CampaignSaveData()
: _currentScenarioID( 0 )
, _campaignID( 0 )
: _currentScenarioInfoId( -1, -1 )
, _daysPassed( 0 )
{}
{
// Do nothing.
}

CampaignSaveData & Campaign::CampaignSaveData::Get()
{
Expand All @@ -54,21 +56,17 @@ namespace Campaign
_currentScenarioBonus = bonus;
}

void CampaignSaveData::setCurrentScenarioID( const int scenarioID )
void CampaignSaveData::setCurrentScenarioInfoId( const ScenarioInfoId & scenarioInfoId )
{
_currentScenarioID = scenarioID;
}

void CampaignSaveData::setCampaignID( const int campaignID )
{
_campaignID = campaignID;
assert( scenarioInfoId.campaignId >= 0 && scenarioInfoId.scenarioId >= 0 );
_currentScenarioInfoId = scenarioInfoId;
}

void CampaignSaveData::addCurrentMapToFinished()
{
const bool isNotDuplicate = std::find( _finishedMaps.begin(), _finishedMaps.end(), _currentScenarioID ) == _finishedMaps.end();
const bool isNotDuplicate = std::find( _finishedMaps.begin(), _finishedMaps.end(), _currentScenarioInfoId ) == _finishedMaps.end();
if ( isNotDuplicate )
_finishedMaps.emplace_back( _currentScenarioID );
_finishedMaps.emplace_back( _currentScenarioInfoId );
}

void CampaignSaveData::addDaysPassed( const uint32_t days )
Expand All @@ -81,8 +79,7 @@ namespace Campaign
_finishedMaps.clear();
_obtainedCampaignAwards.clear();
_carryOverTroops.clear();
_currentScenarioID = 0;
_campaignID = 0;
_currentScenarioInfoId = { -1, -1 };
_daysPassed = 0;
}

Expand All @@ -95,7 +92,7 @@ namespace Campaign
}
}

int CampaignSaveData::getLastCompletedScenarioID() const
const ScenarioInfoId & CampaignSaveData::getLastCompletedScenarioInfoID() const
{
assert( !_finishedMaps.empty() );
return _finishedMaps.back();
Expand All @@ -106,15 +103,15 @@ namespace Campaign
std::vector<Campaign::CampaignAwardData> obtainedAwards;

for ( size_t i = 0; i < _finishedMaps.size(); ++i ) {
const std::vector<Campaign::CampaignAwardData> awards = Campaign::CampaignAwardData::getCampaignAwardData( _campaignID, _finishedMaps[i] );
const std::vector<Campaign::CampaignAwardData> awards = Campaign::CampaignAwardData::getCampaignAwardData( _finishedMaps[i] );

for ( size_t j = 0; j < awards.size(); ++j ) {
if ( std::find( _obtainedCampaignAwards.begin(), _obtainedCampaignAwards.end(), awards[j]._id ) != _obtainedCampaignAwards.end() )
obtainedAwards.emplace_back( awards[j] );
}
}

const std::vector<Campaign::CampaignAwardData> extraAwards = Campaign::CampaignAwardData::getExtraCampaignAwardData( _campaignID );
const std::vector<Campaign::CampaignAwardData> extraAwards = Campaign::CampaignAwardData::getExtraCampaignAwardData( _currentScenarioInfoId.campaignId );
for ( const Campaign::CampaignAwardData & award : extraAwards ) {
if ( std::find( _obtainedCampaignAwards.begin(), _obtainedCampaignAwards.end(), award._id ) != _obtainedCampaignAwards.end() )
obtainedAwards.emplace_back( award );
Expand All @@ -125,14 +122,31 @@ namespace Campaign

StreamBase & operator<<( StreamBase & msg, const CampaignSaveData & data )
{
return msg << data._currentScenarioID << data._currentScenarioBonus << data._finishedMaps << data._campaignID << data._daysPassed << data._obtainedCampaignAwards
<< data._carryOverTroops;
return msg << data._currentScenarioInfoId.campaignId << data._currentScenarioInfoId.scenarioId << data._currentScenarioBonus << data._finishedMaps
<< data._daysPassed << data._obtainedCampaignAwards << data._carryOverTroops;
}

StreamBase & operator>>( StreamBase & msg, CampaignSaveData & data )
{
return msg >> data._currentScenarioID >> data._currentScenarioBonus >> data._finishedMaps >> data._campaignID >> data._daysPassed >> data._obtainedCampaignAwards
>> data._carryOverTroops;
return msg >> data._currentScenarioInfoId.campaignId >> data._currentScenarioInfoId.scenarioId >> data._currentScenarioBonus >> data._finishedMaps
>> data._daysPassed >> data._obtainedCampaignAwards >> data._carryOverTroops;
}

void CampaignSaveData::loadOldSaveSata( StreamBase & msg, CampaignSaveData & data )
{
static_assert( LAST_SUPPORTED_FORMAT_VERSION < FORMAT_VERSION_0912_RELEASE, "Remove this method." );

msg >> data._currentScenarioInfoId.scenarioId >> data._currentScenarioBonus;

std::vector<int> finishedMaps;
msg >> finishedMaps;

msg >> data._currentScenarioInfoId.campaignId >> data._daysPassed >> data._obtainedCampaignAwards >> data._carryOverTroops;

data._finishedMaps.clear();
for ( const int mapId : finishedMaps ) {
data._finishedMaps.emplace_back( data._currentScenarioInfoId.campaignId, mapId );
}
}

ScenarioVictoryCondition getCurrentScenarioVictoryCondition()
Expand Down
30 changes: 21 additions & 9 deletions src/fheroes2/campaign/campaign_savedata.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,28 @@ namespace Campaign
public:
CampaignSaveData();

const std::vector<int> & getFinishedMaps() const
const std::vector<ScenarioInfoId> & getFinishedMaps() const
{
return _finishedMaps;
}

int getCampaignID() const
{
return _campaignID;
return _currentScenarioInfoId.campaignId;
}

int getCurrentScenarioID() const
{
return _currentScenarioID;
return _currentScenarioInfoId.scenarioId;
}

const ScenarioInfoId & getCurrentScenarioInfoId() const
{
return _currentScenarioInfoId;
}

// Make sure that this is not the first scenario in the campaign. Please call isStarting to verify this.
int getLastCompletedScenarioID() const;
const ScenarioInfoId & getLastCompletedScenarioInfoID() const;

bool isStarting() const
{
Expand All @@ -71,26 +76,33 @@ namespace Campaign
std::vector<Campaign::CampaignAwardData> getObtainedCampaignAwards() const;

void setCurrentScenarioBonus( const ScenarioBonusData & bonus );
void setCurrentScenarioID( const int scenarioID );
void setCampaignID( const int campaignID );
void setCurrentScenarioInfoId( const ScenarioInfoId & scenarioInfoId );
void addCurrentMapToFinished();
void addCampaignAward( const int awardID );
void setCarryOverTroops( const Troops & troops );
void reset();
void addDaysPassed( const uint32_t days );
void removeCampaignAward( const int awardID );

void removeAllAwards()
{
_obtainedCampaignAwards.clear();
}

static CampaignSaveData & Get();

static void loadOldSaveSata( StreamBase & msg, CampaignSaveData & data );

private:
friend StreamBase & operator<<( StreamBase & msg, const CampaignSaveData & data );
friend StreamBase & operator>>( StreamBase & msg, CampaignSaveData & data );

std::vector<int> _finishedMaps;
std::vector<ScenarioInfoId> _finishedMaps;
std::vector<int> _obtainedCampaignAwards;
std::vector<Troop> _carryOverTroops;
int _currentScenarioID;
int _campaignID;

ScenarioInfoId _currentScenarioInfoId;

uint32_t _daysPassed;
ScenarioBonusData _currentScenarioBonus;
};
Expand Down
46 changes: 33 additions & 13 deletions src/fheroes2/campaign/campaign_scenariodata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ namespace
bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::HIDEOUS_MASK, 1 );
bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::FIZBIN_MISFORTUNE, 1 );
break;
case 10:
bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::NECR, 1 );
bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::WRLK, 1 );
bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::BARB, 1 );
break;
default:
assert( 0 );
break;
Expand Down Expand Up @@ -140,6 +145,11 @@ namespace
bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::HIDEOUS_MASK, 1 );
bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::FIZBIN_MISFORTUNE, 1 );
break;
case 11:
bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::WZRD, 1 );
bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::SORC, 1 );
bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::KNGT, 1 );
break;
default:
assert( 0 );
break;
Expand Down Expand Up @@ -396,6 +406,16 @@ namespace

namespace Campaign
{
StreamBase & operator<<( StreamBase & msg, const ScenarioInfoId & data )
{
return msg << data.campaignId << data.scenarioId;
}

StreamBase & operator>>( StreamBase & msg, ScenarioInfoId & data )
{
return msg >> data.campaignId >> data.scenarioId;
}

ScenarioBonusData::ScenarioBonusData()
: _type( 0 )
, _subType( 0 )
Expand Down Expand Up @@ -446,22 +466,22 @@ namespace Campaign
return useAmount ? std::to_string( _amount ) + " " + objectName : objectName;
}

std::vector<ScenarioBonusData> ScenarioBonusData::getCampaignBonusData( const int campaignID, const int scenarioID )
std::vector<ScenarioBonusData> ScenarioBonusData::getCampaignBonusData( const ScenarioInfoId & scenarioInfo )
{
assert( scenarioID >= 0 );
switch ( campaignID ) {
assert( scenarioInfo.scenarioId >= 0 );
switch ( scenarioInfo.campaignId ) {
case Campaign::ROLAND_CAMPAIGN:
return getRolandCampaignBonusData( scenarioID );
return getRolandCampaignBonusData( scenarioInfo.scenarioId );
case Campaign::ARCHIBALD_CAMPAIGN:
return getArchibaldCampaignBonusData( scenarioID );
return getArchibaldCampaignBonusData( scenarioInfo.scenarioId );
case Campaign::PRICE_OF_LOYALTY_CAMPAIGN:
return getPriceOfLoyaltyCampaignBonusData( scenarioID );
return getPriceOfLoyaltyCampaignBonusData( scenarioInfo.scenarioId );
case Campaign::VOYAGE_HOME_CAMPAIGN:
return getVoyageHomeCampaignBonusData( scenarioID );
return getVoyageHomeCampaignBonusData( scenarioInfo.scenarioId );
case Campaign::WIZARDS_ISLE_CAMPAIGN:
return getWizardsIsleCampaignBonusData( scenarioID );
return getWizardsIsleCampaignBonusData( scenarioInfo.scenarioId );
case Campaign::DESCENDANTS_CAMPAIGN:
return getDescendantsCampaignBonusData( scenarioID );
return getDescendantsCampaignBonusData( scenarioInfo.scenarioId );
default:
// Did you add a new campaign? Add the corresponding case above.
assert( 0 );
Expand All @@ -482,13 +502,13 @@ namespace Campaign
return msg >> data._type >> data._subType >> data._amount;
}

ScenarioData::ScenarioData( int scenarioID, const std::vector<int> & nextMaps, const std::vector<ScenarioBonusData> & bonuses, const std::string & fileName,
ScenarioData::ScenarioData( const ScenarioInfoId & scenarioInfo, std::vector<ScenarioInfoId> && nextScenarios, const std::string & fileName,
const std::string & scenarioName, const std::string & description, const VideoSequence & startScenarioVideoPlayback,
const VideoSequence & endScenarioVideoPlayback, const ScenarioVictoryCondition victoryCondition,
const ScenarioLossCondition lossCondition )
: _scenarioID( scenarioID )
, _nextMaps( nextMaps )
, _bonuses( bonuses )
: _scenarioInfo( scenarioInfo )
, _nextScenarios( std::move( nextScenarios ) )
, _bonuses( ScenarioBonusData::getCampaignBonusData( scenarioInfo ) )
, _fileName( StringLower( fileName ) )
, _scenarioName( scenarioName )
, _description( description )
Expand Down
Loading

0 comments on commit 5e7e4ef

Please sign in to comment.