diff --git a/Content.Server/GameTicking/Rules/Components/NukeOperativeComponent.cs b/Content.Server/GameTicking/Rules/Components/NukeOperativeComponent.cs index 23994f673a..b27e8b73dc 100644 --- a/Content.Server/GameTicking/Rules/Components/NukeOperativeComponent.cs +++ b/Content.Server/GameTicking/Rules/Components/NukeOperativeComponent.cs @@ -1,3 +1,5 @@ +using Robust.Shared.Audio; + namespace Content.Server.GameTicking.Rules.Components; /// @@ -6,5 +8,9 @@ namespace Content.Server.GameTicking.Rules.Components; [RegisterComponent] public sealed class NukeOperativeComponent : Component { - + /// + /// Path to antagonist alert sound. + /// + [DataField("greetSoundNotification")] + public SoundSpecifier GreetSoundNotification = new SoundPathSpecifier("/Audio/Ambience/Antag/nukeops_start.ogg"); } diff --git a/Content.Server/GameTicking/Rules/Components/NukeopsRuleComponent.cs b/Content.Server/GameTicking/Rules/Components/NukeopsRuleComponent.cs index a9a88efcd8..8b950f5ab7 100644 --- a/Content.Server/GameTicking/Rules/Components/NukeopsRuleComponent.cs +++ b/Content.Server/GameTicking/Rules/Components/NukeopsRuleComponent.cs @@ -79,9 +79,6 @@ public sealed class NukeopsRuleComponent : Component [DataField("shuttleMap", customTypeSerializer: typeof(ResPathSerializer))] public ResPath NukieShuttleMap = new("/Maps/infiltrator.yml"); - [DataField("greetingSound", customTypeSerializer: typeof(SoundSpecifierTypeSerializer))] - public SoundSpecifier? GreetSound = new SoundPathSpecifier("/Audio/Misc/nukeops.ogg"); - [DataField("winType")] public WinType WinType = WinType.Neutral; diff --git a/Content.Server/GameTicking/Rules/Components/PiratesRuleComponent.cs b/Content.Server/GameTicking/Rules/Components/PiratesRuleComponent.cs index 7cb748c54d..1c8045d484 100644 --- a/Content.Server/GameTicking/Rules/Components/PiratesRuleComponent.cs +++ b/Content.Server/GameTicking/Rules/Components/PiratesRuleComponent.cs @@ -1,4 +1,6 @@ -namespace Content.Server.GameTicking.Rules.Components; +using Robust.Shared.Audio; + +namespace Content.Server.GameTicking.Rules.Components; [RegisterComponent, Access(typeof(PiratesRuleSystem))] public sealed class PiratesRuleComponent : Component @@ -12,4 +14,11 @@ public sealed class PiratesRuleComponent : Component [ViewVariables] public double InitialShipValue; + /// + /// Path to antagonist alert sound. + /// + [DataField("pirateAlertSound")] + public readonly SoundSpecifier PirateAlertSound = new SoundPathSpecifier( + "/Audio/Ambience/Antag/pirate_start.ogg", + AudioParams.Default.WithVolume(4)); } diff --git a/Content.Server/GameTicking/Rules/Components/TraitorRuleComponent.cs b/Content.Server/GameTicking/Rules/Components/TraitorRuleComponent.cs index 38f992144a..844aa74f3d 100644 --- a/Content.Server/GameTicking/Rules/Components/TraitorRuleComponent.cs +++ b/Content.Server/GameTicking/Rules/Components/TraitorRuleComponent.cs @@ -1,4 +1,4 @@ -using Content.Server.Traitor; +using Content.Server.Roles; using Content.Shared.Preferences; using Content.Shared.Roles; using Robust.Server.Player; @@ -10,7 +10,6 @@ namespace Content.Server.GameTicking.Rules.Components; [RegisterComponent, Access(typeof(TraitorRuleSystem))] public sealed class TraitorRuleComponent : Component { - public readonly SoundSpecifier AddedSound = new SoundPathSpecifier("/Audio/Misc/tatoralert.ogg"); public List Traitors = new(); [DataField("traitorPrototypeId", customTypeSerializer: typeof(PrototypeIdSerializer))] @@ -29,4 +28,10 @@ public sealed class TraitorRuleComponent : Component public SelectionState SelectionStatus = SelectionState.WaitingForSpawn; public TimeSpan AnnounceAt = TimeSpan.Zero; public Dictionary StartCandidates = new(); + + /// + /// Path to antagonist alert sound. + /// + [DataField("greetSoundNotification")] + public SoundSpecifier GreetSoundNotification = new SoundPathSpecifier("/Audio/Ambience/Antag/traitor_start.ogg"); } diff --git a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs index 47b421c419..f343de3f8e 100644 --- a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs @@ -10,6 +10,7 @@ using Content.Server.NPC.Components; using Content.Server.NPC.Systems; using Content.Server.Nuke; using Content.Server.Preferences.Managers; +using Content.Server.Roles; using Content.Server.RoundEnd; using Content.Server.Shuttles.Components; using Content.Server.Shuttles.Systems; @@ -194,8 +195,6 @@ public sealed class NukeopsRuleSystem : GameRuleSystem _chatManager.DispatchServerMessage(actor.PlayerSession, Loc.GetString("nukeops-welcome", ("station", component.TargetStation.Value))); filter.AddPlayer(actor.PlayerSession); } - - _audioSystem.PlayGlobal(component.GreetSound, filter, recordReplay: false); } private void OnRoundEnd(EntityUid uid, NukeopsRuleComponent? component = null) @@ -583,7 +582,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem { role ??= nukeops.OperativeRoleProto; - mind.AddRole(new TraitorRole(mind, _prototypeManager.Index(role))); + mind.AddRole(new NukeopsRole(mind, _prototypeManager.Index(role))); nukeops.OperativeMindPendingData.Remove(uid); } @@ -599,10 +598,13 @@ public sealed class NukeopsRuleSystem : GameRuleSystem if (GameTicker.RunLevel != GameRunLevel.InRound) return; - _audioSystem.PlayGlobal(nukeops.GreetSound, playerSession); - if (nukeops.TargetStation != null && !string.IsNullOrEmpty(Name(nukeops.TargetStation.Value))) + { _chatManager.DispatchServerMessage(playerSession, Loc.GetString("nukeops-welcome", ("station", nukeops.TargetStation.Value))); + + // Notificate player about new role assignment + _audioSystem.PlayGlobal(component.GreetSoundNotification, playerSession); + } } } @@ -760,7 +762,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem CharacterName = spawnDetails.Name }; newMind.ChangeOwningPlayer(session.UserId); - newMind.AddRole(new TraitorRole(newMind, nukeOpsAntag)); + newMind.AddRole(new NukeopsRole(newMind, nukeOpsAntag)); newMind.TransferTo(mob); } @@ -808,7 +810,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem return; //ok hardcoded value bad but so is everything else here - mind.AddRole(new TraitorRole(mind, _prototypeManager.Index("Nukeops"))); + mind.AddRole(new NukeopsRole(mind, _prototypeManager.Index("Nukeops"))); SetOutfitCommand.SetOutfit(mind.OwnedEntity.Value, "SyndicateOperativeGearFull", EntityManager); } diff --git a/Content.Server/GameTicking/Rules/PiratesRuleSystem.cs b/Content.Server/GameTicking/Rules/PiratesRuleSystem.cs index 043ba255a5..86d4a8bcaa 100644 --- a/Content.Server/GameTicking/Rules/PiratesRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/PiratesRuleSystem.cs @@ -14,12 +14,14 @@ using Content.Shared.Roles; using Robust.Server.GameObjects; using Robust.Server.Maps; using Robust.Server.Player; +using Robust.Shared.Audio; using Robust.Shared.Configuration; using Robust.Shared.Map; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Utility; using Robust.Shared.Enums; +using Robust.Shared.Player; namespace Content.Server.GameTicking.Rules; @@ -35,10 +37,10 @@ public sealed class PiratesRuleSystem : GameRuleSystem [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IServerPreferencesManager _prefs = default!; [Dependency] private readonly StationSpawningSystem _stationSpawningSystem = default!; - [Dependency] private readonly StationSystem _stationSystem = default!; [Dependency] private readonly PricingSystem _pricingSystem = default!; [Dependency] private readonly MapLoaderSystem _map = default!; [Dependency] private readonly NamingSystem _namingSystem = default!; + [Dependency] private readonly SharedAudioSystem _audioSystem = default!; /// public override void Initialize() @@ -218,6 +220,9 @@ public sealed class PiratesRuleSystem : GameRuleSystem pirates.Pirates.Add(newMind); + // Notificate every player about a pirate antagonist role with sound + _audioSystem.PlayGlobal(pirates.PirateAlertSound, session); + GameTicker.PlayerJoinGame(session); } @@ -235,6 +240,20 @@ public sealed class PiratesRuleSystem : GameRuleSystem if (!mind.OwnedEntity.HasValue) return; SetOutfitCommand.SetOutfit(mind.OwnedEntity.Value, "PirateGear", EntityManager); + + var pirateRule = EntityQuery().FirstOrDefault(); + if (pirateRule == null) + { + //todo fuck me this shit is awful + GameTicker.StartGameRule("Pirates", out var ruleEntity); + pirateRule = Comp(ruleEntity); + } + + // Notificate every player about a pirate antagonist role with sound + if (mind.Session != null) + { + _audioSystem.PlayGlobal(pirateRule.PirateAlertSound, mind.Session); + } } private void OnStartAttempt(RoundStartAttemptEvent ev) diff --git a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs index 0c93e0e267..f9e43a5aec 100644 --- a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs @@ -7,21 +7,18 @@ using Content.Server.PDA.Ringer; using Content.Server.Players; using Content.Server.Roles; using Content.Server.Shuttles.Components; -using Content.Server.Traitor; using Content.Server.Traitor.Uplink; using Content.Shared.CCVar; using Content.Shared.Dataset; using Content.Shared.Preferences; using Content.Shared.Mobs.Systems; +using Content.Shared.PDA; using Content.Shared.Roles; using Robust.Server.Player; -using Robust.Shared.Audio; using Robust.Shared.Configuration; -using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Timing; -using Robust.Shared.Utility; namespace Content.Server.GameTicking.Rules; @@ -149,7 +146,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem } } - public List FindPotentialTraitors(in Dictionary candidates, TraitorRuleComponent component) + private List FindPotentialTraitors(in Dictionary candidates, TraitorRuleComponent component) { var list = new List(); var pendingQuery = GetEntityQuery(); @@ -187,7 +184,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem return prefList; } - public List PickTraitors(int traitorCount, List prefList) + private List PickTraitors(int traitorCount, List prefList) { var results = new List(traitorCount); if (prefList.Count == 0) @@ -213,6 +210,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem //no i wont fuck you, erp is against rules GameTicker.StartGameRule("Traitor", out var ruleEntity); traitorRule = Comp(ruleEntity); + MakeCodewords(traitorRule); } var mind = traitor.Data.ContentData()?.Mind; @@ -221,60 +219,83 @@ public sealed class TraitorRuleSystem : GameRuleSystem _sawmill.Info("Failed getting mind for picked traitor."); return false; } - if (mind.OwnedEntity is not { } entity) { Logger.ErrorS("preset", "Mind picked for traitor did not have an attached entity."); return false; } - // creadth: we need to create uplink for the antag. - // PDA should be in place already - DebugTools.AssertNotNull(mind.OwnedEntity); - + // Calculate the amount of currency on the uplink. var startingBalance = _cfg.GetCVar(CCVars.TraitorStartingBalance); - if (mind.CurrentJob != null) startingBalance = Math.Max(startingBalance - mind.CurrentJob.Prototype.AntagAdvantage, 0); + // creadth: we need to create uplink for the antag. + // PDA should be in place already var pda = _uplink.FindUplinkTarget(mind.OwnedEntity!.Value); if (pda == null || !_uplink.AddUplink(mind.OwnedEntity.Value, startingBalance)) return false; + // Add the ringtone uplink and get its code for greeting + var code = EnsureComp(pda.Value).Code; - // add the ringtone uplink and get its code for greeting - var code = AddComp(pda.Value).Code; - + // Prepare antagonist role var antagPrototype = _prototypeManager.Index(traitorRule.TraitorPrototypeId); var traitorRole = new TraitorRole(mind, antagPrototype); - mind.AddRole(traitorRole); - traitorRule.Traitors.Add(traitorRole); - traitorRole.GreetTraitor(traitorRule.Codewords, code); + // Give traitors their codewords and uplink code to keep in their character info menu + traitorRole.Mind.Briefing = string.Format( + "{0}\n{1}", + Loc.GetString("traitor-role-codewords-short", ("codewords", string.Join(", ", traitorRule.Codewords))), + Loc.GetString("traitor-role-uplink-code-short", ("code", string.Join("", code)))); + + // Assign traitor roles + mind.AddRole(traitorRole); + SendTraitorBriefing(mind, traitorRule.Codewords, code); + traitorRule.Traitors.Add(traitorRole); + + if (mind.TryGetSession(out var session)) + { + // Notificate player about new role assignment + _audioSystem.PlayGlobal(traitorRule.GreetSoundNotification, session); + } + + // Change the faction _faction.RemoveFaction(entity, "NanoTrasen", false); _faction.AddFaction(entity, "Syndicate"); + // Give traitors their objectives var maxDifficulty = _cfg.GetCVar(CCVars.TraitorMaxDifficulty); var maxPicks = _cfg.GetCVar(CCVars.TraitorMaxPicks); - - //give traitors their objectives var difficulty = 0f; for (var pick = 0; pick < maxPicks && maxDifficulty > difficulty; pick++) { var objective = _objectivesManager.GetRandomObjective(traitorRole.Mind, "TraitorObjectiveGroups"); - if (objective == null) continue; + if (objective == null) + continue; if (traitorRole.Mind.TryAddObjective(objective)) difficulty += objective.Difficulty; } - //give traitors their codewords and uplink code to keep in their character info menu - traitorRole.Mind.Briefing = Loc.GetString("traitor-role-codewords-short", ("codewords", string.Join(", ", traitorRule.Codewords))) - + "\n" + Loc.GetString("traitor-role-uplink-code-short", ("code", string.Join("", code))); - - _audioSystem.PlayGlobal(traitorRule.AddedSound, Filter.Empty().AddPlayer(traitor), false, AudioParams.Default); return true; } + /// + /// Send a codewords and uplink codes to traitor chat. + /// + /// A mind (player) + /// Codewords + /// Uplink codes + private void SendTraitorBriefing(Mind.Mind mind, string[] codewords, Note[] code) + { + if (mind.TryGetSession(out var session)) + { + _chatManager.DispatchServerMessage(session, Loc.GetString("traitor-role-greeting")); + _chatManager.DispatchServerMessage(session, Loc.GetString("traitor-role-codewords", ("codewords", string.Join(", ", codewords)))); + _chatManager.DispatchServerMessage(session, Loc.GetString("traitor-role-uplink-code", ("code", string.Join("", code)))); + } + } + private void HandleLatejoin(PlayerSpawnCompleteEvent ev) { var query = EntityQueryEnumerator(); @@ -428,7 +449,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem return allTraitors; } - public List GetOtherTraitorsAliveAndConnected(Mind.Mind ourMind, TraitorRuleComponent component) + private List GetOtherTraitorsAliveAndConnected(Mind.Mind ourMind, TraitorRuleComponent component) { return component.Traitors // don't want .Where(t => t.Mind.OwnedEntity is not null) // no entity diff --git a/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs b/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs index f7975e1560..7ae2c44711 100644 --- a/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs @@ -7,6 +7,7 @@ using Content.Server.Mind.Components; using Content.Server.Players; using Content.Server.Popups; using Content.Server.Preferences.Managers; +using Content.Server.Roles; using Content.Server.RoundEnd; using Content.Server.Traitor; using Content.Server.Zombies; @@ -284,7 +285,7 @@ public sealed class ZombieRuleSystem : GameRuleSystem DebugTools.AssertNotNull(mind.OwnedEntity); - mind.AddRole(new TraitorRole(mind, _prototypeManager.Index(component.PatientZeroPrototypeID))); + mind.AddRole(new ZombieRole(mind, _prototypeManager.Index(component.PatientZeroPrototypeID))); var inCharacterName = string.Empty; // Create some variation between the times of each zombie, relative to the time of the group as a whole. diff --git a/Content.Server/Mind/Mind.cs b/Content.Server/Mind/Mind.cs index 4407a1b2cd..3af6daf4eb 100644 --- a/Content.Server/Mind/Mind.cs +++ b/Content.Server/Mind/Mind.cs @@ -259,9 +259,7 @@ namespace Content.Server.Mind public bool HasRole() where T : Role { - var t = typeof(T); - - return _roles.Any(role => role.GetType() == t); + return _roles.Any(role => role is T); } /// diff --git a/Content.Server/Objectives/Conditions/RandomTraitorProgressCondition.cs b/Content.Server/Objectives/Conditions/RandomTraitorProgressCondition.cs index 99de8be282..1f8e6ffc2e 100644 --- a/Content.Server/Objectives/Conditions/RandomTraitorProgressCondition.cs +++ b/Content.Server/Objectives/Conditions/RandomTraitorProgressCondition.cs @@ -3,6 +3,7 @@ using Content.Server.Objectives.Interfaces; using Robust.Shared.Random; using Robust.Shared.Utility; using Content.Server.GameTicking.Rules; +using Content.Server.Roles; namespace Content.Server.Objectives.Conditions { @@ -17,7 +18,7 @@ namespace Content.Server.Objectives.Conditions var entityMgr = IoCManager.Resolve(); var traitors = entityMgr.EntitySysManager.GetEntitySystem().GetOtherTraitorsAliveAndConnected(mind).ToList(); - List removeList = new(); + List removeList = new(); foreach (var traitor in traitors) { diff --git a/Content.Server/Objectives/Requirements/TraitorRequirement.cs b/Content.Server/Objectives/Requirements/TraitorRequirement.cs index 3f25ce593a..1a7cd816ff 100644 --- a/Content.Server/Objectives/Requirements/TraitorRequirement.cs +++ b/Content.Server/Objectives/Requirements/TraitorRequirement.cs @@ -1,6 +1,8 @@ using Content.Server.Objectives.Interfaces; +using Content.Server.Roles; using Content.Server.Traitor; using JetBrains.Annotations; +using TraitorRole = Content.Server.Roles.TraitorRole; namespace Content.Server.Objectives.Requirements { diff --git a/Content.Server/Roles/AntagonistRole.cs b/Content.Server/Roles/AntagonistRole.cs new file mode 100644 index 0000000000..9eb6146365 --- /dev/null +++ b/Content.Server/Roles/AntagonistRole.cs @@ -0,0 +1,24 @@ +using Content.Shared.Roles; + +namespace Content.Server.Roles; + +public abstract class AntagonistRole : Role +{ + public AntagPrototype Prototype { get; } + + public override string Name { get; } + + public override bool Antagonist { get; } + + /// + /// .ctor + /// + /// A mind (player) + /// Antagonist prototype + protected AntagonistRole(Mind.Mind mind, AntagPrototype antagPrototype) : base(mind) + { + Prototype = antagPrototype; + Name = Loc.GetString(antagPrototype.Name); + Antagonist = antagPrototype.Antagonist; + } +} diff --git a/Content.Server/Roles/NukeopsRole.cs b/Content.Server/Roles/NukeopsRole.cs new file mode 100644 index 0000000000..bbb8ca1da3 --- /dev/null +++ b/Content.Server/Roles/NukeopsRole.cs @@ -0,0 +1,8 @@ +using Content.Shared.Roles; + +namespace Content.Server.Roles; + +public sealed class NukeopsRole : AntagonistRole +{ + public NukeopsRole(Mind.Mind mind, AntagPrototype antagPrototype) : base(mind, antagPrototype) { } +} diff --git a/Content.Server/Roles/TraitorRole.cs b/Content.Server/Roles/TraitorRole.cs new file mode 100644 index 0000000000..adab41eed2 --- /dev/null +++ b/Content.Server/Roles/TraitorRole.cs @@ -0,0 +1,10 @@ +using Content.Server.Chat.Managers; +using Content.Shared.PDA; +using Content.Shared.Roles; + +namespace Content.Server.Roles; + +public sealed class TraitorRole : AntagonistRole +{ + public TraitorRole(Mind.Mind mind, AntagPrototype antagPrototype) : base(mind, antagPrototype) { } +} diff --git a/Content.Server/Roles/ZombieRole.cs b/Content.Server/Roles/ZombieRole.cs new file mode 100644 index 0000000000..75a4807664 --- /dev/null +++ b/Content.Server/Roles/ZombieRole.cs @@ -0,0 +1,8 @@ +using Content.Shared.Roles; + +namespace Content.Server.Roles; + +public sealed class ZombieRole : AntagonistRole +{ + public ZombieRole(Mind.Mind mind, AntagPrototype antagPrototype) : base(mind, antagPrototype) { } +} diff --git a/Content.Server/Store/Conditions/BuyerAntagCondition.cs b/Content.Server/Store/Conditions/BuyerAntagCondition.cs index d0f4292dbe..fcf02b73c0 100644 --- a/Content.Server/Store/Conditions/BuyerAntagCondition.cs +++ b/Content.Server/Store/Conditions/BuyerAntagCondition.cs @@ -1,4 +1,5 @@ using Content.Server.Mind.Components; +using Content.Server.Roles; using Content.Server.Traitor; using Content.Shared.Roles; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set; @@ -35,7 +36,7 @@ public sealed class BuyerAntagCondition : ListingCondition { foreach (var role in mind.Mind.AllRoles) { - if (role is not TraitorRole blacklistantag) + if (role is not AntagonistRole blacklistantag) continue; if (Blacklist.Contains(blacklistantag.Prototype.ID)) @@ -48,7 +49,7 @@ public sealed class BuyerAntagCondition : ListingCondition var found = false; foreach (var role in mind.Mind.AllRoles) { - if (role is not TraitorRole antag) + if (role is not AntagonistRole antag) continue; if (Whitelist.Contains(antag.Prototype.ID)) diff --git a/Content.Server/Traitor/TraitorRole.cs b/Content.Server/Traitor/TraitorRole.cs deleted file mode 100644 index 6717fcb4c6..0000000000 --- a/Content.Server/Traitor/TraitorRole.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Content.Server.Chat.Managers; -using Content.Server.Roles; -using Content.Shared.PDA; -using Content.Shared.Roles; - -namespace Content.Server.Traitor -{ - public sealed class TraitorRole : Role - { - public AntagPrototype Prototype { get; } - - public TraitorRole(Mind.Mind mind, AntagPrototype antagPrototype) : base(mind) - { - Prototype = antagPrototype; - Name = Loc.GetString(antagPrototype.Name); - Antagonist = antagPrototype.Antagonist; - } - - public override string Name { get; } - public override bool Antagonist { get; } - - public void GreetTraitor(string[] codewords, Note[] code) - { - if (Mind.TryGetSession(out var session)) - { - var chatMgr = IoCManager.Resolve(); - var entMgr = IoCManager.Resolve(); - chatMgr.DispatchServerMessage(session, Loc.GetString("traitor-role-greeting")); - chatMgr.DispatchServerMessage(session, Loc.GetString("traitor-role-codewords", ("codewords", string.Join(", ", codewords)))); - chatMgr.DispatchServerMessage(session, Loc.GetString("traitor-role-uplink-code", ("code", string.Join("", code)))); - } - } - } -} diff --git a/Content.Server/Zombies/ZombifyOnDeathSystem.cs b/Content.Server/Zombies/ZombifyOnDeathSystem.cs index a0a26eb6e2..9c1fb81e99 100644 --- a/Content.Server/Zombies/ZombifyOnDeathSystem.cs +++ b/Content.Server/Zombies/ZombifyOnDeathSystem.cs @@ -13,6 +13,7 @@ using Content.Server.Mind.Commands; using Content.Server.Mind.Components; using Content.Server.Nutrition.Components; using Content.Server.Popups; +using Content.Server.Roles; using Content.Server.Speech.Components; using Content.Server.Temperature.Components; using Content.Server.Traitor; @@ -58,6 +59,7 @@ namespace Content.Server.Zombies [Dependency] private readonly IPrototypeManager _proto = default!; [Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly MobThresholdSystem _mobThreshold = default!; + [Dependency] private readonly SharedAudioSystem _audioSystem = default!; public override void Initialize() { @@ -207,9 +209,12 @@ namespace Content.Server.Zombies if (mindcomp.Mind != null && mindcomp.Mind.TryGetSession(out var session)) { //Zombie role for player manifest - mindcomp.Mind.AddRole(new TraitorRole(mindcomp.Mind, _proto.Index(zombiecomp.ZombieRoleId))); + mindcomp.Mind.AddRole(new ZombieRole(mindcomp.Mind, _proto.Index(zombiecomp.ZombieRoleId))); //Greeting message for new bebe zombers _chatMan.DispatchServerMessage(session, Loc.GetString("zombie-infection-greeting")); + + // Notificate player about new role assignment + _audioSystem.PlayGlobal(zombiecomp.GreetSoundNotification, session); } if (!HasComp(target) && !mindcomp.HasMind) //this specific component gives build test trouble so pop off, ig diff --git a/Content.Shared/Zombies/ZombieComponent.cs b/Content.Shared/Zombies/ZombieComponent.cs index 6031f993c1..28ab989ae1 100644 --- a/Content.Shared/Zombies/ZombieComponent.cs +++ b/Content.Shared/Zombies/ZombieComponent.cs @@ -2,6 +2,7 @@ using Content.Shared.Chat.Prototypes; using Content.Shared.Damage; using Content.Shared.Roles; using Content.Shared.Humanoid; +using Robust.Shared.Audio; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; @@ -133,5 +134,11 @@ namespace Content.Shared.Zombies { "Shock", -0.2 }, } }; + + /// + /// Path to antagonist alert sound. + /// + [DataField("greetSoundNotification")] + public SoundSpecifier GreetSoundNotification = new SoundPathSpecifier("/Audio/Ambience/Antag/zombie_start.ogg"); } } diff --git a/Resources/Audio/Ambience/Antag/attributions.yml b/Resources/Audio/Ambience/Antag/attributions.yml new file mode 100644 index 0000000000..b600fc30b4 --- /dev/null +++ b/Resources/Audio/Ambience/Antag/attributions.yml @@ -0,0 +1,12 @@ +- files: ["nukeops_start.ogg"] + license: "CC-BY-NC-SA-3.0" + copyright: "Taken from TG station." + source: "https://github.com/tgstation/tgstation/commit/827967c9650c23af64280ad1491405fed8f644c5" +- files: ["pirate_start.ogg"] + license: "CC-BY-NC-SA-3.0" + copyright: "Made by @MIXnikita#1474 (Discord) for SS14" + source: "https://github.com/SerbiaStrong-220/space-station-14/blob/master/Resources/Audio/Ambience/Antag/pirate_start.ogg" +- files: ["zombie_start.ogg"] + license: "CC-BY-NC-SA-3.0" + copyright: "Made by @MIXnikita#1474 (Discord) for SS14" + source: "https://github.com/SerbiaStrong-220/space-station-14/blob/master/Resources/Audio/Ambience/Antag/zombie_start.ogg" \ No newline at end of file diff --git a/Resources/Audio/Misc/nukeops.ogg b/Resources/Audio/Ambience/Antag/nukeops_start.ogg similarity index 100% rename from Resources/Audio/Misc/nukeops.ogg rename to Resources/Audio/Ambience/Antag/nukeops_start.ogg diff --git a/Resources/Audio/Ambience/Antag/pirate_start.ogg b/Resources/Audio/Ambience/Antag/pirate_start.ogg new file mode 100644 index 0000000000..785b1313c9 Binary files /dev/null and b/Resources/Audio/Ambience/Antag/pirate_start.ogg differ diff --git a/Resources/Audio/Misc/tatoralert.ogg b/Resources/Audio/Ambience/Antag/traitor_start.ogg similarity index 100% rename from Resources/Audio/Misc/tatoralert.ogg rename to Resources/Audio/Ambience/Antag/traitor_start.ogg diff --git a/Resources/Audio/Ambience/Antag/zombie_start.ogg b/Resources/Audio/Ambience/Antag/zombie_start.ogg new file mode 100644 index 0000000000..e1ef13f465 Binary files /dev/null and b/Resources/Audio/Ambience/Antag/zombie_start.ogg differ diff --git a/Resources/Audio/Misc/license.txt b/Resources/Audio/Misc/license.txt index 0870697261..a4f5ac49e3 100644 --- a/Resources/Audio/Misc/license.txt +++ b/Resources/Audio/Misc/license.txt @@ -4,6 +4,4 @@ siren.ogg taken from https://github.com/ParadiseSS13/Paradise/blob/master/sound/ redalert.ogg was taken from: https://github.com/Skyrat-SS13/Skyrat13/commit/2d4f2d1b489590b559e4073f41b126cef56f4c50 -bluealert.ogg was taken from: https://github.com/Skyrat-SS13/Skyrat13/commit/2d4f2d1b489590b559e4073f41b126cef56f4c50 - -nukeops.ogg was taken from: https://github.com/tgstation/tgstation/commit/827967c9650c23af64280ad1491405fed8f644c5 +bluealert.ogg was taken from: https://github.com/Skyrat-SS13/Skyrat13/commit/2d4f2d1b489590b559e4073f41b126cef56f4c50 \ No newline at end of file