Skip to content

Commit cfa0251

Browse files
authored
Merge pull request #380 from Gothic-Unity-Project/fix/npc-ai-fixes
Fix/npc ai fixes
2 parents 3a71991 + 17f158b commit cfa0251

6 files changed

Lines changed: 44 additions & 12 deletions

File tree

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
using Gothic.Core.Extensions;
77
using Gothic.Core.Logging;
88
using Gothic.Core.Models.Vm;
9+
using FreePoint = Gothic.Core.Models.Vob.WayNet.FreePoint;
10+
using WayPoint = Gothic.Core.Models.Vob.WayNet.WayPoint;
911
using Gothic.Core.Services;
1012
using Gothic.Core.Services.Config;
1113
using Gothic.Core.Services.Npc;
@@ -316,6 +318,7 @@ public void ClearState(bool callEndFunction)
316318
Properties.AnimationQueue.Clear();
317319
Properties.CurrentAction = new None(new AnimationAction(), NpcData);
318320
Properties.CurrentLoopState = NpcProperties.LoopState.None; // i.e. call StartNextState() next frame
321+
Properties.BodyState = VmGothicEnums.BodyState.BsStand;
319322

320323
PrefabProps.AnimationSystem.StopAllAnimations();
321324
}
@@ -339,7 +342,11 @@ public void ReEnableNpc()
339342
{
340343
var wp = _wayNetService.GetWayNetPoint(currentRoutine.Waypoint);
341344
if (wp != null)
345+
{
342346
gameObject.transform.position = _npcService.GetFreeAreaAtSpawnPoint(wp.Position);
347+
Properties.CurrentFreePoint = wp as FreePoint;
348+
Properties.CurrentWayPoint = wp as WayPoint;
349+
}
343350
else
344351
Logger.LogWarning($"ReEnableNpc: waypoint '{currentRoutine.Waypoint}' not found for {gameObject.name} — NPC will re-enable at current position.", LogCat.Npc);
345352
}

Assets/Gothic-Core/Scripts/Domain/Npc/Actions/AnimationActions/AbstractWalkAnimationAction2.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,19 @@ protected virtual void StartWalk()
5959
{
6060
PhysicsService.EnablePhysicsForNpc(PrefabProps);
6161

62+
var walkMode = (VmGothicEnums.WalkMode)Vob.AiHuman.WalkMode;
63+
Props.BodyState = walkMode == VmGothicEnums.WalkMode.Walk
64+
? VmGothicEnums.BodyState.BsWalk
65+
: VmGothicEnums.BodyState.BsRun;
66+
6267
var animName = AnimationService.GetAnimationName(VmGothicEnums.AnimationType.Move, NpcContainer);
6368
PrefabProps.AnimationSystem.PlayAnimation(animName);
6469
}
6570

6671
protected virtual void StopWalk()
6772
{
6873
PhysicsService.EnablePhysicsForNpc(PrefabProps);
74+
Props.BodyState = VmGothicEnums.BodyState.BsStand;
6975

7076
var animName = AnimationService.GetAnimationName(VmGothicEnums.AnimationType.Move, NpcContainer);
7177
PrefabProps.AnimationSystem.StopAnimation(animName);

Assets/Gothic-Core/Scripts/Domain/Npc/Actions/AnimationActions/ContinueRoutine.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using Gothic.Core.Adapters.Npc;
2+
using Gothic.Core.Logging;
13
using Gothic.Core.Models.Container;
24

35
namespace Gothic.Core.Domain.Npc.Actions.AnimationActions
@@ -10,7 +12,14 @@ public ContinueRoutine(AnimationAction action, NpcContainer npcContainer) : base
1012

1113
public override void Start()
1214
{
13-
var ai = PrefabProps.AiHandler;
15+
var ai = PrefabProps.AiHandler ?? NpcGo.GetComponent<AiHandler>();
16+
17+
if (ai == null)
18+
{
19+
Logger.LogWarning($"[ContinueRoutine] AiHandler null on {NpcGo.name} — skipping routine restart", LogCat.Ai);
20+
IsFinishedFlag = true;
21+
return;
22+
}
1423

1524
ai.ClearState(false);
1625

Assets/Gothic-Core/Scripts/Domain/Npc/Actions/AnimationActions/UseMob.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public override void Start()
4949
_mobContainer = container;
5050
_mobsiScheme = _mobContainer?.Props.GetVisualScheme();
5151

52-
if (container!.Go == null)
52+
if (container == null || container.Go == null)
5353
{
5454
IsFinishedFlag = true;
5555
return;

Assets/Gothic-Core/Scripts/Services/Npc/NpcAiService.cs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,21 @@ public void ExtAiStartState(NpcInstance npc, int action, bool stopCurrentState,
207207
{
208208
var other = (NpcInstance)_gameStateService.GothicVm.GlobalOther;
209209
var victim = (NpcInstance)_gameStateService.GothicVm.GlobalOther;
210-
211-
npc.GetUserData().Props.AnimationQueue.Enqueue(new StartState(
210+
211+
var container = npc.GetUserData();
212+
213+
if (stopCurrentState)
214+
{
215+
// Abandon current state immediately so the new one starts next frame, not after the whole queue drains.
216+
container.PrefabProps?.AiHandler?.ClearState(false);
217+
container.Props.StateEnd = 0;
218+
container.Props.CurrentWayPoint = null; // forces GoToWp to use nearest WP, not stale pre-interrupt WP
219+
220+
}
221+
222+
container.Props.AnimationQueue.Enqueue(new StartState(
212223
new AnimationAction(int0: action, bool0: stopCurrentState, string0: wayPointName, instance0: other, instance1: victim),
213-
npc.GetUserData()));
224+
container));
214225
}
215226

216227
public void ExtAiLookAt(NpcInstance npc, string wayPointName)
@@ -259,7 +270,10 @@ public void ExtAiStandUp(NpcInstance npc)
259270
// FIXME - Implement remaining tasks from G1 documentation:
260271
// * Ist der Nsc in einem Animatinsstate, wird die passende Rücktransition abgespielt.
261272
// * Benutzt der NSC gerade ein MOBSI, poppt er ins stehen.
262-
npc.GetUserData().Props.AnimationQueue.Enqueue(new StandUp(new AnimationAction(), npc.GetUserData()));
273+
var container = npc.GetUserData();
274+
// Reset immediately (not via queue) so Daedalus C_BodyStateContains checks in the same ZS_*_Loop tick see BsStand.
275+
container.Props.BodyState = VmGothicEnums.BodyState.BsStand;
276+
container.Props.AnimationQueue.Enqueue(new StandUp(new AnimationAction(), container));
263277
}
264278

265279
public void ExtAiTurnToNpc(NpcInstance npc, NpcInstance other)

Assets/Gothic-Core/Scripts/Services/Npc/NpcHelperService.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,17 +176,13 @@ public bool ExtWldDetectNpcEx(NpcInstance npcInstance, int specificNpcIndex, int
176176
public int ExtNpcGetDistToWp(NpcInstance npc, string waypointName)
177177
{
178178
var npcGo = GetNpc(npc);
179-
var npcPos = npcGo.transform.position;
180-
181179
var waypoint = _wayNetService.GetWayNetPoint(waypointName);
182180

183-
if (waypoint == null || !npcGo)
184-
{
181+
if (!npcGo || waypoint == null)
185182
return int.MaxValue;
186-
}
187183

188184
// *100 as Gothic metrics are in cm, not m.
189-
return (int)(Vector3.Distance(npcPos, waypoint.Position) * 100);
185+
return (int)(Vector3.Distance(npcGo.transform.position, waypoint.Position) * 100);
190186
}
191187

192188
public int ExtNpcGetTalentSkill(NpcInstance npc, int skillId)

0 commit comments

Comments
 (0)