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(); } ///