Skip to content

Commit

Permalink
Custom scenario fixes (#11368)
Browse files Browse the repository at this point in the history
* Fix crash in CvHandicapInfo::getYieldAmountForDifficultyBonus with uninitialized era

When calculating difficulty bonuses during city initialization, getCurrentEra() can return -1 (NO_ERA)
if no teams have been initialized yet. Add validation to use era 0 (Ancient) as fallback to prevent crash.

* Fix crash in CvGame::initSpyThreshold()

Added safety checks for divide-by-zero and debug logging. The crash was caused by
unprotected division in spy threshold calculation. Modified to ensure minimum
values for number of civs and added MOD_CORE_DEBUGGING output to track
configuration values.

* Change MOD_COMMUNITY_PATCH check

MOD_COMMUNITY_PATCH should always be true

* remove MOD_CORE_DEBUGGING
  • Loading branch information
JohnsterID authored Nov 24, 2024
1 parent f450e1a commit 5efd943
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 3 deletions.
37 changes: 34 additions & 3 deletions CvGameCoreDLL_Expansion2/CvGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10772,14 +10772,45 @@ int CvGame::GetCultureMedian() const
return m_iCultureMedian;
}


void CvGame::initSpyThreshold()
{
// MOD_COMMUNITY_PATCH should always be true
ASSERT(MOD_COMMUNITY_PATCH);

// Early return if spy balance module is not active
if (!MOD_BALANCE_CORE_SPIES)
return;

int iThreshold = 100 * /* 20 */ GD_INT_GET(BALANCE_SPY_TO_PLAYER_RATIO) / (GetNumMinorCivsEver(true) + /* 2 */ GD_INT_GET(BALANCE_SPY_POINT_MAJOR_PLAYER_MULTIPLIER) * GetNumMajorCivsEver(true));
m_iSpyThreshold = range(iThreshold, /* 33 */ GD_INT_GET(BALANCE_SPY_POINT_THRESHOLD_MIN), /* 100 */ GD_INT_GET(BALANCE_SPY_POINT_THRESHOLD_MAX));
// Get the values with safety checks
int iNumMinors = max(1, GetNumMinorCivsEver(true)); // Ensure we don't divide by zero
int iNumMajors = max(1, GetNumMajorCivsEver(true)); // Ensure we don't divide by zero

// Get configuration values:
// BALANCE_SPY_TO_PLAYER_RATIO = 20
// BALANCE_SPY_POINT_MAJOR_PLAYER_MULTIPLIER = 2
// BALANCE_SPY_POINT_THRESHOLD_MIN = 33
// BALANCE_SPY_POINT_THRESHOLD_MAX = 100
int iSpyRatio = GD_INT_GET(BALANCE_SPY_TO_PLAYER_RATIO);
int iMajorMultiplier = GD_INT_GET(BALANCE_SPY_POINT_MAJOR_PLAYER_MULTIPLIER);
int iMinThreshold = GD_INT_GET(BALANCE_SPY_POINT_THRESHOLD_MIN);
int iMaxThreshold = GD_INT_GET(BALANCE_SPY_POINT_THRESHOLD_MAX);

#if defined(VPDEBUG)
CUSTOMLOG("Spy Threshold Config: Ratio=%d, MajorMult=%d, Min=%d, Max=%d",
iSpyRatio, iMajorMultiplier, iMinThreshold, iMaxThreshold);
CUSTOMLOG("Spy Threshold Civs: Minors=%d, Majors=%d", iNumMinors, iNumMajors);
#endif

// Calculate threshold using the formula:
// threshold = (100 * 20) / (numMinors + 2 * numMajors)
int iThreshold = 100 * iSpyRatio / (iNumMinors + iMajorMultiplier * iNumMajors);

// Clamp the result between 33 and 100
m_iSpyThreshold = range(iThreshold, iMinThreshold, iMaxThreshold);

#if defined(VPDEBUG)
CUSTOMLOG("Spy Threshold Result: %d", m_iSpyThreshold);
#endif
}

int CvGame::GetSpyThreshold() const
Expand Down
3 changes: 3 additions & 0 deletions CvGameCoreDLL_Expansion2/CvPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18123,6 +18123,9 @@ void CvPlayer::DoDifficultyBonus(HistoricEventTypes eHistoricEvent)
int iDifficultyBonusPercent = GC.getGame().getGameSpeedInfo().getDifficultyBonusPercent();
int iEra = GC.getGame().getCurrentEra();

if (iEra < 0)
iEra = 0; // Use as fallback when game era is not yet set

// First do the human difficulty bonus
CvHandicapInfo* pHandicapInfo = GC.getHandicapInfo(getHandicapType());
if (pHandicapInfo)
Expand Down

0 comments on commit 5efd943

Please sign in to comment.