using Content.Server.Antag; using Content.Server.Atmos.Components; using Content.Server.GameTicking.Rules.Components; using Content.Server.Mind; using Content.Server.Objectives; using Content.Server.Roles; using Content.Server.Vampire; using Content.Server.Bible.Components; using Content.Shared.Alert; using Content.Shared.Vampire.Components; using Content.Shared.NPC.Prototypes; using Content.Shared.NPC.Systems; using Content.Shared.Roles; using Content.Shared.Store; using Content.Shared.Store.Components; using Content.Shared.Atmos; using Content.Shared.Atmos.Rotting; using Content.Shared.Nutrition.Components; using Robust.Server.GameObjects; using Robust.Shared.Audio; using Robust.Shared.Prototypes; using System.Text; using Content.Shared.Roles.Components; namespace Content.Server.GameTicking.Rules; public sealed partial class VampireRuleSystem : GameRuleSystem { [Dependency] private readonly MindSystem _mind = default!; [Dependency] private readonly AntagSelectionSystem _antag = default!; [Dependency] private readonly AlertsSystem _alerts = default!; [Dependency] private readonly SharedRoleSystem _role = default!; [Dependency] private readonly NpcFactionSystem _npcFaction = default!; [Dependency] private readonly ObjectivesSystem _objective = default!; [Dependency] private readonly VampireSystem _vampire = default!; [Dependency] private readonly UserInterfaceSystem _uiSystem = default!; public readonly SoundSpecifier BriefingSound = new SoundPathSpecifier("/Audio/Ambience/Antag/vampire_start.ogg"); public readonly ProtoId VampirePrototypeId = "Vampire"; public readonly ProtoId ChangelingFactionId = "Vampire"; public readonly ProtoId NanotrasenFactionId = "NanoTrasen"; public readonly ProtoId Currency = "BloodEssence"; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnGetBriefing); SubscribeLocalEvent(OnSelectAntag); SubscribeLocalEvent(OnTextPrepend); } private void OnSelectAntag(EntityUid mindId, VampireRuleComponent comp, ref AfterAntagEntitySelectedEvent args) { var ent = args.EntityUid; if (HasComp(ent)) return; _antag.SendBriefing(ent, MakeBriefing(ent), Color.Yellow, BriefingSound); MakeVampire(ent, comp); } public bool MakeVampire(EntityUid target, VampireRuleComponent rule) { if (!_mind.TryGetMind(target, out var mindId, out var mind)) return false; // briefing if (TryComp(target, out var metaData)) { var briefing = Loc.GetString("vampire-role-greeting", ("name", metaData?.EntityName ?? "Unknown")); var briefingShort = Loc.GetString("vampire-role-greeting-short", ("name", metaData?.EntityName ?? "Unknown")); _role.MindHasRole(mindId, out var vampireRole); _role.MindHasRole(mindId, out var briefingComp); if (vampireRole is not null && briefingComp is null) { AddComp(vampireRole.Value.Owner); Comp(vampireRole.Value.Owner).Briefing = briefing; } } // vampire stuff _npcFaction.RemoveFaction(target, NanotrasenFactionId, false); _npcFaction.AddFaction(target, ChangelingFactionId); // make sure it's initial chems are set to max var vampireComponent = EnsureComp(target); var alertsComponent = EnsureComp(target); EnsureComp(target); var vampireAlertComponent = EnsureComp(target); var interfaceComponent = EnsureComp(target); if (HasComp(target)) _uiSystem.SetUiState(target, VampireMutationUiKey.Key, new VampireMutationBoundUserInterfaceState(vampireComponent.VampireMutations, vampireComponent.CurrentMutation)); var vampire = new Entity(target, vampireComponent); RemComp(vampire); RemComp(vampire); RemComp(vampire); vampireComponent.Balance = new() { { VampireComponent.CurrencyProto, 0 } }; rule.VampireMinds.Add(mindId); _vampire.AddStartingAbilities(vampire); _vampire.MakeVulnerableToHoly(vampire); _alerts.ShowAlert((vampire, alertsComponent), vampireAlertComponent.BloodAlert); _alerts.ShowAlert((vampire, alertsComponent), vampireAlertComponent.StellarWeaknessAlert); return true; } private void OnGetBriefing(Entity role, ref GetBriefingEvent args) { var ent = args.Mind.Comp.OwnedEntity; if (ent is null) return; args.Append(MakeBriefing(ent.Value)); } private string MakeBriefing(EntityUid ent) { if (TryComp(ent, out var metaData)) { var briefing = Loc.GetString("vampire-role-greeting", ("name", metaData?.EntityName ?? "Unknown")); return briefing; } return ""; } private void OnTextPrepend(EntityUid uid, VampireRuleComponent comp, ref ObjectivesTextPrependEvent args) { var mostDrainedName = string.Empty; var mostDrained = 0f; foreach (var vamp in EntityQuery()) { if (!_mind.TryGetMind(vamp.Owner, out var mindId, out var mind)) continue; if (!TryComp(vamp.Owner, out var metaData)) continue; if (vamp.TotalBloodDrank > mostDrained) { mostDrained = vamp.TotalBloodDrank; mostDrainedName = _objective.GetTitle((mindId, mind), metaData.EntityName); } } var sb = new StringBuilder(); sb.AppendLine(Loc.GetString($"roundend-prepend-vampire-drained{(!string.IsNullOrWhiteSpace(mostDrainedName) ? "-named" : "")}", ("name", mostDrainedName), ("number", mostDrained))); args.Text = sb.ToString(); } }