Skip to content

Add support for campaign status - #1681

Draft
kubaau wants to merge 9 commits into
Return-To-The-Roots:masterfrom
kubaau:campaign_status
Draft

kubaau wants to merge 9 commits into
Return-To-The-Roots:masterfrom
kubaau:campaign_status

Conversation

@kubaau

@kubaau kubaau commented Jul 23, 2024

Copy link
Copy Markdown
Contributor

Adds support for Roman-style (video) campaigns and the world campaign (video).

Fixed world campaign scripts to unlock the same continents as it was in S2.

Related to issues #1639 and #1177

@Spikeone

Copy link
Copy Markdown
Member

Either I'm blind or the implementation is somewhere else? What is rttr:SetCampaignChapterCompleted good for?

@kubaau

kubaau commented Jul 26, 2024 •

Copy link
Copy Markdown
Contributor Author

Either I'm blind or the implementation is somewhere else? What is rttr:SetCampaignChapterCompleted good for?

It doesn't make a difference in Roman-style campaigns, but it marks a continent as conquered in the world campaign. It could also be used for other campaign types as well if we wanted to show what was completed, especially if someone designs a campaign whose progression is not linear.

Edit: For roman-style campaigns it shows the "You have successfully completed chapter X." screen after ending the game.

Comment thread libs/s25main/lua/LuaInterfaceGame.cpp Outdated

@Flamefire Flamefire left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Awesome, the last bit for campaigns! Review inline.

General hint: Try to make best use of the type system. E.g. "unsigned char" is/should be a (text-)character (although only since C++11 introduced uint8_t) And using this narrow width number-type as parameters likely introduces overhead (registers are wider so often need to be masked) so it is even faster to just use unsigned there.
Similar for string which should be text. It can be stored in the config as a string for brevity but converted during load/save to a more appropriate type, especially when (scoped) enums can be used.

In general I like the changes, thanks! :)

Comment thread libs/libGamedata/gameData/CampaignSaveCodes.h Outdated
Comment thread libs/libGamedata/gameData/CampaignDescription.h Outdated
Comment thread libs/s25main/CampaignSaveData.cpp Outdated
Comment thread libs/s25main/CampaignSaveData.h Outdated
Comment thread libs/s25main/CampaignSaveData.cpp Outdated

BOOST_FIXTURE_TEST_CASE(Chapters0and1AreEnabledByDefault, CampaignSaveDataFixture)
{
saveData[uid] = CampaignSaveCodes::defaultChaptersEnabled;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So the default is to enable the first 2 chapters? Why that? Wouldn't (only) the first one be a more sensible default?
I'm also a bit confused as you seem to be using indices and 1-based values for chapters

Maybe stick to indices and use an optional instead of zero

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

In the original S2, I also had first 2 missions unlocked at start. Maybe because 1st one is actually a tutorial without AI opponent?

Just rechecked with GOG S2 Gold Edition.
obraz

Comment thread tests/s25Main/campaign/testCampaignSaveData.cpp Outdated
Comment thread tests/s25Main/campaign/testCampaignSaveData.cpp Outdated
Comment thread tests/s25Main/lua/testLua.cpp Outdated
Comment thread libs/libGamedata/gameData/CampaignDescription.cpp Outdated
@kubaau
kubaau marked this pull request as draft December 25, 2024 21:11
@kubaau

kubaau commented Dec 25, 2024

Copy link
Copy Markdown
Contributor Author

Rework in progress - converting to draft, will notify when ready for review. Resolving some conversations since they will not be relevant.

jarvis-jhk added a commit to jarvis-jhk/s25coop that referenced this pull request Sep 28, 2026
… fix it (M1)

Merged kubaau's campaign_status branch (upstream PR Return-To-The-Roots#1681) and fixed what
the upstream review and our own tests found:
- world mission scripts completed/enabled 1-based chapters (winning Europe
  marked Africa conquered); luaFolder back to "" (upper case breaks Linux)
- a CONFIG.INI without [campaigns] was thrown away and replaced by defaults
- save string padded with NUL bytes instead of '0'
- onHumanWinner fired for the wrong winner (IsWinnerHuman team-mask bug);
  now fires for the announced winner only, also without a GUI
- victory screen showed "chapter 0", and a pending one leaked into the
  next game; progress is saved as soon as the game is left
- default chapters stay playable after scripts changed other chapters

Tested: unit tests (settings roundtrip, old config, save format, every
shipped mission completes its own chapter, CheckObjective winner cases)
and local ctest CoopCampaign_* that finishes all 19 official missions
headless and checks the recorded progress. Reviewed by Codex (GPT-6 Sol):
winner attribution fixed; one finding rejected (MISS209 does not enable a
chapter 10).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jarvis-jhk

Copy link
Copy Markdown
Contributor

Thanks for this PR — we merged it into our fork (jarvis-jhk/s25coop, a coop-campaign fork) and found a few things while testing it; feel free to take any of it: jarvis-jhk@07bf3205a

  • The world mission scripts use 1-based chapter ids while chaptersEnabled / isChapterPlayable use map indices, so winning Europe marks Africa as conquered. Converted the scripts to 0-based.
  • luaFolder = "<RTTR_RTTR>/CAMPAIGNS/WORLD" breaks on case-sensitive file systems (the folder is campaigns/world); reverted to "".
  • A CONFIG.INI without a [campaigns] section (every existing install) failed Load() and was replaced by the defaults (also the settings.size() < SECTION_NAMES.size() check). Made the section optional.
  • toSaveString resizes with '\0', so untouched chapters between two known ones are written as NUL bytes. Now padded with '0'.
  • IsWinnerHuman indexes players by bestTeam & (1 << i) (Flamefire's comment); it now checks the winner actually announced (team or single player).
  • The victory screen shows the 0-based index ("chapter 0"); the pending state is reset in Game::Start, and settings are saved in ShowMenu when progress changed.

Tests we added: settings roundtrip/old config/save format, a check that every shipped mission script completes its own chapter index, and CheckObjective winner cases in testLua.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants