Skip to content

Commit 3a9e778

Browse files
committed
fix: set GlobalOther=hero before ZS_* loops and dialog condition evaluation
After commit 69d7707 correctly fixed the GlobalOther save/restore in ExecutePerception, a stale NPC (e.g. a Shadow guard from a recent perception) remained in GlobalOther between perception calls. This caused two visible bugs: 1. NPCs turned their backs during conversation - routine states like ZS_*_Loop called B_AssessTalk/B_SmartTurnToNpc using 'other', which pointed to the stale Shadow instead of the player. NPCs would physically rotate toward that guard. 2. Important dialogs refused to trigger - conditions like Npc_GetDistToNpc(self,other) or guild attitude checks ran against the Shadow's position/guild, not the hero's, causing them to return false and skip the dialog entirely. Fix in AiHandler: set GlobalOther=GlobalHero before executing ZS_* state functions. This is just a sensible default - perception calls override GlobalOther via their own save/restore, so combat/assess perceptions are unaffected. Fix in DialogService: save/restore GlobalOther and explicitly set it to GlobalHero around Info_*_Condition calls. In Gothic's convention, self=NPC and other=hero in all dialog condition functions.
1 parent b69faf3 commit 3a9e778

2 files changed

Lines changed: 9 additions & 0 deletions

File tree

Assets/Gothic-Core/Scripts/Adapters/Npc/AiHandler.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,12 @@ private void Update()
7979
if (Properties.AnimationQueue.Count == 0)
8080
{
8181
// We always need to set "self" before executing any Daedalus function.
82+
// "other" defaults to hero here so routine states (ZS_*_Loop) have a sensible fallback.
83+
// Perception calls (ExecutePerception) override GlobalOther themselves with their own save/restore.
8284
if (NpcInstance != null)
8385
{
8486
Vm.GlobalSelf = NpcInstance;
87+
Vm.GlobalOther = Vm.GlobalHero;
8588
}
8689

8790
DaedalusSymbol loopSymbol;

Assets/Gothic-Core/Scripts/Services/Player/DialogService.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,12 @@ public void StartDialog(NpcContainer npcContainer, bool initialDialogStarting)
9999

100100
// TODO - Should be outsourced to some VmManager.Call<int> function which sets and resets values.
101101
var oldSelf = _gameStateService.GothicVm.GlobalSelf;
102+
var oldOther = _gameStateService.GothicVm.GlobalOther;
102103
_gameStateService.GothicVm.GlobalSelf = npcContainer.Instance;
104+
_gameStateService.GothicVm.GlobalOther = _gameStateService.GothicVm.GlobalHero;
103105
var conditionResult = _gameStateService.GothicVm.Call<int>(dialog.Condition);
104106
_gameStateService.GothicVm.GlobalSelf = oldSelf;
107+
_gameStateService.GothicVm.GlobalOther = oldOther;
105108

106109
// Dialog condition is false
107110
if (conditionResult == 0)
@@ -146,9 +149,12 @@ private bool TryGetImportant(NpcContainer npcContainer, out InfoInstance item)
146149

147150
// TODO - Should be outsourced to some VmManager.Call<int> function which sets and resets values.
148151
var oldSelf = _gameStateService.GothicVm.GlobalSelf;
152+
var oldOther = _gameStateService.GothicVm.GlobalOther;
149153
_gameStateService.GothicVm.GlobalSelf = npcContainer.Instance;
154+
_gameStateService.GothicVm.GlobalOther = _gameStateService.GothicVm.GlobalHero;
150155
var conditionResult = _gameStateService.GothicVm.Call<int>(dialog.Condition);
151156
_gameStateService.GothicVm.GlobalSelf = oldSelf;
157+
_gameStateService.GothicVm.GlobalOther = oldOther;
152158

153159
if (conditionResult == 0)
154160
{

0 commit comments

Comments
 (0)