Skip to content

Fix event random numbers never stored in setRandomNumbers() - #1217

Open
acato wants to merge 1 commit into
We-the-People-civ4col-mod:developfrom
acato:fix/event-random-numbers-not-stored
Open

Fix event random numbers never stored in setRandomNumbers()#1217
acato wants to merge 1 commit into
We-the-People-civ4col-mod:developfrom
acato:fix/event-random-numbers-not-stored

Conversation

@acato

@acato acato commented Mar 27, 2026

Copy link
Copy Markdown
Contributor

Summary

  • EventTriggeredData::setRandomNumbers() creates a RandomContainer for each event, generates a random number, but never calls m_RandomNumbers.push_back(container) — the vector stays empty
  • This causes getRandomNumber() and getRandomNumberForIndex() to always return 0 (the fallback default)
  • All probability checks using these functions become no-ops (e.g., canTriggerVolcanoDormant1 fires 100% instead of ~25%)

Details

The bug affects two code paths:

  1. Python callbacks using getRandomNumberForIndex() — e.g., the volcano dormant event always triggers because 0 < 250 is always true
  2. DLL-side TriggerChance fastpath in CvPlayer::canDoEvent() which uses getRandomNumber(eEvent) — always returns 0, bypassing probability gates

The fix is a single missing push_back call.

Test plan

  • Start a game with a volcano on the map; verify the dormant event doesn't fire every single time
  • Verify events using TriggerChance fire at their intended probability rather than always/never

Related: #1205

🤖 Generated with Claude Code

EventTriggeredData::setRandomNumbers() creates a RandomContainer for
each event in the trigger, generates a random number via getSorenRandNum,
but never actually stores the container in m_RandomNumbers. The
push_back call was missing, so m_RandomNumbers remained empty after
the function completed.

This caused getRandomNumber() and getRandomNumberForIndex() to always
return 0 (the fallback default), which had two consequences:

1. Any Python PythonCanDo callback using getRandomNumberForIndex()
   for probability checks would always see 0. For example,
   canTriggerVolcanoDormant1() checks "getRandomNumberForIndex(0) < 250"
   which was always true (0 < 250), making the volcano dormant event
   fire 100% of the time instead of the intended ~25%.

2. The DLL-side TriggerChance fastpath in CvPlayer::canDoEvent()
   (line 14762) uses getRandomNumber(eEvent) to check event probability
   thresholds. With the vector always empty, this also always returned 0,
   bypassing intended probability gates for events validated through
   that code path.

The fix adds the missing m_RandomNumbers.push_back(container) so that
generated random numbers are actually persisted in the vector and
available to both Python and C++ callers.

Related: We-the-People-civ4col-mod#1205 (CvRandomInterfaceEvent tuple index out of range)
The primary cause of We-the-People-civ4col-mod#1205 was an argsList index mismatch fixed in
38b7518, but this bug compounded the issue by making the random
number check in canTriggerVolcanoDormant1 a no-op.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@devolution79

Copy link
Copy Markdown
Member

@Nightinggale could you have a look at this ?

@Schmiddie1979

Copy link
Copy Markdown
Collaborator

I assume we should do this fix. It could have influence on the existing events, but I have checked if there are any events which use probabilities via

  1. TriggerChance(argsList)
  2. canTriggerVolcanoDormant1
  3. getRandomNumber()

but I could not find any or only the volcano event and very few that still use TriggerChance. Hence the effect should be limited. We need to monitor if any events have unintended issues after the fix.

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.

3 participants