public void Die() { if (currentState == MonsterAiState.StateDead) { return; } currentState = MonsterAiState.StateDead; Character.State = CharacterState.Dead; CombatEntity.DistributeExperience(); Character.IsActive = false; Character.Map.RemoveEntity(ref Entity, CharacterRemovalReason.Dead); if (SpawnEntry == null) { ServerLogger.LogWarning("Attempting to remove entity without spawn data! How?? " + Character.ClassId); World.Instance.RemoveEntity(ref Entity); } else { var min = SpawnEntry.SpawnTime; var max = SpawnEntry.SpawnTime + SpawnEntry.SpawnVariance; deadTimeout = GameRandom.NextFloat(min / 1000f, max / 1000f); if (deadTimeout < 0.4f) { deadTimeout = 0.4f; //minimum respawn time } nextAiUpdate = Time.ElapsedTimeFloat + deadTimeout + 0.1f; deadTimeout += Time.ElapsedTimeFloat; } }
public void AiStateMachineUpdate() { #if DEBUG if (!Character.IsActive && currentState != MonsterAiState.StateDead) { ServerLogger.LogWarning($"Monster was in incorrect state {currentState}, even though it should be dead (character is not active)"); currentState = MonsterAiState.StateDead; } #endif Profiler.Event(ProfilerEvent.MonsterStateMachineUpdate); for (var i = 0; i < aiEntries.Count; i++) { var entry = aiEntries[i]; if (entry.InputState != currentState) { continue; } if (!InputStateCheck(entry.InputCheck)) { continue; } if (!OutputStateCheck(entry.OutputCheck)) { continue; } //ServerLogger.Log($"Monster from {entry.InputState} to state {entry.OutputState} (via {entry.InputCheck}/{entry.OutputCheck})"); Profiler.Event(ProfilerEvent.MonsterStateMachineChangeSuccess); currentState = entry.OutputState; } Character.LastAttacked = EcsEntity.Null; if (Character.Map != null && Character.Map.PlayerCount == 0) { nextAiUpdate = Time.ElapsedTimeFloat + 2f + GameRandom.NextFloat(0f, 1f); } else { if (nextAiUpdate < Time.ElapsedTimeFloat) { if (nextAiUpdate + Time.DeltaTimeFloat < Time.ElapsedTimeFloat) { nextAiUpdate = Time.ElapsedTimeFloat + aiTickRate; } else { nextAiUpdate += aiTickRate; } } } }
public void Initialize(ref EcsEntity e, Character character, CombatEntity combat, MonsterDatabaseInfo monData, MonsterAiType type, MapSpawnEntry spawnEntry, string mapName) { Entity = e; Character = character; this.SpawnEntry = spawnEntry; CombatEntity = combat; MonsterBase = monData; aiType = type; SpawnMap = mapName; aiEntries = DataManager.GetAiStateMachine(aiType); nextAiUpdate = Time.ElapsedTimeFloat + 1f; if (Character.ClassId >= 4000 && SpawnEntry == null) { throw new Exception("Monster created without spawn entry"); //remove when arbitrary monster spawning is added } UpdateStats(); currentState = MonsterAiState.StateIdle; }