Skip to content

Commit

Permalink
Hotfix for crash issue:
Browse files Browse the repository at this point in the history
When combat is broken by dialog (originating in san_enter_combat, specifically), it could trigger a start combat / end combat inifinite loop, resulting in stack overflow. Added "forceEndedCombatNow" flag to handle this
  • Loading branch information
Lei Chabolan committed Sep 17, 2022
1 parent 762bd8b commit bdf0e9f
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 2 deletions.
7 changes: 7 additions & 0 deletions TemplePlus/combat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,13 @@ BOOL LegacyCombatSystem::StartCombat(objHndl combatInitiator, int setToFirstInit

if (AllPcsUnconscious())
return FALSE;

if (forceEndedCombatNow) { // temple+: added this vs. combat start/end loops
logger->debug("StartCombat: averted due to forceEndedCombatNow = true");
return FALSE;
}


logger->debug("StartCombat: entering combat mode; initiated by {}", combatInitiator);

*combatAddresses.combatRoundCount = 0;
Expand Down
1 change: 1 addition & 0 deletions TemplePlus/combat.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ struct LegacyCombatSystem : temple::AddressTable {


uint32_t* combatModeActive;
bool forceEndedCombatNow; // to prevent loops where combat is entered and exited at the same time event
bool isCombatActive();
bool IsAutoAttack();
bool AllCombatantsFarFromParty();
Expand Down
2 changes: 1 addition & 1 deletion TemplePlus/gamesystems/timeevents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1067,7 +1067,7 @@ void TimeEventSystem::AdvanceTime(uint32_t newTimeMs) {

}
}

combatSys.forceEndedCombatNow = false; // reset this

if (!timeAdvanceBlockerCount || uiSystems->GetDlg().IsActive()) {

Expand Down
3 changes: 2 additions & 1 deletion TemplePlus/python/python_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,10 @@ static PyObject* PyObjHandle_BeginDialog(PyObject* obj, PyObject* args) {
uiPicker.CancelPicker();

// Temple+: added this, otherwise the combat continues briefly and goes on to the next combatant who can start an action
// the dialog event callback does this anyway, but 1ms later
// the dialog event callback (0x1014CED0) does this anyway, but 1ms later
auto leader = party.GetConsciousPartyLeader();
if (leader) {
combatSys.forceEndedCombatNow = true;
combatSys.CritterExitCombatMode(leader);
}

Expand Down

0 comments on commit bdf0e9f

Please sign in to comment.