diff --git a/src/GameLogic/MapInitializer.cs b/src/GameLogic/MapInitializer.cs
index 45a7e21e4..f59546929 100644
--- a/src/GameLogic/MapInitializer.cs
+++ b/src/GameLogic/MapInitializer.cs
@@ -138,6 +138,7 @@ private void RegisterForConfigChanges(GameMap createdMap, MonsterSpawnArea spawn
await createdMap.RemoveAsync(o).ConfigureAwait(false);
o.Initialize();
await createdMap.AddAsync(o).ConfigureAwait(false);
+ o.OnSpawn();
if (this._spawnedMonsters.TryGetValue(area, out var previousSpawnCount))
{
@@ -275,6 +276,7 @@ public async ValueTask InitializeNpcsOnWaveStartAsync(GameMap createdMap, IEvent
npc.SpawnIndex = spawnIndex;
npc.Initialize();
await createdMap.AddAsync(npc).ConfigureAwait(false);
+ npc.OnSpawn();
if (spawnArea.SpawnTrigger is SpawnTrigger.Automatic or SpawnTrigger.Wandering)
{
this.RegisterForConfigChanges(createdMap, spawnArea, npc);
diff --git a/src/GameLogic/NPC/AttackableNpcBase.cs b/src/GameLogic/NPC/AttackableNpcBase.cs
index 675f7ec50..c84aac422 100644
--- a/src/GameLogic/NPC/AttackableNpcBase.cs
+++ b/src/GameLogic/NPC/AttackableNpcBase.cs
@@ -237,6 +237,7 @@ private async ValueTask RespawnAsync()
this.Initialize();
await this.CurrentMap.RespawnAsync(this).ConfigureAwait(false);
+ this.OnSpawn();
}
catch (Exception ex)
{
diff --git a/src/GameLogic/NPC/Monster.cs b/src/GameLogic/NPC/Monster.cs
index d13f7444d..c1310301b 100644
--- a/src/GameLogic/NPC/Monster.cs
+++ b/src/GameLogic/NPC/Monster.cs
@@ -41,6 +41,8 @@ public sealed class Monster : AttackableNpcBase, IAttackable, IAttacker, ISuppor
private bool _isCalculatingPath;
+ private bool _isReadyToWalk;
+
///
/// Initializes a new instance of the class.
///
@@ -77,7 +79,6 @@ public Monster(MonsterSpawnArea spawnInfo, MonsterDefinition stats, GameMap map,
///
public Player? SummonedBy => (this._intelligence as SummonedMonsterIntelligence)?.Owner;
- ///
public Point WalkTarget => this._walker.CurrentTarget;
///
@@ -104,13 +105,20 @@ public async ValueTask AttackAsync(IAttackable target)
}
}
+ ///
+ public override void OnSpawn()
+ {
+ base.OnSpawn();
+ this._isReadyToWalk = true;
+ }
+
///
/// Walks to the target coordinates.
///
/// The target object.
public async ValueTask WalkToAsync(Point target)
{
- if (this._isCalculatingPath || this.IsWalking)
+ if (this._isCalculatingPath || this.IsWalking || !this._isReadyToWalk)
{
return false;
}
@@ -215,6 +223,11 @@ public ValueTask MoveAsync(Point target)
///
internal async ValueTask RandomMoveAsync()
{
+ if (!this._isReadyToWalk)
+ {
+ return;
+ }
+
byte randx = (byte)GameLogic.Rand.NextInt(Math.Max(0, this.Position.X - 1), Math.Min(0xFF, this.Position.X + 2));
byte randy = (byte)GameLogic.Rand.NextInt(Math.Max(0, this.Position.Y - 1), Math.Min(0xFF, this.Position.Y + 2));
if (this.CurrentMap.Terrain.AIgrid[randx, randy] == 1)
diff --git a/src/GameLogic/NPC/NonPlayerCharacter.cs b/src/GameLogic/NPC/NonPlayerCharacter.cs
index 9ef7319e4..fa95125c8 100644
--- a/src/GameLogic/NPC/NonPlayerCharacter.cs
+++ b/src/GameLogic/NPC/NonPlayerCharacter.cs
@@ -96,6 +96,14 @@ public virtual void Initialize()
this.Rotation = GetSpawnDirection(this.SpawnArea.Direction);
}
+ ///
+ /// Called when this instance spawned on the map.
+ ///
+ public virtual void OnSpawn()
+ {
+ // can be overwritten
+ }
+
///
public async ValueTask AddObserverAsync(IWorldObserver observer)
{
diff --git a/src/GameLogic/Player.cs b/src/GameLogic/Player.cs
index 80f3d8bbe..c2899a6e2 100644
--- a/src/GameLogic/Player.cs
+++ b/src/GameLogic/Player.cs
@@ -901,6 +901,7 @@ public async ValueTask ClientReadyAfterMapChangeAsync()
if (this.Summon?.Item1 is { IsAlive: true } summon)
{
await this.CurrentMap.AddAsync(summon).ConfigureAwait(false);
+ summon.OnSpawn();
}
}
@@ -1321,6 +1322,7 @@ public async ValueTask CreateSummonedMonsterAsync(MonsterDefinition definition)
this.Summon = (monster, intelligence);
monster.Initialize();
await gameMap.AddAsync(monster).ConfigureAwait(false);
+ monster.OnSpawn();
}
///