#nullable enable annotations using System.Collections.Generic; using Content.Shared.Preferences; using Content.Server.Administration; using Content.Server.GameObjects.Components.Mobs; using Content.Server.GameObjects.Components.Observer; using Content.Server.Interfaces.GameTicking; using Content.Server.Players; using Content.Server.Mobs; using Content.Shared.Damage; using Content.Shared.GameObjects.Components.Damage; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.Components.Mobs.State; using Robust.Shared.Network; using Robust.Shared.Interfaces.GameObjects; using Robust.Server.Interfaces.Console; using Robust.Server.Interfaces.Player; using Robust.Shared.IoC; namespace Content.Server.GameTicking { /// /// A round-start setup preset, such as which antagonists to spawn. /// public abstract class GamePreset { public abstract bool Start(IReadOnlyList readyPlayers, bool force = false); public virtual string ModeTitle => "Sandbox"; public virtual string Description => "Secret!"; public virtual bool DisallowLateJoin => false; public Dictionary ReadyProfiles = new(); public virtual void OnGameStarted() { } /// /// Called when a player is spawned in (this includes, but is not limited to, before Start) /// public virtual void OnSpawnPlayerCompleted(IPlayerSession session, IEntity mob, bool lateJoin) { } /// /// Called when a player attempts to ghost. /// public virtual bool OnGhostAttempt(Mind mind, bool canReturnGlobal) { var playerEntity = mind.OwnedEntity; if (playerEntity != null && playerEntity.HasComponent()) return false; if (mind.VisitingEntity != null) { mind.UnVisit(); mind.VisitingEntity.Delete(); } var position = playerEntity?.Transform.Coordinates ?? IoCManager.Resolve().GetObserverSpawnPoint(); var canReturn = false; if (playerEntity != null && canReturnGlobal && playerEntity.TryGetComponent(out IMobStateComponent? mobState)) { if (mobState.IsDead()) { canReturn = true; } else if (mobState.IsCritical()) { canReturn = true; if (playerEntity.TryGetComponent(out IDamageableComponent? damageable)) { //todo: what if they dont breathe lol damageable.SetDamage(DamageType.Asphyxiation, 200, playerEntity); } } else { canReturn = false; } } var entityManager = IoCManager.Resolve(); var ghost = entityManager.SpawnEntity("MobObserver", position); ghost.Name = mind.CharacterName; var ghostComponent = ghost.GetComponent(); ghostComponent.CanReturnToBody = canReturn; if (canReturn) mind.Visit(ghost); else mind.TransferTo(ghost); return true; } public virtual string GetRoundEndDescription() => ""; } }