Ert fix (#317)
* Hotfix * Fuck custom server event! Hello gamerule! * add some shit * oopsie * Add CCVAR of loading a ERT map and disable it on dev build
This commit is contained in:
@@ -1,13 +1,13 @@
|
|||||||
using Content.Server.Access.Systems;
|
using Content.Server.GameTicking;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
|
using Content.Server.Station.Systems;
|
||||||
using Content.Server.White.ERTRecruitment;
|
using Content.Server.White.ERTRecruitment;
|
||||||
using Content.Server.White.ServerEvent;
|
|
||||||
using Content.Shared.Access.Systems;
|
using Content.Shared.Access.Systems;
|
||||||
using Content.Shared.Administration.Logs;
|
using Content.Shared.Administration.Logs;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
using Content.Shared.White.AuthPanel;
|
using Content.Shared.White.AuthPanel;
|
||||||
using Content.Shared.White.Cyborg.Components;
|
using Content.Shared.White.GhostRecruitment;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
@@ -20,11 +20,12 @@ public sealed class AuthPanelSystem : EntitySystem
|
|||||||
[Dependency] private readonly PopupSystem _popup = default!;
|
[Dependency] private readonly PopupSystem _popup = default!;
|
||||||
[Dependency] private readonly AccessReaderSystem _access = default!;
|
[Dependency] private readonly AccessReaderSystem _access = default!;
|
||||||
[Dependency] private readonly AppearanceSystem _appearance = default!;
|
[Dependency] private readonly AppearanceSystem _appearance = default!;
|
||||||
[Dependency] private readonly ServerEventSystem _event = default!;
|
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly ERTRecruitmentSystem _ert = default!;
|
|
||||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||||
|
[Dependency] private readonly ERTRecruitmentRule _ert = default!;
|
||||||
|
[Dependency] private readonly GameTicker _gameTicker = default!;
|
||||||
|
[Dependency] private readonly StationSystem _station = default!;
|
||||||
|
|
||||||
public Dictionary<AuthPanelAction, HashSet<EntityUid>> Counter = new();
|
public Dictionary<AuthPanelAction, HashSet<EntityUid>> Counter = new();
|
||||||
public Dictionary<AuthPanelAction, HashSet<int>> CardIndexes = new();
|
public Dictionary<AuthPanelAction, HashSet<int>> CardIndexes = new();
|
||||||
@@ -38,10 +39,16 @@ public sealed class AuthPanelSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
SubscribeLocalEvent<AuthPanelComponent,AuthPanelButtonPressedMessage>(OnButtonPressed);
|
SubscribeLocalEvent<AuthPanelComponent,AuthPanelButtonPressedMessage>(OnButtonPressed);
|
||||||
SubscribeLocalEvent<AuthPanelComponent,AuthPanelPerformActionEvent>(OnPerformAction);
|
SubscribeLocalEvent<AuthPanelComponent,AuthPanelPerformActionEvent>(OnPerformAction);
|
||||||
|
SubscribeLocalEvent<RecruitedComponent,ERTRecruitedReasonEvent>(OnReason);
|
||||||
|
|
||||||
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRestart);
|
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRestart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnReason(EntityUid uid, RecruitedComponent component, ERTRecruitedReasonEvent args)
|
||||||
|
{
|
||||||
|
args.Reason = Reason;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnRestart(RoundRestartCleanupEvent ev)
|
private void OnRestart(RoundRestartCleanupEvent ev)
|
||||||
{
|
{
|
||||||
Counter.Clear();
|
Counter.Clear();
|
||||||
@@ -54,15 +61,16 @@ public sealed class AuthPanelSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
if (args.Action is AuthPanelAction.ERTRecruit)
|
if (args.Action is AuthPanelAction.ERTRecruit)
|
||||||
{
|
{
|
||||||
if (_random.Next(0, 10) < 2
|
if (_random.Next(10) < 2)
|
||||||
&& _event.TryStartEvent(ERTRecruitmentSystem.EventName)
|
|
||||||
&& _event.TryGetEvent(ERTRecruitmentSystem.EventName,out var eventPrototype))
|
|
||||||
{
|
{
|
||||||
eventPrototype.Description = Reason;
|
_gameTicker.AddGameRule(ERTRecruitmentRuleComponent.EventName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_ert.DeclineERT();
|
var station = _station.GetStationInMap(Transform(uid).MapID);
|
||||||
|
|
||||||
|
if (station != null)
|
||||||
|
_ert.DeclineERT(station.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var entities in Counter.Values)
|
foreach (var entities in Counter.Values)
|
||||||
@@ -81,9 +89,6 @@ public sealed class AuthPanelSystem : EntitySystem
|
|||||||
if(args.Session.AttachedEntity == null)
|
if(args.Session.AttachedEntity == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(HasComp<CyborgComponent>(args.Session.AttachedEntity))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var access = _access.FindAccessTags(args.Session.AttachedEntity.Value);
|
var access = _access.FindAccessTags(args.Session.AttachedEntity.Value);
|
||||||
|
|
||||||
if (!access.Contains("Command"))
|
if (!access.Contains("Command"))
|
||||||
@@ -168,7 +173,7 @@ public sealed class AuthPanelSystem : EntitySystem
|
|||||||
var state = new AuthPanelConfirmationActionState(action);
|
var state = new AuthPanelConfirmationActionState(action);
|
||||||
var ui = _ui.GetUi(uid, AuthPanelUiKey.Key);
|
var ui = _ui.GetUi(uid, AuthPanelUiKey.Key);
|
||||||
|
|
||||||
UserInterfaceSystem.SetUiState(ui, state);
|
_ui.SetUiState(ui, state);
|
||||||
_appearance.SetData(uid,AuthPanelVisualLayers.Confirm,true);
|
_appearance.SetData(uid,AuthPanelVisualLayers.Confirm,true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,16 +16,16 @@ public sealed class BlockERT : IConsoleCommand
|
|||||||
public string Help => "blockert <true/false>";
|
public string Help => "blockert <true/false>";
|
||||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||||
{
|
{
|
||||||
var ertsys = _entities.System<ERTRecruitmentSystem>();
|
var ertsys = _entities.System<ERTRecruitmentRule>();
|
||||||
var isBlocked = !ertsys.IsBlocked;
|
var isDisabled = !ertsys.IsDisabled;
|
||||||
|
|
||||||
if (args.Length > 0)
|
if (args.Length > 0)
|
||||||
{
|
{
|
||||||
isBlocked = args[0] == "true";
|
isDisabled = args[0] == "true";
|
||||||
}
|
}
|
||||||
|
|
||||||
ertsys.IsBlocked = isBlocked;
|
ertsys.IsDisabled = isDisabled;
|
||||||
var message = isBlocked ? "ERT is blocked!" : "ERT is no longer blocked!";
|
var message = isDisabled ? "ERT is blocked!" : "ERT is no longer blocked!";
|
||||||
shell.WriteLine(message);
|
shell.WriteLine(message);
|
||||||
_chatManager.SendAdminAnnouncement(message);
|
_chatManager.SendAdminAnnouncement(message);
|
||||||
}
|
}
|
||||||
|
|||||||
16
Content.Server/White/ERTRecruitment/ERTMapComponent.cs
Normal file
16
Content.Server/White/ERTRecruitment/ERTMapComponent.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using Robust.Shared.Map;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Server.White.ERTRecruitment;
|
||||||
|
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed partial class ERTMapComponent : Component
|
||||||
|
{
|
||||||
|
[ViewVariables]
|
||||||
|
public MapId? MapId;
|
||||||
|
[ViewVariables]
|
||||||
|
public EntityUid? Shuttle;
|
||||||
|
|
||||||
|
public static ResPath OutpostMap = new("/Maps/ERT/ERTStation.yml");
|
||||||
|
public static ResPath ShuttleMap = new("/Maps/ERT/ERTShuttle.yml");
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
namespace Content.Server.White.ERTRecruitment;
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public sealed class ERTRecruitedReasonEvent : EntityEventArgs
|
||||||
|
{
|
||||||
|
public string Reason = "";
|
||||||
|
|
||||||
|
public void SetReason(string reason)
|
||||||
|
{
|
||||||
|
Reason = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
193
Content.Server/White/ERTRecruitment/ERTRecruitmentRule.cs
Normal file
193
Content.Server/White/ERTRecruitment/ERTRecruitmentRule.cs
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using System.Numerics;
|
||||||
|
using Content.Server.Chat.Managers;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
|
using Content.Server.GameTicking;
|
||||||
|
using Content.Server.GameTicking.Rules.Components;
|
||||||
|
using Content.Server.Shuttles.Components;
|
||||||
|
using Content.Server.Shuttles.Systems;
|
||||||
|
using Content.Server.StationEvents.Events;
|
||||||
|
using Content.Server.White.GhostRecruitment;
|
||||||
|
using Content.Shared.CCVar;
|
||||||
|
using Content.Shared.White;
|
||||||
|
using Content.Shared.White.GhostRecruitment;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Server.Maps;
|
||||||
|
using Robust.Shared.Configuration;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
|
||||||
|
namespace Content.Server.White.ERTRecruitment;
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
public sealed class ERTRecruitmentRule : StationEventSystem<ERTRecruitmentRuleComponent>
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IChatManager _chat = default!;
|
||||||
|
[Dependency] private readonly GhostRecruitmentSystem _recruitment = default!;
|
||||||
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
|
[Dependency] private readonly MapLoaderSystem _map = default!;
|
||||||
|
[Dependency] private readonly ShuttleSystem _shuttle = default!;
|
||||||
|
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
||||||
|
[Dependency] private readonly IConfigurationManager _cfgManager = default!;
|
||||||
|
|
||||||
|
private ISawmill _logger = default!;
|
||||||
|
|
||||||
|
public bool IsDisabled = false;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
_logger = Logger.GetSawmill("ERTRecruit");
|
||||||
|
SubscribeLocalEvent<RoundStartAttemptEvent>(OnStartAttempt);
|
||||||
|
SubscribeLocalEvent<RecruitedComponent,GhostRecruitmentSuccessEvent>(OnRecruitmentSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Added(EntityUid uid, ERTRecruitmentRuleComponent component, GameRuleComponent gameRule, GameRuleAddedEvent args)
|
||||||
|
{
|
||||||
|
base.Added(uid, component, gameRule, args);
|
||||||
|
|
||||||
|
if (TryGetRandomStation(out var stationUid))
|
||||||
|
{
|
||||||
|
component.TargetStation = stationUid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsDisabled)
|
||||||
|
{
|
||||||
|
if (component.TargetStation != null)
|
||||||
|
DeclineERT(component.TargetStation.Value);
|
||||||
|
|
||||||
|
component.IsBlocked = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var query = EntityQueryEnumerator<ERTMapComponent>();
|
||||||
|
if (query.MoveNext(out uid, out var ertMapComponent))
|
||||||
|
{
|
||||||
|
component.Outpost = uid;
|
||||||
|
component.Shuttle = ertMapComponent.Shuttle;
|
||||||
|
component.MapId = ertMapComponent.MapId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Started(EntityUid uid, ERTRecruitmentRuleComponent component, GameRuleComponent gameRule,
|
||||||
|
GameRuleStartedEvent args)
|
||||||
|
{
|
||||||
|
base.Started(uid, component, gameRule, args);
|
||||||
|
_logger.Debug("Event is started");
|
||||||
|
|
||||||
|
if (component.TargetStation == null || component.IsBlocked)
|
||||||
|
{
|
||||||
|
ForceEndSelf(uid,gameRule);
|
||||||
|
_logger.Debug("oopsie doopsie we make a poopie poopie on starting event!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_recruitment.GetEventSpawners(ERTRecruitmentRuleComponent.EventName).Count() < component.MinPlayer)
|
||||||
|
{
|
||||||
|
_logger.Error("Not enough spawners!");
|
||||||
|
|
||||||
|
DeclineERT(component.TargetStation.Value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_chatSystem.DispatchStationAnnouncement(component.TargetStation.Value,Loc.GetString("ert-wait-message"),colorOverride: Color.Gold);
|
||||||
|
|
||||||
|
if (TryComp<ShuttleComponent>(component.Shuttle, out var shuttle) && component.Outpost != null)
|
||||||
|
{
|
||||||
|
_shuttle.TryFTLDock(component.Shuttle.Value, shuttle, component.Outpost.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
_recruitment.StartRecruitment(ERTRecruitmentRuleComponent.EventName);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Ended(EntityUid uid, ERTRecruitmentRuleComponent component, GameRuleComponent gameRule, GameRuleEndedEvent args)
|
||||||
|
{
|
||||||
|
base.Ended(uid, component, gameRule, args);
|
||||||
|
|
||||||
|
if (component.IsBlocked || _recruitment.GetAllRecruited(ERTRecruitmentRuleComponent.EventName).Count() < component.MinPlayer ||
|
||||||
|
!_recruitment.EndRecruitment(ERTRecruitmentRuleComponent.EventName))
|
||||||
|
{
|
||||||
|
if (component.TargetStation != null)
|
||||||
|
DeclineERT(component.TargetStation.Value);
|
||||||
|
_recruitment.Cleanup(ERTRecruitmentRuleComponent.EventName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (component.TargetStation != null)
|
||||||
|
AcceptERT(component.TargetStation.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRecruitmentSuccess(EntityUid uid, RecruitedComponent component, GhostRecruitmentSuccessEvent args)
|
||||||
|
{
|
||||||
|
var ev = new ERTRecruitedReasonEvent();
|
||||||
|
RaiseLocalEvent(uid,ev);
|
||||||
|
|
||||||
|
_chat.DispatchServerMessage(args.PlayerSession,Loc.GetString("ert-description"));
|
||||||
|
_chat.DispatchServerMessage(args.PlayerSession, Loc.GetString("ert-reason", ("reason", ev.Reason)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStartAttempt(RoundStartAttemptEvent ev)
|
||||||
|
{
|
||||||
|
if(_cfgManager.GetCVar(WhiteCVars.LoadERTMap))
|
||||||
|
SpawnMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void AcceptERT(EntityUid targetStation)
|
||||||
|
{
|
||||||
|
_chatSystem.DispatchStationAnnouncement(targetStation,Loc.GetString("ert-accept-message"),
|
||||||
|
colorOverride: Color.Gold,announcementSound:ERTRecruitmentRuleComponent.ERTYes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeclineERT(EntityUid targetStation)
|
||||||
|
{
|
||||||
|
_chatSystem.DispatchStationAnnouncement(targetStation,Loc.GetString("ert-deny-message"),
|
||||||
|
colorOverride: Color.Gold,announcementSound:ERTRecruitmentRuleComponent.ERTNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool SpawnMap()
|
||||||
|
{
|
||||||
|
_logger.Debug($"Loading maps!");
|
||||||
|
|
||||||
|
var mapId = _mapManager.CreateMap();
|
||||||
|
var options = new MapLoadOptions
|
||||||
|
{
|
||||||
|
LoadMap = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!_map.TryLoad(mapId, ERTMapComponent.OutpostMap.ToString(), out var outpostGrids, options) || outpostGrids.Count == 0)
|
||||||
|
{
|
||||||
|
_logger.Error( $"Error loading map {ERTMapComponent.OutpostMap}!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_logger.Debug($"Loaded map {ERTMapComponent.OutpostMap} on {mapId}!");
|
||||||
|
|
||||||
|
// Assume the first grid is the outpost grid.
|
||||||
|
var outpost = outpostGrids[0];
|
||||||
|
|
||||||
|
// Listen I just don't want it to overlap.
|
||||||
|
if (!_map.TryLoad(mapId, ERTMapComponent.ShuttleMap.ToString(), out var grids, new MapLoadOptions {Offset = Vector2.One * 1000f}) || !grids.Any())
|
||||||
|
{
|
||||||
|
_logger.Error( $"Error loading grid {ERTMapComponent.ShuttleMap}!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_logger.Debug($"Loaded shuttle {ERTMapComponent.ShuttleMap} on {mapId}!");
|
||||||
|
|
||||||
|
var shuttleId = grids.First();
|
||||||
|
|
||||||
|
// Naughty, someone saved the shuttle as a map.
|
||||||
|
if (Deleted(shuttleId))
|
||||||
|
{
|
||||||
|
_logger.Error( $"Tried to load shuttle as a map, aborting.");
|
||||||
|
_mapManager.DeleteMap(mapId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ERTMap = EnsureComp<ERTMapComponent>(outpost);
|
||||||
|
ERTMap.MapId = mapId;
|
||||||
|
ERTMap.Shuttle = shuttleId;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using Robust.Shared.Audio;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Server.White.ERTRecruitment;
|
||||||
|
|
||||||
|
[RegisterComponent, Access(typeof(ERTRecruitmentRule))]
|
||||||
|
public sealed partial class ERTRecruitmentRuleComponent : Component
|
||||||
|
{
|
||||||
|
public static string EventName = "ERTRecruitment";
|
||||||
|
[ViewVariables]
|
||||||
|
public MapId? MapId = null;
|
||||||
|
|
||||||
|
[DataField("minPlayer")] public int MinPlayer = 4;
|
||||||
|
|
||||||
|
public static SoundSpecifier ERTYes = new SoundPathSpecifier("/Audio/Announcements/ert_yes.ogg");
|
||||||
|
public static SoundSpecifier ERTNo = new SoundPathSpecifier("/Audio/Announcements/ert_no.ogg");
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
public bool IsBlocked = false;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
public EntityUid? Outpost;
|
||||||
|
[ViewVariables]
|
||||||
|
public EntityUid? Shuttle;
|
||||||
|
[ViewVariables]
|
||||||
|
public EntityUid? TargetStation;
|
||||||
|
}
|
||||||
@@ -1,213 +0,0 @@
|
|||||||
using System.Linq;
|
|
||||||
using System.Numerics;
|
|
||||||
using Content.Server.Chat.Managers;
|
|
||||||
using Content.Server.Chat.Systems;
|
|
||||||
using Content.Server.GameTicking;
|
|
||||||
using Content.Server.Shuttles.Components;
|
|
||||||
using Content.Server.Shuttles.Systems;
|
|
||||||
using Content.Server.Station.Systems;
|
|
||||||
using Content.Server.White.GhostRecruitment;
|
|
||||||
using Content.Server.White.ServerEvent;
|
|
||||||
using Content.Shared.GameTicking;
|
|
||||||
using Content.Shared.White.GhostRecruitment;
|
|
||||||
using Content.Shared.White.ServerEvent;
|
|
||||||
using Robust.Server.GameObjects;
|
|
||||||
using Robust.Server.Maps;
|
|
||||||
using Robust.Shared.Audio;
|
|
||||||
using Robust.Shared.Map;
|
|
||||||
using Robust.Shared.Utility;
|
|
||||||
|
|
||||||
namespace Content.Server.White.ERTRecruitment;
|
|
||||||
|
|
||||||
public sealed class ERTRecruitmentSystem : EntitySystem
|
|
||||||
{
|
|
||||||
public static string EventName = "ERTRecruitment";
|
|
||||||
private ISawmill _logger = default!;
|
|
||||||
private MapId? _mapId = null;
|
|
||||||
|
|
||||||
public ResPath OutpostMap = new("/Maps/ERT/ERTStation.yml");
|
|
||||||
public ResPath ShuttleMap = new("/Maps/ERT/ERTShuttle.yml");
|
|
||||||
|
|
||||||
public SoundSpecifier ERTYes = new SoundPathSpecifier("/Audio/Announcements/ert_yes.ogg");
|
|
||||||
public SoundSpecifier ERTNo = new SoundPathSpecifier("/Audio/Announcements/ert_no.ogg");
|
|
||||||
|
|
||||||
public bool IsBlocked = false;
|
|
||||||
|
|
||||||
public EntityUid? Outpost;
|
|
||||||
public EntityUid? Shuttle;
|
|
||||||
public EntityUid? TargetStation;
|
|
||||||
|
|
||||||
[Dependency] private readonly ServerEventSystem _event = default!;
|
|
||||||
[Dependency] private readonly IChatManager _chat = default!;
|
|
||||||
[Dependency] private readonly GhostRecruitmentSystem _recruitment = default!;
|
|
||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
|
||||||
[Dependency] private readonly MapLoaderSystem _map = default!;
|
|
||||||
[Dependency] private readonly ShuttleSystem _shuttle = default!;
|
|
||||||
[Dependency] private readonly StationSystem _station = default!;
|
|
||||||
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
|
||||||
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
_logger = Logger.GetSawmill(EventName);
|
|
||||||
SubscribeLocalEvent<RoundStartAttemptEvent>(OnRoundStart);
|
|
||||||
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundEnd);
|
|
||||||
SubscribeLocalEvent<RecruitedComponent,GhostRecruitmentSuccessEvent>(OnRecruitmentSuccess);
|
|
||||||
|
|
||||||
SubscribeLocalEvent<EventStarted>(OnEventStart);
|
|
||||||
SubscribeLocalEvent<EventEnded>(OnEventEnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnEventEnd(EventEnded ev)
|
|
||||||
{
|
|
||||||
if(ev.EventName != EventName)
|
|
||||||
return;
|
|
||||||
EventEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnEventStart(EventStarted ev)
|
|
||||||
{
|
|
||||||
if(ev.EventName != EventName)
|
|
||||||
return;
|
|
||||||
EventStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnRoundEnd(RoundRestartCleanupEvent ev)
|
|
||||||
{
|
|
||||||
Outpost = null;
|
|
||||||
Shuttle = null;
|
|
||||||
TargetStation = null;
|
|
||||||
|
|
||||||
_mapId = null;
|
|
||||||
_logger.Debug("Deleted map");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnRecruitmentSuccess(EntityUid uid, RecruitedComponent component, GhostRecruitmentSuccessEvent args)
|
|
||||||
{
|
|
||||||
if(args.RecruitmentName != EventName || !_event.TryGetEvent(EventName, out var prototype))
|
|
||||||
return;
|
|
||||||
|
|
||||||
_chat.DispatchServerMessage(args.PlayerSession,Loc.GetString("ert-description"));
|
|
||||||
_chat.DispatchServerMessage(args.PlayerSession, Loc.GetString("ert-reason",("reason",prototype.Description)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void OnRoundStart(RoundStartAttemptEvent ev)
|
|
||||||
{
|
|
||||||
var stations = _station.GetStations();
|
|
||||||
if (stations.Count > 0)
|
|
||||||
{
|
|
||||||
TargetStation = stations[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
SpawnMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void EventStart()
|
|
||||||
{
|
|
||||||
if(TargetStation == null || IsBlocked)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!_event.TryGetEvent(EventName, out var prototype) ||
|
|
||||||
_recruitment.GetEventSpawners(EventName).Count() < prototype.MinPlayer)
|
|
||||||
{
|
|
||||||
_logger.Error("Not enough spawners!");
|
|
||||||
_event.BreakEvent(EventName);
|
|
||||||
DeclineERT();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_chatSystem.DispatchStationAnnouncement(TargetStation.Value,Loc.GetString("ert-wait-message"),colorOverride: Color.Gold);
|
|
||||||
|
|
||||||
if (TryComp<ShuttleComponent>(Shuttle, out var shuttle) && Outpost != null)
|
|
||||||
{
|
|
||||||
_shuttle.TryFTLDock(Shuttle.Value, shuttle, Outpost.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
_recruitment.StartRecruitment(EventName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void EventEnd()
|
|
||||||
{
|
|
||||||
if (!_event.TryGetEvent(EventName, out var prototype) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_recruitment.GetAllRecruited(EventName).Count() < prototype.MinPlayer ||
|
|
||||||
!_recruitment.EndRecruitment(EventName))
|
|
||||||
{
|
|
||||||
DeclineERT();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AcceptERT();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AcceptERT()
|
|
||||||
{
|
|
||||||
if(TargetStation == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_chatSystem.DispatchStationAnnouncement(TargetStation.Value,Loc.GetString("ert-accept-message"),
|
|
||||||
colorOverride: Color.Gold,announcementSound:ERTYes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DeclineERT()
|
|
||||||
{
|
|
||||||
if(TargetStation == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_chatSystem.DispatchStationAnnouncement(TargetStation.Value,Loc.GetString("ert-deny-message"),
|
|
||||||
colorOverride: Color.Gold,announcementSound:ERTNo);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool SpawnMap()
|
|
||||||
{
|
|
||||||
_logger.Debug($"Loading maps!");
|
|
||||||
if (_mapId != null)
|
|
||||||
{
|
|
||||||
// The map is already loaded, so there is no point in loading further
|
|
||||||
_logger.Debug("Map is already loaded " + _mapId);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var mapId = _mapManager.CreateMap();
|
|
||||||
var options = new MapLoadOptions
|
|
||||||
{
|
|
||||||
LoadMap = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!_map.TryLoad(mapId, OutpostMap.ToString(), out var outpostGrids, options) || outpostGrids.Count == 0)
|
|
||||||
{
|
|
||||||
_logger.Error( $"Error loading map {OutpostMap}!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
_logger.Debug($"Loaded map {OutpostMap} on {mapId}!");
|
|
||||||
|
|
||||||
// Assume the first grid is the outpost grid.
|
|
||||||
Outpost = outpostGrids[0];
|
|
||||||
|
|
||||||
// Listen I just don't want it to overlap.
|
|
||||||
if (!_map.TryLoad(mapId, ShuttleMap.ToString(), out var grids, new MapLoadOptions {Offset = Vector2.One * 1000f}) || !grids.Any())
|
|
||||||
{
|
|
||||||
_logger.Error( $"Error loading grid {ShuttleMap}!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
_logger.Debug($"Loaded shuttle {ShuttleMap} on {mapId}!");
|
|
||||||
|
|
||||||
var shuttleId = grids.First();
|
|
||||||
|
|
||||||
// Naughty, someone saved the shuttle as a map.
|
|
||||||
if (Deleted(shuttleId))
|
|
||||||
{
|
|
||||||
_logger.Error( $"Tried to load shuttle as a map, aborting.");
|
|
||||||
_mapManager.DeleteMap(mapId);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_mapId = mapId;
|
|
||||||
Shuttle = shuttleId;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
using Robust.Server.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Serialization;
|
|
||||||
|
|
||||||
namespace Content.Server.White.GhostRecruitment;
|
namespace Content.Server.White.GhostRecruitment;
|
||||||
|
|
||||||
@@ -7,9 +6,9 @@ namespace Content.Server.White.GhostRecruitment;
|
|||||||
public sealed class GhostRecruitmentSuccessEvent : EntityEventArgs
|
public sealed class GhostRecruitmentSuccessEvent : EntityEventArgs
|
||||||
{
|
{
|
||||||
public string RecruitmentName;
|
public string RecruitmentName;
|
||||||
public IPlayerSession PlayerSession;
|
public ICommonSession PlayerSession;
|
||||||
|
|
||||||
public GhostRecruitmentSuccessEvent(string recruitmentName, IPlayerSession playerSession)
|
public GhostRecruitmentSuccessEvent(string recruitmentName, ICommonSession playerSession)
|
||||||
{
|
{
|
||||||
RecruitmentName = recruitmentName;
|
RecruitmentName = recruitmentName;
|
||||||
PlayerSession = playerSession;
|
PlayerSession = playerSession;
|
||||||
|
|||||||
@@ -4,9 +4,12 @@ using Content.Server.Ghost.Components;
|
|||||||
using Content.Server.Humanoid.Components;
|
using Content.Server.Humanoid.Components;
|
||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
using Content.Server.Players;
|
using Content.Server.Players;
|
||||||
|
using Content.Shared.Ghost;
|
||||||
|
using Content.Shared.Players;
|
||||||
using Content.Shared.White.GhostRecruitment;
|
using Content.Shared.White.GhostRecruitment;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
namespace Content.Server.White.GhostRecruitment;
|
namespace Content.Server.White.GhostRecruitment;
|
||||||
@@ -19,7 +22,7 @@ public sealed class GhostRecruitmentSystem : EntitySystem
|
|||||||
[Dependency] private readonly EuiManager _eui = default!;
|
[Dependency] private readonly EuiManager _eui = default!;
|
||||||
[Dependency] private readonly MindSystem _mind = default!;
|
[Dependency] private readonly MindSystem _mind = default!;
|
||||||
|
|
||||||
private readonly Dictionary<IPlayerSession, GhostRecruitmentEuiAccept> _openUis = new();
|
private readonly Dictionary<ICommonSession, GhostRecruitmentEuiAccept> _openUis = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// starts recruiting ghosts, showing them a menu with a choice to recruit.
|
/// starts recruiting ghosts, showing them a menu with a choice to recruit.
|
||||||
@@ -51,8 +54,6 @@ public sealed class GhostRecruitmentSystem : EntitySystem
|
|||||||
/// <returns>is success?</returns>
|
/// <returns>is success?</returns>
|
||||||
public bool EndRecruitment(string recruitmentName)
|
public bool EndRecruitment(string recruitmentName)
|
||||||
{
|
{
|
||||||
var query = EntityQueryEnumerator<GhostRecruitedComponent>();
|
|
||||||
|
|
||||||
var spawners = GetEventSpawners(recruitmentName).ToList();
|
var spawners = GetEventSpawners(recruitmentName).ToList();
|
||||||
|
|
||||||
// We prioritize the queue, for example, the commander first, and then the engineer
|
// We prioritize the queue, for example, the commander first, and then the engineer
|
||||||
@@ -60,29 +61,16 @@ public sealed class GhostRecruitmentSystem : EntitySystem
|
|||||||
|
|
||||||
var count = 0;
|
var count = 0;
|
||||||
|
|
||||||
var attemptRecruitment = new GhostRecruitmentAttemptEvent(recruitmentName);
|
var query = EntityQueryEnumerator<GhostRecruitedComponent>();
|
||||||
RaiseLocalEvent(attemptRecruitment);
|
|
||||||
|
|
||||||
if (attemptRecruitment.Cancelled)
|
|
||||||
{
|
|
||||||
var failEvent = new GhostsRecruitmentFailEvent(recruitmentName);
|
|
||||||
RaiseLocalEvent(failEvent);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (query.MoveNext(out var uid,out var ghostRecruitedComponent))
|
while (query.MoveNext(out var uid,out var ghostRecruitedComponent))
|
||||||
{
|
{
|
||||||
if(ghostRecruitedComponent.RecruitmentName != recruitmentName)
|
if(ghostRecruitedComponent.RecruitmentName != recruitmentName)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
RemComp<GhostRecruitedComponent>(uid);
|
|
||||||
|
|
||||||
if (!TryComp<ActorComponent>(uid, out var actorComponent))
|
if (!TryComp<ActorComponent>(uid, out var actorComponent))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CloseEui(uid,recruitmentName,actorComponent);
|
|
||||||
|
|
||||||
// if there are too many recruited, then just skip
|
// if there are too many recruited, then just skip
|
||||||
if(count >= spawners.Count)
|
if(count >= spawners.Count)
|
||||||
continue;
|
continue;
|
||||||
@@ -100,9 +88,26 @@ public sealed class GhostRecruitmentSystem : EntitySystem
|
|||||||
|
|
||||||
var ghostsEvent = new GhostsRecruitmentSuccessEvent(recruitmentName);
|
var ghostsEvent = new GhostsRecruitmentSuccessEvent(recruitmentName);
|
||||||
RaiseLocalEvent(ghostsEvent);
|
RaiseLocalEvent(ghostsEvent);
|
||||||
|
|
||||||
|
Cleanup(recruitmentName);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Cleanup(string recruitmentName)
|
||||||
|
{
|
||||||
|
ClearEui(recruitmentName);
|
||||||
|
|
||||||
|
var query = EntityQueryEnumerator<GhostRecruitedComponent>();
|
||||||
|
|
||||||
|
while (query.MoveNext(out var uid, out var ghostRecruitedComponent))
|
||||||
|
{
|
||||||
|
if (ghostRecruitedComponent.RecruitmentName != recruitmentName)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
RemComp<GhostRecruitedComponent>(uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void TransferMind(EntityUid from,EntityUid spawnerUid,GhostRecruitmentSpawnPointComponent? component = null)
|
private void TransferMind(EntityUid from,EntityUid spawnerUid,GhostRecruitmentSpawnPointComponent? component = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(spawnerUid, ref component) || !TryComp<ActorComponent>(from,out var actorComponent))
|
if (!Resolve(spawnerUid, ref component) || !TryComp<ActorComponent>(from,out var actorComponent))
|
||||||
@@ -112,10 +117,14 @@ public sealed class GhostRecruitmentSystem : EntitySystem
|
|||||||
|
|
||||||
if(!entityUid.HasValue)
|
if(!entityUid.HasValue)
|
||||||
return;
|
return;
|
||||||
var mind = actorComponent.PlayerSession.GetMind()!;
|
|
||||||
|
|
||||||
_mind.TransferTo(mind,entityUid.Value);
|
var mind = actorComponent.PlayerSession.GetMind();
|
||||||
_mind.UnVisit(mind);
|
|
||||||
|
if (!mind.HasValue)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_mind.TransferTo(mind.Value, entityUid.Value);
|
||||||
|
_mind.UnVisit(mind.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private EntityUid? Spawn(EntityUid spawnerUid,GhostRecruitmentSpawnPointComponent? component = null)
|
private EntityUid? Spawn(EntityUid spawnerUid,GhostRecruitmentSpawnPointComponent? component = null)
|
||||||
@@ -159,20 +168,32 @@ public sealed class GhostRecruitmentSystem : EntitySystem
|
|||||||
return;
|
return;
|
||||||
var eui = new GhostRecruitmentEuiAccept(uid, recruitmentName, this);
|
var eui = new GhostRecruitmentEuiAccept(uid, recruitmentName, this);
|
||||||
|
|
||||||
_openUis.Add(actorComponent.PlayerSession,eui);
|
Logger.Debug("Added EUI to "+ uid);
|
||||||
_eui.OpenEui(eui,actorComponent.PlayerSession);
|
if(_openUis.TryAdd(actorComponent.PlayerSession,eui))
|
||||||
|
_eui.OpenEui(eui,actorComponent.PlayerSession);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearEui(string recruitmentName)
|
||||||
|
{
|
||||||
|
foreach (var (session,eui) in _openUis)
|
||||||
|
{
|
||||||
|
if (session.AttachedEntity != null)
|
||||||
|
CloseEui(session.AttachedEntity.Value, recruitmentName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CloseEui(EntityUid uid,string recruitmentName,ActorComponent? actorComponent = null)
|
public void CloseEui(EntityUid uid,string recruitmentName,ActorComponent? actorComponent = null)
|
||||||
{
|
{
|
||||||
if(!Resolve(uid,ref actorComponent))
|
if (!Resolve(uid, ref actorComponent))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
var session = actorComponent.PlayerSession;
|
var session = actorComponent.PlayerSession;
|
||||||
|
|
||||||
if (!_openUis.ContainsKey(session))
|
if (!_openUis.ContainsKey(session))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Logger.Debug("Removed EUI from "+ uid);
|
||||||
_openUis.Remove(session, out var eui);
|
_openUis.Remove(session, out var eui);
|
||||||
|
|
||||||
eui?.Close();
|
eui?.Close();
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
using Content.Server.Administration;
|
|
||||||
using Content.Shared.Administration;
|
|
||||||
using Content.Shared.White.ServerEvent;
|
|
||||||
using Robust.Shared.Console;
|
|
||||||
|
|
||||||
namespace Content.Server.White.ServerEvent.Commands;
|
|
||||||
|
|
||||||
[AdminCommand(AdminFlags.Admin)]
|
|
||||||
public sealed class StartServerEvent : IConsoleCommand
|
|
||||||
{
|
|
||||||
[Dependency] private readonly IEntityManager _entities = default!;
|
|
||||||
|
|
||||||
public string Command => "startevent";
|
|
||||||
public string Description => "starting a new event";
|
|
||||||
public string Help => "startevent <event>";
|
|
||||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length < 1)
|
|
||||||
{
|
|
||||||
shell.WriteError("Not enough args!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!_entities.System<ServerEventSystem>().TryStartEvent(args[0]))
|
|
||||||
shell.WriteError("Oopsie! error on starting event!");
|
|
||||||
else
|
|
||||||
shell.WriteLine("Done!");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
|
||||||
{
|
|
||||||
return CompletionResult.FromHintOptions(CompletionHelper.PrototypeIDs<ServerEventPrototype>(),
|
|
||||||
"<serverEventPrototype>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using Content.Server.GameTicking;
|
|
||||||
using Content.Shared.GameTicking;
|
|
||||||
using Content.Shared.White.ServerEvent;
|
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
using Robust.Shared.Timing;
|
|
||||||
|
|
||||||
namespace Content.Server.White.ServerEvent;
|
|
||||||
|
|
||||||
public sealed class ServerEventSystem : EntitySystem
|
|
||||||
{
|
|
||||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
|
||||||
[Dependency] private readonly GameTicker _gameTicker = default!;
|
|
||||||
|
|
||||||
private readonly Dictionary<string,ServerEventPrototype> _eventCache = new();
|
|
||||||
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnEnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnEnd(RoundRestartCleanupEvent ev)
|
|
||||||
{
|
|
||||||
foreach (var eventPrototype in GetActiveEvents())
|
|
||||||
{
|
|
||||||
BreakEvent(eventPrototype);
|
|
||||||
}
|
|
||||||
|
|
||||||
_eventCache.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryGetEvent(string eventName,[MaybeNullWhen(false)] out ServerEventPrototype prototype)
|
|
||||||
{
|
|
||||||
if (!_eventCache.TryGetValue(eventName, out prototype))
|
|
||||||
{
|
|
||||||
if (!_prototype.TryIndex(eventName, out prototype))
|
|
||||||
{
|
|
||||||
Logger.Debug("Failed load " + eventName);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Logger.Debug("Caching " + eventName);
|
|
||||||
_eventCache.Add(eventName,prototype);
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.Debug("Successful get " + eventName);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsEventRunning(string eventName)
|
|
||||||
{
|
|
||||||
if (!TryGetEvent(eventName, out var prototype))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return IsEventRunning(prototype);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsEventRunning(ServerEventPrototype prototype)
|
|
||||||
{
|
|
||||||
return prototype.EndPlayerGatherTime.HasValue && !prototype.IsBreak;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<ServerEventPrototype> GetActiveEvents()
|
|
||||||
{
|
|
||||||
foreach (var (_,prototype) in _eventCache)
|
|
||||||
{
|
|
||||||
if (IsEventRunning(prototype))
|
|
||||||
yield return prototype;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void BreakEvent(string eventName)
|
|
||||||
{
|
|
||||||
if(!TryGetEvent(eventName,out var prototype))
|
|
||||||
return;
|
|
||||||
BreakEvent(prototype);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void BreakEvent(ServerEventPrototype prototype)
|
|
||||||
{
|
|
||||||
Logger.Debug("Event is break! " + prototype.ID);
|
|
||||||
prototype.CurrentPlayerGatherTime = null;
|
|
||||||
prototype.EndPlayerGatherTime = null;
|
|
||||||
prototype.IsBreak = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryStartEvent(string eventName)
|
|
||||||
{
|
|
||||||
if (!TryGetEvent(eventName, out var prototype) || IsEventRunning(prototype) || _gameTicker.RunLevel != GameRunLevel.InRound)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
prototype.IsBreak = false;
|
|
||||||
prototype.EndPlayerGatherTime = _timing.CurTime + prototype.PlayerGatherTime;
|
|
||||||
|
|
||||||
Logger.Debug("Event is started " + eventName);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
|
||||||
{
|
|
||||||
base.Update(frameTime);
|
|
||||||
|
|
||||||
foreach (var prototype in GetActiveEvents())
|
|
||||||
{
|
|
||||||
if (!prototype.CurrentPlayerGatherTime.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Started with " + prototype.CurrentPlayerGatherTime + " " + prototype.EndPlayerGatherTime + " " + prototype.IsBreak );
|
|
||||||
RaiseLocalEvent(new EventStarted(prototype.ID));
|
|
||||||
prototype.OnStart?.Execute(prototype);
|
|
||||||
}
|
|
||||||
prototype.CurrentPlayerGatherTime = _timing.CurTime;
|
|
||||||
|
|
||||||
if (prototype.CurrentPlayerGatherTime > prototype.EndPlayerGatherTime)
|
|
||||||
{
|
|
||||||
prototype.OnEnd?.Execute(prototype);
|
|
||||||
RaiseLocalEvent(new EventEnded(prototype.ID));
|
|
||||||
Logger.Debug("Ended with " + prototype.CurrentPlayerGatherTime + " " + prototype.EndPlayerGatherTime + " " + prototype.IsBreak );
|
|
||||||
BreakEvent(prototype);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
namespace Content.Shared.White.AuthPanel;
|
namespace Content.Shared.White.AuthPanel;
|
||||||
|
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed class AuthPanelComponent : Component
|
public sealed partial class AuthPanelComponent : Component
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ namespace Content.Shared.White.GhostRecruitment;
|
|||||||
|
|
||||||
//this for ghosts
|
//this for ghosts
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed class GhostRecruitedComponent : Component
|
public sealed partial class GhostRecruitedComponent : Component
|
||||||
{
|
{
|
||||||
[DataField("recruitmentName")]
|
[DataField("recruitmentName")]
|
||||||
public string RecruitmentName = "default";
|
public string RecruitmentName = "default";
|
||||||
|
|||||||
@@ -13,27 +13,6 @@ public sealed class GhostsRecruitmentSuccessEvent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable,NetSerializable]
|
|
||||||
public sealed class GhostsRecruitmentFailEvent
|
|
||||||
{
|
|
||||||
public string RecruitmentName;
|
|
||||||
|
|
||||||
public GhostsRecruitmentFailEvent(string recruitmentName)
|
|
||||||
{
|
|
||||||
RecruitmentName = recruitmentName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable,NetSerializable]
|
|
||||||
public sealed class GhostRecruitmentAttemptEvent : CancelableEventArgs
|
|
||||||
{
|
|
||||||
public string RecruitmentName;
|
|
||||||
|
|
||||||
public GhostRecruitmentAttemptEvent(string recruitmentName)
|
|
||||||
{
|
|
||||||
RecruitmentName = recruitmentName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Serializable,NetSerializable]
|
[Serializable,NetSerializable]
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototy
|
|||||||
namespace Content.Shared.White.GhostRecruitment;
|
namespace Content.Shared.White.GhostRecruitment;
|
||||||
|
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed class GhostRecruitmentSpawnPointComponent : Component
|
public sealed partial class GhostRecruitmentSpawnPointComponent : Component
|
||||||
{
|
{
|
||||||
[DataField("prototype", customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>),required:true)]
|
[DataField("prototype", customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>),required:true)]
|
||||||
public string EntityPrototype = default!;
|
public string EntityPrototype = default!;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ namespace Content.Shared.White.GhostRecruitment;
|
|||||||
|
|
||||||
// this for spawned prototype
|
// this for spawned prototype
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed class RecruitedComponent : Component
|
public sealed partial class RecruitedComponent : Component
|
||||||
{
|
{
|
||||||
[DataField("recruitmentName")]
|
[DataField("recruitmentName")]
|
||||||
public string RecruitmentName = "default";
|
public string RecruitmentName = "default";
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace Content.Shared.White.ServerEvent.Data;
|
|
||||||
|
|
||||||
[ImplicitDataDefinitionForInheritors]
|
|
||||||
public interface IEventAction
|
|
||||||
{
|
|
||||||
void Execute(ServerEventPrototype prototype);
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
using Robust.Shared.Serialization;
|
|
||||||
|
|
||||||
namespace Content.Shared.White.ServerEvent;
|
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
|
||||||
public sealed class EventStarted
|
|
||||||
{
|
|
||||||
public string EventName;
|
|
||||||
|
|
||||||
public EventStarted(string eventName)
|
|
||||||
{
|
|
||||||
EventName = eventName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
|
||||||
public sealed class EventEnded
|
|
||||||
{
|
|
||||||
public string EventName;
|
|
||||||
|
|
||||||
public EventEnded(string eventName)
|
|
||||||
{
|
|
||||||
EventName = eventName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
using Content.Shared.White.ServerEvent.Data;
|
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
|
||||||
|
|
||||||
namespace Content.Shared.White.ServerEvent;
|
|
||||||
|
|
||||||
[Prototype("serverEvent")]
|
|
||||||
public sealed class ServerEventPrototype : IPrototype
|
|
||||||
{
|
|
||||||
[IdDataField]
|
|
||||||
public string ID { get; } = default!;
|
|
||||||
|
|
||||||
[DataField("name")]
|
|
||||||
public string Name { get; } = string.Empty;
|
|
||||||
|
|
||||||
[DataField("description")]
|
|
||||||
public string Description = string.Empty;
|
|
||||||
|
|
||||||
[DataField("playerGatherTime", customTypeSerializer: typeof(TimeOffsetSerializer))]
|
|
||||||
public TimeSpan PlayerGatherTime = TimeSpan.FromSeconds(10);
|
|
||||||
|
|
||||||
[DataField("onStart")] public IEventAction? OnStart;
|
|
||||||
[DataField("onEnd")] public IEventAction? OnEnd;
|
|
||||||
|
|
||||||
[DataField("minPlayer")] public int MinPlayer;
|
|
||||||
|
|
||||||
[ViewVariables] public TimeSpan? CurrentPlayerGatherTime = null;
|
|
||||||
[ViewVariables] public TimeSpan? EndPlayerGatherTime = null;
|
|
||||||
|
|
||||||
[ViewVariables] public bool IsBreak;
|
|
||||||
}
|
|
||||||
@@ -291,4 +291,12 @@ public sealed class WhiteCVars
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly CVarDef<bool> SlippedCountTopSlipper =
|
public static readonly CVarDef<bool> SlippedCountTopSlipper =
|
||||||
CVarDef.Create("eorstats.slippedcount_topslipper", true, CVar.SERVERONLY);
|
CVarDef.Create("eorstats.slippedcount_topslipper", true, CVar.SERVERONLY);
|
||||||
|
|
||||||
|
public static readonly CVarDef<string>
|
||||||
|
ServerCulture = CVarDef.Create("white.culture", "ru-RU", CVar.REPLICATED | CVar.SERVER);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should load a ERT map?
|
||||||
|
/// </summary>
|
||||||
|
public static readonly CVarDef<bool> LoadERTMap = CVarDef.Create("white.ert_load", false, CVar.SERVERONLY);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,3 +29,6 @@ see_own_notes = true
|
|||||||
|
|
||||||
[worldgen]
|
[worldgen]
|
||||||
enabled = false
|
enabled = false
|
||||||
|
|
||||||
|
[white]
|
||||||
|
ert_load = false
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
- type: serverEvent
|
- type: entity
|
||||||
id: ERTRecruitment
|
id: ERTRecruitment
|
||||||
name: ERT
|
parent: BaseGameRule
|
||||||
description: Your tasks is meow!
|
noSpawn: true
|
||||||
minPlayer: 4
|
components:
|
||||||
|
- type: StationEvent
|
||||||
|
earliestStart: 25
|
||||||
|
weight: 0
|
||||||
|
minimumPlayers: 125
|
||||||
|
duration: 20
|
||||||
|
- type: ERTRecruitmentRule
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user