перенос файлов сервера из папки White в _White
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Shared.Access.Components;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class AiRunLockAspect : AspectSystem<AiRunLockAspectComponent>
|
||||
{
|
||||
protected override void Started(EntityUid uid, AiRunLockAspectComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
var query = EntityQueryEnumerator<AccessReaderComponent>();
|
||||
while (query.MoveNext(out _, out var accessReaderComponent))
|
||||
{
|
||||
accessReaderComponent.Enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
87
Content.Server/_White/AspectsSystem/Aspects/BattledAspect.cs
Normal file
87
Content.Server/_White/AspectsSystem/Aspects/BattledAspect.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using System.Linq;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.White.NonPeacefulRoundEnd;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class BattledAspect : AspectSystem<BattledAspectComponent>
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||
|
||||
private NonPeacefulRoundItemsPrototype _nonPeacefulRoundItemsPrototype = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<PlayerSpawnCompleteEvent>(HandleLateJoin);
|
||||
}
|
||||
|
||||
protected override void Started(EntityUid uid, BattledAspectComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
var prototypes = _prototypeManager.EnumeratePrototypes<NonPeacefulRoundItemsPrototype>().ToList();
|
||||
|
||||
if (prototypes.Count == 0)
|
||||
ForceEndSelf(uid, gameRule);
|
||||
|
||||
_nonPeacefulRoundItemsPrototype = _robustRandom.Pick(prototypes);
|
||||
|
||||
var query = EntityQueryEnumerator<HumanoidAppearanceComponent>();
|
||||
while (query.MoveNext(out var ent, out _))
|
||||
{
|
||||
GiveItem(ent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void HandleLateJoin(PlayerSpawnCompleteEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<BattledAspectComponent, GameRuleComponent>();
|
||||
while (query.MoveNext(out var ruleEntity, out _, out var gameRule))
|
||||
{
|
||||
if (!GameTicker.IsGameRuleAdded(ruleEntity, gameRule))
|
||||
continue;
|
||||
|
||||
if (!ev.LateJoin)
|
||||
return;
|
||||
|
||||
var mob = ev.Mob;
|
||||
|
||||
GiveItem(mob);
|
||||
}
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
private void GiveItem(EntityUid player)
|
||||
{
|
||||
var item = _robustRandom.Pick(_nonPeacefulRoundItemsPrototype.Items);
|
||||
|
||||
var transform = CompOrNull<TransformComponent>(player);
|
||||
|
||||
if(transform == null)
|
||||
return;
|
||||
|
||||
if(!HasComp<HandsComponent>(player))
|
||||
return;
|
||||
|
||||
var weaponEntity = EntityManager.SpawnEntity(item, transform.Coordinates);
|
||||
|
||||
_handsSystem.TryDrop(player);
|
||||
_handsSystem.PickupOrDrop(player, weaponEntity);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
26
Content.Server/_White/AspectsSystem/Aspects/BloodyAspect.cs
Normal file
26
Content.Server/_White/AspectsSystem/Aspects/BloodyAspect.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Shared.White;
|
||||
using Robust.Shared.Configuration;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class BloodyAspect : AspectSystem<BloodyAspectComponent>
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
|
||||
protected override void Started(EntityUid uid, BloodyAspectComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
_cfg.SetCVar(WhiteCVars.DamageGetModifier, 2.5f);
|
||||
}
|
||||
|
||||
protected override void Ended(EntityUid uid, BloodyAspectComponent component, GameRuleComponent gameRule, GameRuleEndedEvent args)
|
||||
{
|
||||
base.Ended(uid, component, gameRule, args);
|
||||
|
||||
_cfg.SetCVar(WhiteCVars.DamageGetModifier, 1.0f);
|
||||
}
|
||||
}
|
||||
31
Content.Server/_White/AspectsSystem/Aspects/BombassAspect.cs
Normal file
31
Content.Server/_White/AspectsSystem/Aspects/BombassAspect.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class BombassAspect : AspectSystem<BombassAspectComponent>
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
protected override void Added(EntityUid uid, BombassAspectComponent component, GameRuleComponent gameRule, GameRuleAddedEvent args)
|
||||
{
|
||||
base.Added(uid, component, gameRule, args);
|
||||
|
||||
SpawnMines();
|
||||
}
|
||||
|
||||
private void SpawnMines()
|
||||
{
|
||||
var minMines = _random.Next(40, 60);
|
||||
|
||||
for (var i = 0; i < minMines; i++)
|
||||
{
|
||||
if (!TryFindRandomTile(out _, out _, out _, out var targetCoords))
|
||||
break;
|
||||
|
||||
EntityManager.SpawnEntity("LandMineAspectExplosive", targetCoords);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using Content.Server.Cargo.Components;
|
||||
using Content.Server.Cargo.Systems;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class CargoRichAspect : AspectSystem<CargoRichAspectComponent>
|
||||
{
|
||||
[Dependency] private readonly CargoSystem _cargoSystem = default!;
|
||||
|
||||
protected override void Added(EntityUid uid, CargoRichAspectComponent component, GameRuleComponent gameRule, GameRuleAddedEvent args)
|
||||
{
|
||||
base.Added(uid, component, gameRule, args);
|
||||
|
||||
if (!TryGetRandomStation(out var station))
|
||||
return;
|
||||
|
||||
if (!TryComp<StationBankAccountComponent>(station, out var stationBankAccountComponent))
|
||||
return;
|
||||
|
||||
_cargoSystem.UpdateBankAccount(station, stationBankAccountComponent, 100000);
|
||||
}
|
||||
}
|
||||
157
Content.Server/_White/AspectsSystem/Aspects/CatEarsAspect.cs
Normal file
157
Content.Server/_White/AspectsSystem/Aspects/CatEarsAspect.cs
Normal file
@@ -0,0 +1,157 @@
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server.Speech.Components;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Shared.GameTicking;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Markings;
|
||||
using Content.Shared.Speech;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class CatEarsAspect : AspectSystem<CatEarsAspectComponent>
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _protoMan = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly ChatSystem _chat = default!;
|
||||
|
||||
private MarkingPrototype _ears = default!;
|
||||
private MarkingPrototype _tail = default!;
|
||||
|
||||
private const string FemaleFelinidVoices = "FemaleFelinid";
|
||||
private const string MaleFelinidVoices = "MaleFelinid";
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<PlayerSpawnCompleteEvent>(HandleLateJoin);
|
||||
SubscribeLocalEvent<RoundEndedEvent>(OnRoundEnd);
|
||||
|
||||
_ears = _protoMan.Index<MarkingPrototype>("FelinidEarsBasic");
|
||||
_tail = _protoMan.Index<MarkingPrototype>("FelinidTailBasic");
|
||||
}
|
||||
|
||||
private void OnRoundEnd(RoundEndedEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<CatEarsAspectComponent, GameRuleComponent>();
|
||||
while (query.MoveNext(out var ruleEntity, out _, out var gameRule))
|
||||
{
|
||||
if (!GameTicker.IsGameRuleAdded(ruleEntity, gameRule))
|
||||
continue;
|
||||
|
||||
var entQuery = EntityQueryEnumerator<SpeechComponent, HumanoidAppearanceComponent>();
|
||||
while (entQuery.MoveNext(out var ent, out _, out _))
|
||||
{
|
||||
_chat.TrySendInGameICMessage(ent, _random.Pick(new[] { "Мяу", "Мур", "Ня" }), InGameICChatType.Speak,
|
||||
ChatTransmitRange.Normal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Started(
|
||||
EntityUid uid,
|
||||
CatEarsAspectComponent component,
|
||||
GameRuleComponent gameRule,
|
||||
GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
var query = EntityQueryEnumerator<HumanoidAppearanceComponent>();
|
||||
while (query.MoveNext(out var ent, out var appearance))
|
||||
{
|
||||
AddMarkings(ent, appearance);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleLateJoin(PlayerSpawnCompleteEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<CatEarsAspectComponent, GameRuleComponent>();
|
||||
while (query.MoveNext(out var ruleEntity, out _, out var gameRule))
|
||||
{
|
||||
if (!GameTicker.IsGameRuleAdded(ruleEntity, gameRule))
|
||||
continue;
|
||||
|
||||
if (!ev.LateJoin)
|
||||
return;
|
||||
|
||||
AddMarkings(ev.Mob);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddMarkings(EntityUid uid, HumanoidAppearanceComponent? appearance = null)
|
||||
{
|
||||
if (!Resolve(uid, ref appearance, false))
|
||||
return;
|
||||
|
||||
switch (appearance.Species)
|
||||
{
|
||||
case "Felinid":
|
||||
return;
|
||||
case "Human":
|
||||
{
|
||||
if (!appearance.MarkingSet.TryGetCategory(MarkingCategories.HeadTop, out var markings) ||
|
||||
markings.Count == 0)
|
||||
AddEars(appearance);
|
||||
|
||||
if (!appearance.MarkingSet.TryGetCategory(MarkingCategories.Tail, out markings) || markings.Count == 0)
|
||||
AddTail(appearance);
|
||||
|
||||
Dirty(uid, appearance);
|
||||
ChangeEmotesVoice(uid, appearance);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
AddEars(appearance);
|
||||
AddTail(appearance);
|
||||
Dirty(uid, appearance);
|
||||
ChangeEmotesVoice(uid, appearance);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private List<Color> GetColors(HumanoidAppearanceComponent appearance, MarkingPrototype prototype)
|
||||
{
|
||||
return MarkingColoring.GetMarkingLayerColors(prototype, appearance.SkinColor, appearance.EyeColor,
|
||||
appearance.MarkingSet);
|
||||
}
|
||||
|
||||
private void AddTail(HumanoidAppearanceComponent appearance)
|
||||
{
|
||||
if (!appearance.MarkingSet.TryGetMarking(MarkingCategories.Tail, _tail.ID, out _))
|
||||
{
|
||||
appearance.MarkingSet.AddFront(MarkingCategories.Tail,
|
||||
new Marking(_tail.ID, GetColors(appearance, _tail)) { Forced = true });
|
||||
}
|
||||
}
|
||||
|
||||
private void AddEars(HumanoidAppearanceComponent appearance)
|
||||
{
|
||||
if (!appearance.MarkingSet.TryGetMarking(MarkingCategories.HeadTop, _tail.ID, out _))
|
||||
{
|
||||
appearance.MarkingSet.AddFront(MarkingCategories.HeadTop,
|
||||
new Marking(_ears.ID, GetColors(appearance, _ears)) { Forced = true });
|
||||
}
|
||||
}
|
||||
|
||||
private void ChangeEmotesVoice(EntityUid user, HumanoidAppearanceComponent appearanceComponent)
|
||||
{
|
||||
if (!TryComp(user, out VocalComponent? vocals))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (appearanceComponent.Gender)
|
||||
{
|
||||
case Gender.Female:
|
||||
_protoMan.TryIndex(FemaleFelinidVoices, out vocals.EmoteSounds);
|
||||
break;
|
||||
case Gender.Male:
|
||||
_protoMan.TryIndex(MaleFelinidVoices, out vocals.EmoteSounds);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Server._White.Other;
|
||||
using Content.Shared.Buckle;
|
||||
using Content.Shared.Buckle.Components;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class ChairLeakAspect : AspectSystem<ChairLeakAspectComponent>
|
||||
{
|
||||
[Dependency] private readonly SharedBuckleSystem _buckle = default!;
|
||||
|
||||
protected override void Started(EntityUid uid, ChairLeakAspectComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
var query = EntityQueryEnumerator<ChairMarkComponent>();
|
||||
while (query.MoveNext(out var ent, out _))
|
||||
{
|
||||
if (TryComp(ent, out StrapComponent? strap))
|
||||
_buckle.StrapRemoveAll(strap);
|
||||
|
||||
EntityManager.DeleteEntity(ent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class AiRunLockAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class BattledAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class BloodyAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class BombassAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class CargoRichAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class CatEarsAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class ChairLeakAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class DancingAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class DarknessAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class DrunkAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class FastAndFuriousAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class NoEngineAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class NothingAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class PresentAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class RandomAccentAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class RandomAppearanceAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class ReflectAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class SkeletonAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class SlipperyAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class StolenFloorAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class TraitorRichAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class TraitoredAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class WeakAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class WeakWallsAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class WhisperAspectComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class WindowLeakAspectComponent : Component
|
||||
{
|
||||
}
|
||||
49
Content.Server/_White/AspectsSystem/Aspects/DancingAspect.cs
Normal file
49
Content.Server/_White/AspectsSystem/Aspects/DancingAspect.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server._White.Animations;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.White.Animations;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class DancingAspect : AspectSystem<DancingAspectComponent>
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<PlayerSpawnCompleteEvent>(HandleLateJoin);
|
||||
}
|
||||
|
||||
protected override void Started(
|
||||
EntityUid uid,
|
||||
DancingAspectComponent component,
|
||||
GameRuleComponent gameRule,
|
||||
GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
var query = EntityQueryEnumerator<EmoteAnimationComponent, MobStateComponent>();
|
||||
while (query.MoveNext(out var ent, out _, out _))
|
||||
{
|
||||
EnsureComp<DancingComponent>(ent);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleLateJoin(PlayerSpawnCompleteEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<DancingAspectComponent, GameRuleComponent>();
|
||||
while (query.MoveNext(out var ruleEntity, out _, out var gameRule))
|
||||
{
|
||||
if (!GameTicker.IsGameRuleAdded(ruleEntity, gameRule))
|
||||
continue;
|
||||
|
||||
if (!ev.LateJoin)
|
||||
return;
|
||||
|
||||
var mob = ev.Mob;
|
||||
|
||||
EnsureComp<DancingComponent>(mob);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Server._White.Other;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class DarknessAspect : AspectSystem<DarknessAspectComponent>
|
||||
{
|
||||
protected override void Started(EntityUid uid, DarknessAspectComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
var query = EntityQueryEnumerator<LightMarkComponent>();
|
||||
while (query.MoveNext(out var ent, out _))
|
||||
{
|
||||
EntityManager.DeleteEntity(ent);
|
||||
}
|
||||
}
|
||||
}
|
||||
48
Content.Server/_White/AspectsSystem/Aspects/DrunkAspect.cs
Normal file
48
Content.Server/_White/AspectsSystem/Aspects/DrunkAspect.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Shared.Drunk;
|
||||
using Content.Shared.Humanoid;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class DrunkAspect : AspectSystem<DrunkAspectComponent>
|
||||
{
|
||||
[Dependency] private readonly SharedDrunkSystem _drunkSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<PlayerSpawnCompleteEvent>(HandleLateJoin);
|
||||
}
|
||||
|
||||
protected override void Started(EntityUid uid, DrunkAspectComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
var query = EntityQueryEnumerator<HumanoidAppearanceComponent>();
|
||||
while (query.MoveNext(out var ent, out _))
|
||||
{
|
||||
_drunkSystem.TryApplyDrunkenness(ent, 50);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleLateJoin(PlayerSpawnCompleteEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<DrunkAspectComponent, GameRuleComponent>();
|
||||
while (query.MoveNext(out var ruleEntity, out _, out var gameRule))
|
||||
{
|
||||
if (!GameTicker.IsGameRuleAdded(ruleEntity, gameRule))
|
||||
continue;
|
||||
|
||||
if (!ev.LateJoin)
|
||||
return;
|
||||
|
||||
var mob = ev.Mob;
|
||||
|
||||
_drunkSystem.TryApplyDrunkenness(mob, 50);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
using Content.Server.Cloning;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Shared.Cloning;
|
||||
using Content.Shared.Movement.Components;
|
||||
using Content.Shared.Movement.Systems;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class FastAndFuriousAspect : AspectSystem<FastAndFuriousAspectComponent>
|
||||
{
|
||||
[Dependency] private readonly MovementSpeedModifierSystem _movementSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<PlayerSpawnCompleteEvent>(HandleLateJoin);
|
||||
SubscribeLocalEvent<MovementSpeedModifierComponent, CloningEvent>(HandleCloning);
|
||||
}
|
||||
|
||||
protected override void Started(EntityUid uid, FastAndFuriousAspectComponent component, GameRuleComponent gameRule,
|
||||
GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
var query = EntityQueryEnumerator<MovementSpeedModifierComponent>();
|
||||
while (query.MoveNext(out var ent, out var speedModifierComponent))
|
||||
{
|
||||
_movementSystem.ChangeBaseSpeed(ent, speedModifierComponent.BaseWalkSpeed,
|
||||
speedModifierComponent.BaseSprintSpeed + 3, speedModifierComponent.Acceleration);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Ended(EntityUid uid, FastAndFuriousAspectComponent component, GameRuleComponent gameRule,
|
||||
GameRuleEndedEvent args)
|
||||
{
|
||||
base.Ended(uid, component, gameRule, args);
|
||||
var query = EntityQueryEnumerator<MovementSpeedModifierComponent>();
|
||||
while (query.MoveNext(out var ent, out var speedModifierComponent))
|
||||
{
|
||||
_movementSystem.ChangeBaseSpeed(ent, speedModifierComponent.BaseWalkSpeed,
|
||||
speedModifierComponent.BaseSprintSpeed, speedModifierComponent.Acceleration);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleCloning(EntityUid uid, MovementSpeedModifierComponent component, ref CloningEvent ev)
|
||||
{
|
||||
ModifySpeedIfActive(ev.Target);
|
||||
}
|
||||
|
||||
private void HandleLateJoin(PlayerSpawnCompleteEvent ev)
|
||||
{
|
||||
if (!ev.LateJoin)
|
||||
return;
|
||||
|
||||
ModifySpeedIfActive(ev.Mob);
|
||||
}
|
||||
|
||||
private void ModifySpeedIfActive(EntityUid mob)
|
||||
{
|
||||
var query = EntityQueryEnumerator<FastAndFuriousAspectComponent, GameRuleComponent>();
|
||||
while (query.MoveNext(out var ruleEntity, out _, out var gameRule))
|
||||
{
|
||||
if (!GameTicker.IsGameRuleAdded(ruleEntity, gameRule))
|
||||
continue;
|
||||
|
||||
if (!TryComp<MovementSpeedModifierComponent>(mob, out var speedModifierComponent))
|
||||
return;
|
||||
|
||||
_movementSystem.ChangeBaseSpeed(mob, speedModifierComponent.BaseWalkSpeed,
|
||||
speedModifierComponent.BaseSprintSpeed + 3, speedModifierComponent.Acceleration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Server._White.Other;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class NoEngineAspect : AspectSystem<NoEngineAspectComponent>
|
||||
{
|
||||
protected override void Started(EntityUid uid, NoEngineAspectComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
var query = EntityQueryEnumerator<EngineMarkComponent>();
|
||||
while (query.MoveNext(out var ent, out _))
|
||||
{
|
||||
EntityManager.DeleteEntity(ent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class NothingAspect : AspectSystem<NothingAspectComponent>
|
||||
{
|
||||
}
|
||||
31
Content.Server/_White/AspectsSystem/Aspects/PresentAspect.cs
Normal file
31
Content.Server/_White/AspectsSystem/Aspects/PresentAspect.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class PresentAspect : AspectSystem<PresentAspectComponent>
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
protected override void Added(EntityUid uid, PresentAspectComponent component, GameRuleComponent gameRule, GameRuleAddedEvent args)
|
||||
{
|
||||
base.Added(uid, component, gameRule, args);
|
||||
|
||||
SpawnPresents();
|
||||
}
|
||||
|
||||
private void SpawnPresents()
|
||||
{
|
||||
var minPresents = _random.Next(150, 200);
|
||||
|
||||
for (var i = 0; i < minPresents; i++)
|
||||
{
|
||||
if (!TryFindRandomTile(out _, out _, out _, out var targetCoords))
|
||||
break;
|
||||
|
||||
EntityManager.SpawnEntity("PresentRandomUnsafe", targetCoords);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
using System.Linq;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server.Speech.Components;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Shared.Mind.Components;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class RandomAccentAspect : AspectSystem<RandomAccentAspectComponent>
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<PlayerSpawnCompleteEvent>(HandleLateJoin);
|
||||
}
|
||||
|
||||
protected override void Started(EntityUid uid, RandomAccentAspectComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
var query = EntityQueryEnumerator<MindContainerComponent>();
|
||||
while (query.MoveNext(out var ent, out _))
|
||||
{
|
||||
ApplyRandomAccent(ent);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleLateJoin(PlayerSpawnCompleteEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<RandomAccentAspectComponent, GameRuleComponent>();
|
||||
while (query.MoveNext(out var ruleEntity, out _, out var gameRule))
|
||||
{
|
||||
if (!GameTicker.IsGameRuleAdded(ruleEntity, gameRule))
|
||||
continue;
|
||||
|
||||
if (!ev.LateJoin)
|
||||
return;
|
||||
|
||||
var mob = ev.Mob;
|
||||
|
||||
ApplyRandomAccent(mob);
|
||||
}
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
private enum AccentType
|
||||
{
|
||||
Stuttering,
|
||||
Spanish,
|
||||
Slurred,
|
||||
Scrambled,
|
||||
Pirate,
|
||||
Russian,
|
||||
Anime,
|
||||
Lizard,
|
||||
Backwards
|
||||
}
|
||||
|
||||
private void ApplyRandomAccent(EntityUid uid)
|
||||
{
|
||||
var allAccents = Enum.GetValues(typeof(AccentType)).Cast<AccentType>().ToList();
|
||||
var randomIndex = _random.Next(allAccents.Count);
|
||||
var selectedAccent = allAccents[randomIndex];
|
||||
ApplyAccent(uid, selectedAccent);
|
||||
}
|
||||
|
||||
private void ApplyAccent(EntityUid uid, AccentType accentType)
|
||||
{
|
||||
switch (accentType)
|
||||
{
|
||||
case AccentType.Stuttering:
|
||||
EntityManager.EnsureComponent<StutteringAccentComponent>(uid);
|
||||
break;
|
||||
case AccentType.Spanish:
|
||||
EntityManager.EnsureComponent<SpanishAccentComponent>(uid);
|
||||
break;
|
||||
case AccentType.Slurred:
|
||||
EntityManager.EnsureComponent<SlurredAccentComponent>(uid);
|
||||
break;
|
||||
case AccentType.Scrambled:
|
||||
EntityManager.EnsureComponent<ScrambledAccentComponent>(uid);
|
||||
break;
|
||||
case AccentType.Pirate:
|
||||
EntityManager.EnsureComponent<PirateAccentComponent>(uid);
|
||||
break;
|
||||
case AccentType.Russian:
|
||||
EntityManager.EnsureComponent<RussianAccentComponent>(uid);
|
||||
break;
|
||||
case AccentType.Anime:
|
||||
EntityManager.EnsureComponent<OwOAccentComponent>(uid);
|
||||
break;
|
||||
case AccentType.Lizard:
|
||||
EntityManager.EnsureComponent<LizardAccentComponent>(uid);
|
||||
break;
|
||||
case AccentType.Backwards:
|
||||
EntityManager.EnsureComponent<BackwardsAccentComponent>(uid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Server._White.Other.RandomHumanSystem;
|
||||
using Content.Shared.Humanoid;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class RandomAppearanceAspect : AspectSystem<RandomAppearanceAspectComponent>
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<PlayerSpawnCompleteEvent>(HandleLateJoin);
|
||||
}
|
||||
|
||||
protected override void Started(EntityUid uid, RandomAppearanceAspectComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
var query = EntityQueryEnumerator<HumanoidAppearanceComponent>();
|
||||
while (query.MoveNext(out var ent, out _))
|
||||
{
|
||||
EnsureComp<RandomHumanComponent>(ent);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleLateJoin(PlayerSpawnCompleteEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<RandomAppearanceAspectComponent, GameRuleComponent>();
|
||||
while (query.MoveNext(out var ruleEntity, out _, out var gameRule))
|
||||
{
|
||||
if (!GameTicker.IsGameRuleAdded(ruleEntity, gameRule))
|
||||
continue;
|
||||
|
||||
if (!ev.LateJoin)
|
||||
return;
|
||||
|
||||
var mob = ev.Mob;
|
||||
|
||||
EnsureComp<RandomHumanComponent>(mob);
|
||||
}
|
||||
}
|
||||
}
|
||||
24
Content.Server/_White/AspectsSystem/Aspects/ReflectAspect.cs
Normal file
24
Content.Server/_White/AspectsSystem/Aspects/ReflectAspect.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Server._White.Other;
|
||||
using Content.Shared.Weapons.Reflect;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class ReflectAspect : AspectSystem<ReflectAspectComponent>
|
||||
{
|
||||
protected override void Started(EntityUid uid, ReflectAspectComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
var query = EntityQueryEnumerator<ReflectAspectMarkComponent>();
|
||||
while (query.MoveNext(out var ent, out _))
|
||||
{
|
||||
var reflect = EnsureComp<ReflectComponent>(ent);
|
||||
reflect.ReflectProb = 1;
|
||||
reflect.Reflects = ReflectType.Energy | ReflectType.NonEnergy;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server.Humanoid;
|
||||
using Content.Server.Polymorph.Systems;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Polymorph;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class SkeletonAspect : AspectSystem<SkeletonAspectComponent>
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _protoMan = default!;
|
||||
[Dependency] private readonly PolymorphSystem _polymorph = default!;
|
||||
[Dependency] private readonly HumanoidAppearanceSystem _humanoidAppearance = default!;
|
||||
|
||||
private PolymorphPrototype _proto = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<PlayerSpawnCompleteEvent>(HandleLateJoin);
|
||||
|
||||
_proto = _protoMan.Index<PolymorphPrototype>("AspectForcedSkeleton");
|
||||
}
|
||||
|
||||
protected override void Started(EntityUid uid, SkeletonAspectComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
Dictionary<EntityUid, HumanoidAppearanceComponent> entitiesToPolymorph = new();
|
||||
|
||||
var query = EntityQueryEnumerator<HumanoidAppearanceComponent>();
|
||||
while (query.MoveNext(out var ent, out var humanoid))
|
||||
{
|
||||
entitiesToPolymorph[ent] = humanoid;
|
||||
}
|
||||
|
||||
foreach (var ent in entitiesToPolymorph)
|
||||
{
|
||||
PolymorphEntity(ent.Key, ent.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleLateJoin(PlayerSpawnCompleteEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<SkeletonAspectComponent, GameRuleComponent>();
|
||||
while (query.MoveNext(out var ruleEntity, out _, out var gameRule))
|
||||
{
|
||||
if (!GameTicker.IsGameRuleAdded(ruleEntity, gameRule))
|
||||
continue;
|
||||
|
||||
if (!ev.LateJoin)
|
||||
return;
|
||||
|
||||
PolymorphEntity(ev.Mob);
|
||||
}
|
||||
}
|
||||
|
||||
private void PolymorphEntity(EntityUid uid, HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (!Resolve(uid, ref humanoid, false))
|
||||
return;
|
||||
|
||||
_humanoidAppearance.SetSpecies(uid, "Skeleton", false, humanoid);
|
||||
//_humanoidAppearance.SetBodyType(uid, "SkeletonNormal", false, humanoid);
|
||||
_polymorph.PolymorphEntity(uid, _proto);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Shared.White;
|
||||
using Robust.Shared.Configuration;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class SlipperyAspect : AspectSystem<SlipperyAspectComponent>
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
|
||||
protected override void Started(EntityUid uid, SlipperyAspectComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
_cfg.SetCVar(WhiteCVars.SlipPowerModifier, 2f);
|
||||
}
|
||||
|
||||
protected override void Ended(EntityUid uid, SlipperyAspectComponent component, GameRuleComponent gameRule, GameRuleEndedEvent args)
|
||||
{
|
||||
base.Ended(uid, component, gameRule, args);
|
||||
|
||||
_cfg.SetCVar(WhiteCVars.SlipPowerModifier, 1f);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server.Maps;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Shared.Maps;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class StolenFloorAspect : AspectSystem<StolenFloorAspectComponent>
|
||||
{
|
||||
[Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!;
|
||||
[Dependency] private readonly TileSystem _tileSystem = default!;
|
||||
|
||||
protected override void Started(EntityUid uid, StolenFloorAspectComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
if (!TryGetStationGrids(out _, out var grids))
|
||||
return;
|
||||
|
||||
foreach (var grid in grids)
|
||||
{
|
||||
foreach (var tile in Comp<MapGridComponent>(grid).GetAllTiles())
|
||||
{
|
||||
var tileDef = (ContentTileDefinition) _tileDefinitionManager[tile.Tile.TypeId];
|
||||
|
||||
if (!tileDef.CanCrowbar)
|
||||
continue;
|
||||
|
||||
_tileSystem.DeconstructTile(tile, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.GameTicking.Rules;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server.Store.Components;
|
||||
using Content.Server.Store.Systems;
|
||||
using Content.Server.Traitor.Uplink;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Mind;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class TraitorRichAspect : AspectSystem<TraitorRichAspectComponent>
|
||||
{
|
||||
[Dependency] private readonly TraitorRuleSystem _traitorRuleSystem = default!;
|
||||
[Dependency] private readonly UplinkSystem _uplinkSystem = default!;
|
||||
[Dependency] private readonly StoreSystem _store = default!;
|
||||
[Dependency] private readonly IChatManager _chatManager = default!;
|
||||
|
||||
private const string BriefingExtra =
|
||||
"Поздравляем! Было принято решение выделить для вас 10 дополнительных телекристаллов.";
|
||||
|
||||
protected override void Started(EntityUid uid, TraitorRichAspectComponent component, GameRuleComponent gameRule,
|
||||
GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
if (!HasTraitorGameRule())
|
||||
ForceEndSelf(uid, gameRule);
|
||||
|
||||
RewardTraitors();
|
||||
}
|
||||
|
||||
private void RewardTraitors()
|
||||
{
|
||||
var traitors = _traitorRuleSystem.GetAllLivingConnectedTraitors();
|
||||
|
||||
foreach (var traitor in traitors)
|
||||
{
|
||||
var ent = traitor.Mind.CurrentEntity;
|
||||
|
||||
if (ent == null)
|
||||
continue;
|
||||
|
||||
var uplink = _uplinkSystem.FindUplinkTarget(ent.Value);
|
||||
|
||||
if (uplink == null || !TryComp(uplink, out StoreComponent? store) || store.AccountOwner != ent ||
|
||||
store.Preset != "StorePresetUplink")
|
||||
continue;
|
||||
|
||||
if (_store.TryAddCurrency(
|
||||
new Dictionary<string, FixedPoint2> {{UplinkSystem.TelecrystalCurrencyPrototype, 10}}, uplink.Value,
|
||||
store))
|
||||
{
|
||||
NotifyTraitor(traitor.Mind, _chatManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void NotifyTraitor(MindComponent mind, IChatManager chatManager)
|
||||
{
|
||||
if (mind.Session == null)
|
||||
return;
|
||||
|
||||
chatManager.DispatchServerMessage(mind.Session, BriefingExtra);
|
||||
}
|
||||
|
||||
private bool HasTraitorGameRule()
|
||||
{
|
||||
return EntityQuery<TraitorRuleComponent>().Any();
|
||||
}
|
||||
}
|
||||
130
Content.Server/_White/AspectsSystem/Aspects/TraitoredAspect.cs
Normal file
130
Content.Server/_White/AspectsSystem/Aspects/TraitoredAspect.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.GameTicking.Rules;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server.Mind;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects
|
||||
{
|
||||
public sealed class TraitoredAspect : AspectSystem<TraitoredAspectComponent>
|
||||
{
|
||||
[Dependency] private readonly TraitorRuleSystem _traitorRuleSystem = default!;
|
||||
[Dependency] private readonly IChatManager _chatManager = default!;
|
||||
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
||||
[Dependency] private readonly MindSystem _mindSystem = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
private bool _announcedForTators;
|
||||
|
||||
private float _timeElapsed;
|
||||
private float _timeElapsedForTators;
|
||||
|
||||
private float _wacky;
|
||||
private const float WackyAaa = 60;
|
||||
|
||||
protected override void Started(EntityUid uid, TraitoredAspectComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
// Just to make sure
|
||||
ResetValues();
|
||||
|
||||
if (!HasTraitorGameRule())
|
||||
ForceEndSelf(uid, gameRule);
|
||||
|
||||
_wacky = _random.Next(300, 360);
|
||||
}
|
||||
|
||||
protected override void ActiveTick(EntityUid uid, TraitoredAspectComponent component, GameRuleComponent gameRule, float frameTime)
|
||||
{
|
||||
base.ActiveTick(uid, component, gameRule, frameTime);
|
||||
|
||||
_timeElapsedForTators += frameTime;
|
||||
_timeElapsed += frameTime;
|
||||
|
||||
if (_timeElapsedForTators >= WackyAaa && !_announcedForTators)
|
||||
{
|
||||
AnnounceToTators(uid, gameRule);
|
||||
_announcedForTators = true;
|
||||
}
|
||||
|
||||
if (_timeElapsed >= _wacky)
|
||||
{
|
||||
AnnounceToAll(uid, gameRule);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Ended(EntityUid uid, TraitoredAspectComponent component, GameRuleComponent gameRule, GameRuleEndedEvent args)
|
||||
{
|
||||
base.Ended(uid, component, gameRule, args);
|
||||
ResetValues();
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
private void AnnounceToTators(EntityUid uid, GameRuleComponent rule)
|
||||
{
|
||||
var tators = _traitorRuleSystem.GetAllLivingConnectedTraitors();
|
||||
|
||||
if (tators.Count == 0)
|
||||
{
|
||||
ForceEndSelf(uid, rule);
|
||||
}
|
||||
|
||||
foreach (var tator in tators)
|
||||
{
|
||||
if (!_mindSystem.TryGetSession(tator.Mind, out var session))
|
||||
continue;
|
||||
|
||||
var nig = tator.Mind.OwnedEntity;
|
||||
|
||||
if (nig == null)
|
||||
return;
|
||||
|
||||
_chatManager.DispatchServerMessage(session, "Внимание, коммуникации синдиката перехвачены, вас раскрыли!");
|
||||
_audio.PlayEntity("/Audio/White/Aspects/palevo.ogg", nig.Value, nig.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private void AnnounceToAll(EntityUid uid, GameRuleComponent rule)
|
||||
{
|
||||
var tators = _traitorRuleSystem.GetAllLivingConnectedTraitors();
|
||||
|
||||
var msg = "Станция, служба контрразведки нанотрейзен рассекретила секретную передачу Синдиката и выяснила имена проникниших на вашу станцию агентов. Агенты имеют следующие имена: \n";
|
||||
|
||||
foreach (var tator in tators)
|
||||
{
|
||||
var name = tator.Mind.CharacterName;
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
msg += $" {name} - УБЕЙТЕ ЕГО НАХУЙ\n";
|
||||
}
|
||||
}
|
||||
|
||||
_chatSystem.DispatchGlobalAnnouncement(msg, "Мяукиман Крысус", colorOverride: Color.Aquamarine);
|
||||
|
||||
ForceEndSelf(uid, rule);
|
||||
}
|
||||
|
||||
private void ResetValues()
|
||||
{
|
||||
_announcedForTators = false;
|
||||
_timeElapsed = 0;
|
||||
_timeElapsedForTators = 0;
|
||||
}
|
||||
|
||||
private bool HasTraitorGameRule()
|
||||
{
|
||||
return EntityQuery<TraitorRuleComponent>().Any();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
26
Content.Server/_White/AspectsSystem/Aspects/WeakAspect.cs
Normal file
26
Content.Server/_White/AspectsSystem/Aspects/WeakAspect.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Shared.White;
|
||||
using Robust.Shared.Configuration;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class WeakAspect : AspectSystem<WeakAspectComponent>
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
|
||||
protected override void Started(EntityUid uid, WeakAspectComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
_cfg.SetCVar(WhiteCVars.DamageGetModifier, 0.5f);
|
||||
}
|
||||
|
||||
protected override void Ended(EntityUid uid, WeakAspectComponent component, GameRuleComponent gameRule, GameRuleEndedEvent args)
|
||||
{
|
||||
base.Ended(uid, component, gameRule, args);
|
||||
|
||||
_cfg.SetCVar(WhiteCVars.DamageGetModifier, 1.0f);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Destructible;
|
||||
using Content.Server.Destructible.Thresholds.Triggers;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Server._White.Other;
|
||||
using Content.Shared.Damage;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class WeakWallsAspect : AspectSystem<WeakWallsAspectComponent>
|
||||
{
|
||||
[Dependency] private readonly DamageableSystem _damageable = default!;
|
||||
|
||||
private const float DamageMultiplier = 0.15f;
|
||||
|
||||
protected override void Started(EntityUid uid, WeakWallsAspectComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
var query = EntityQueryEnumerator<WallMarkComponent>();
|
||||
while (query.MoveNext(out var ent, out _))
|
||||
{
|
||||
if (!TryComp<DestructibleComponent>(ent, out var destructible) ||
|
||||
!TryComp<DamageableComponent>(ent, out var damageable))
|
||||
continue;
|
||||
|
||||
_damageable.SetDamageModifierSetId(ent, null, damageable);
|
||||
|
||||
var trigger = (DamageTrigger?) destructible.Thresholds
|
||||
.LastOrDefault(threshold => threshold.Trigger is DamageTrigger)?.Trigger;
|
||||
|
||||
if (trigger == null)
|
||||
continue;
|
||||
|
||||
trigger.Damage = (int) (trigger.Damage * DamageMultiplier);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class WhisperAspect : AspectSystem<WhisperAspectComponent>
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server._White.AspectsSystem.Aspects.Components;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Server._White.Other;
|
||||
using Content.Shared.Coordinates.Helpers;
|
||||
using Content.Shared.Tag;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Aspects;
|
||||
|
||||
public sealed class WindowLeakAspect : AspectSystem<WindowLeakAspectComponent>
|
||||
{
|
||||
[Dependency] private readonly TagSystem _tag = default!;
|
||||
|
||||
protected override void Started(EntityUid uid, WindowLeakAspectComponent component, GameRuleComponent gameRule,
|
||||
GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
HashSet<EntityCoordinates> coordinatesSet = new();
|
||||
|
||||
var query = EntityQueryEnumerator<WindowMarkComponent, TransformComponent>();
|
||||
while (query.MoveNext(out var ent, out var window, out var windowXform))
|
||||
{
|
||||
var coords = windowXform.Coordinates;
|
||||
coordinatesSet.Add(coords);
|
||||
|
||||
EntityManager.DeleteEntity(ent);
|
||||
EntityManager.SpawnEntity(window.ReplacementProto, coords.SnapToGrid(EntityManager));
|
||||
}
|
||||
|
||||
var xformQuery = EntityQueryEnumerator<TransformComponent>();
|
||||
while (xformQuery.MoveNext(out var tileEnt, out var xform))
|
||||
{
|
||||
if (coordinatesSet.Contains(xform.Coordinates) && _tag.HasTag(tileEnt, "DeleteWithWindows"))
|
||||
EntityManager.DeleteEntity(tileEnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
39
Content.Server/_White/AspectsSystem/Base/AspectComponent.cs
Normal file
39
Content.Server/_White/AspectsSystem/Base/AspectComponent.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Base
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed partial class AspectComponent : Component
|
||||
{
|
||||
[DataField("name")]
|
||||
public string? Name;
|
||||
|
||||
[DataField("description")]
|
||||
public string? Description;
|
||||
|
||||
[DataField("requires")]
|
||||
public string? Requires;
|
||||
|
||||
[DataField("weight")]
|
||||
public float Weight = 1.0f;
|
||||
|
||||
[DataField("forbidden")]
|
||||
public bool IsForbidden;
|
||||
|
||||
[DataField("hidden")]
|
||||
public bool IsHidden;
|
||||
|
||||
[DataField("startAudio")]
|
||||
public SoundSpecifier? StartAudio;
|
||||
|
||||
[DataField("endAudio")]
|
||||
public SoundSpecifier? EndAudio;
|
||||
|
||||
[DataField("startDelay")]
|
||||
public TimeSpan StartDelay = TimeSpan.Zero;
|
||||
|
||||
[DataField("startTime", customTypeSerializer: typeof(TimeOffsetSerializer))]
|
||||
public TimeSpan StartTime;
|
||||
}
|
||||
}
|
||||
246
Content.Server/_White/AspectsSystem/Base/AspectSystem.cs
Normal file
246
Content.Server/_White/AspectsSystem/Base/AspectSystem.cs
Normal file
@@ -0,0 +1,246 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.GameTicking.Rules;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Physics;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Collections;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Base
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for aspect systems.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of component to which the system is applied.</typeparam>
|
||||
public abstract class AspectSystem<T> : GameRuleSystem<T> where T : Component
|
||||
{
|
||||
[Dependency] private readonly IAdminLogManager _adminLogManager = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
|
||||
[Dependency] private readonly TransformSystem _transform = default!;
|
||||
|
||||
protected ISawmill Sawmill = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
Sawmill = Logger.GetSawmill("aspects");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called every tick when this aspect is running.
|
||||
/// </summary>
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
var query = EntityQueryEnumerator<AspectComponent, GameRuleComponent>();
|
||||
while (query.MoveNext(out var uid, out var aspect, out var ruleData))
|
||||
{
|
||||
if (!GameTicker.IsGameRuleAdded(uid, ruleData))
|
||||
continue;
|
||||
|
||||
if (!GameTicker.IsGameRuleActive(uid, ruleData) && _timing.CurTime >= aspect.StartTime)
|
||||
{
|
||||
GameTicker.StartGameRule(uid, ruleData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when an aspect is added to an entity.
|
||||
/// </summary>
|
||||
protected override void Added(EntityUid uid, T component, GameRuleComponent gameRule, GameRuleAddedEvent args)
|
||||
{
|
||||
base.Added(uid, component, gameRule, args);
|
||||
|
||||
if (!TryComp<AspectComponent>(uid, out var aspect))
|
||||
return;
|
||||
|
||||
_adminLogManager.Add(LogType.AspectAnnounced, $"Aspect added {ToPrettyString(uid)}");
|
||||
|
||||
if (aspect is { Description: not null, IsHidden: false })
|
||||
{
|
||||
_chatSystem.DispatchGlobalAnnouncement(aspect.Description, playSound: false, colorOverride: Color.Aquamarine);
|
||||
}
|
||||
|
||||
_audio.PlayGlobal(aspect.StartAudio, Filter.Broadcast(), true);
|
||||
aspect.StartTime = _timing.CurTime + aspect.StartDelay;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when an aspect is started.
|
||||
/// </summary>
|
||||
protected override void Started(EntityUid uid, T component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
if (!TryComp<AspectComponent>(uid, out _))
|
||||
return;
|
||||
|
||||
_adminLogManager.Add(LogType.AspectStarted, LogImpact.High, $"Aspect started: {ToPrettyString(uid)}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when an aspect is ended.
|
||||
/// </summary>
|
||||
protected override void Ended(EntityUid uid, T component, GameRuleComponent gameRule, GameRuleEndedEvent args)
|
||||
{
|
||||
base.Ended(uid, component, gameRule, args);
|
||||
|
||||
if (!TryComp<AspectComponent>(uid, out var aspect))
|
||||
return;
|
||||
|
||||
_adminLogManager.Add(LogType.AspectStopped, $"Aspect ended: {ToPrettyString(uid)}");
|
||||
|
||||
if (aspect is { Name: not null, IsHidden: false })
|
||||
{
|
||||
_chatSystem.DispatchGlobalAnnouncement($"Именем аспекта являлось: {aspect.Name}", playSound: false, colorOverride: Color.Aquamarine);
|
||||
}
|
||||
|
||||
_audio.PlayGlobal(aspect.EndAudio, Filter.Broadcast(), true);
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Forces this aspect to end prematurely.
|
||||
/// </summary>
|
||||
/// <param name="uid">The entity UID on which the aspect is being performed.</param>
|
||||
/// <param name="component">The game rule component associated with this aspect (optional).</param>
|
||||
protected void ForceEndSelf(EntityUid uid, GameRuleComponent? component = null)
|
||||
{
|
||||
GameTicker.EndGameRule(uid, component);
|
||||
}
|
||||
|
||||
protected bool TryGetRandomStation([NotNullWhen(true)] out EntityUid? station, Func<EntityUid, bool>? filter = null)
|
||||
{
|
||||
var stations = new ValueList<EntityUid>();
|
||||
|
||||
if (filter == null)
|
||||
{
|
||||
stations.EnsureCapacity(Count<StationEventEligibleComponent>());
|
||||
}
|
||||
|
||||
filter ??= _ => true;
|
||||
var query = AllEntityQuery<StationEventEligibleComponent>();
|
||||
|
||||
while (query.MoveNext(out var uid, out _))
|
||||
{
|
||||
if (!filter(uid))
|
||||
continue;
|
||||
|
||||
stations.Add(uid);
|
||||
}
|
||||
|
||||
if (stations.Count == 0)
|
||||
{
|
||||
station = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
station = stations[_robustRandom.Next(stations.Count)];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected bool TryGetStationGrids([NotNullWhen(true)] out EntityUid? targetStation,
|
||||
[NotNullWhen(true)] out HashSet<EntityUid>? grids)
|
||||
{
|
||||
if (!TryGetRandomStation(out targetStation))
|
||||
{
|
||||
targetStation = EntityUid.Invalid;
|
||||
grids = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
grids = Comp<StationDataComponent>(targetStation.Value).Grids;
|
||||
|
||||
return grids.Count > 0;
|
||||
}
|
||||
|
||||
protected bool TryFindRandomTile(out Vector2i tile, [NotNullWhen(true)] out EntityUid? targetStation, out EntityUid targetGrid, out EntityCoordinates targetCoords)
|
||||
{
|
||||
tile = default;
|
||||
|
||||
targetCoords = EntityCoordinates.Invalid;
|
||||
|
||||
if (!TryGetStationGrids(out targetStation, out var possibleTargets))
|
||||
{
|
||||
targetGrid = EntityUid.Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
targetGrid = _robustRandom.Pick(possibleTargets);
|
||||
foreach (var target in possibleTargets.Where(HasComp<BecomesStationComponent>))
|
||||
{
|
||||
targetGrid = target;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!TryComp<MapGridComponent>(targetGrid, out var gridComp))
|
||||
return false;
|
||||
|
||||
var found = false;
|
||||
var gridBounds = gridComp.LocalAABB.Scale(0.6f);
|
||||
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
var randomX = _robustRandom.Next((int) gridBounds.Left, (int) gridBounds.Right);
|
||||
var randomY = _robustRandom.Next((int) gridBounds.Bottom, (int) gridBounds.Top);
|
||||
|
||||
tile = new Vector2i(randomX, randomY);
|
||||
if (_atmosphere.IsTileSpace(targetGrid, Transform(targetGrid).MapUid, tile,
|
||||
mapGridComp: gridComp)
|
||||
|| _atmosphere.IsTileAirBlocked(targetGrid, tile, mapGridComp: gridComp))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var physQuery = GetEntityQuery<PhysicsComponent>();
|
||||
var valid = true;
|
||||
foreach (var ent in gridComp.GetAnchoredEntities(tile))
|
||||
{
|
||||
if (!physQuery.TryGetComponent(ent, out var body))
|
||||
continue;
|
||||
if (body.BodyType != BodyType.Static ||
|
||||
!body.Hard ||
|
||||
(body.CollisionLayer & (int) CollisionGroup.Impassable) == 0)
|
||||
continue;
|
||||
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!valid)
|
||||
continue;
|
||||
|
||||
found = true;
|
||||
targetCoords = gridComp.GridTileToLocal(tile);
|
||||
break;
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
145
Content.Server/_White/AspectsSystem/Commands/AspectCommands.cs
Normal file
145
Content.Server/_White/AspectsSystem/Commands/AspectCommands.cs
Normal file
@@ -0,0 +1,145 @@
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server._White.AspectsSystem.Managers;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Commands
|
||||
{
|
||||
[AdminCommand(AdminFlags.Fun)]
|
||||
public sealed class ForceAspectCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "forceaspect";
|
||||
public string Description => "Принудительно форсит аспект по его ID.";
|
||||
public string Help => "forceaspect <aspectId>";
|
||||
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var ticker = EntitySystem.Get<GameTicker>();
|
||||
if (ticker.RunLevel != GameRunLevel.PreRoundLobby)
|
||||
{
|
||||
shell.WriteLine("This can only be executed while the game is in the pre-round lobby.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.Length != 1)
|
||||
{
|
||||
shell.WriteError("Использование: forceaspect <aspectId>");
|
||||
return;
|
||||
}
|
||||
|
||||
var aspectId = args[0];
|
||||
var aspectManager = EntitySystem.Get<AspectManager>();
|
||||
var result = aspectManager.ForceAspect(aspectId);
|
||||
shell.WriteLine(result);
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Fun)]
|
||||
public sealed class DeForceAspectCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "deforceaspect";
|
||||
public string Description => "Дефорсит принудительно установленный аспект.";
|
||||
public string Help => "deforceaspect";
|
||||
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var ticker = EntitySystem.Get<GameTicker>();
|
||||
if (ticker.RunLevel != GameRunLevel.PreRoundLobby)
|
||||
{
|
||||
shell.WriteLine("This can only be executed while the game is in the pre-round lobby.");
|
||||
return;
|
||||
}
|
||||
|
||||
var aspectManager = EntitySystem.Get<AspectManager>();
|
||||
var result = aspectManager.DeForceAspect();
|
||||
shell.WriteLine(result);
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Fun)]
|
||||
public sealed class GetForcedAspectCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "getforcedaspect";
|
||||
public string Description => "Получает информацию о принудительно установленном аспекте.";
|
||||
public string Help => "getforcedaspect";
|
||||
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var ticker = EntitySystem.Get<GameTicker>();
|
||||
if (ticker.RunLevel != GameRunLevel.PreRoundLobby)
|
||||
{
|
||||
shell.WriteLine("This can only be executed while the game is in the pre-round lobby.");
|
||||
return;
|
||||
}
|
||||
|
||||
var aspectManager = EntitySystem.Get<AspectManager>();
|
||||
var result = aspectManager.GetForcedAspect();
|
||||
shell.WriteLine(result);
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Fun)]
|
||||
public sealed class ListAspectsCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "listaspects";
|
||||
public string Description => "Список всех доступных аспектов.";
|
||||
public string Help => "listaspects";
|
||||
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var aspectManager = EntitySystem.Get<AspectManager>();
|
||||
var aspectIds = aspectManager.GetAllAspectIds();
|
||||
|
||||
if (aspectIds.Count == 0)
|
||||
{
|
||||
shell.WriteLine("Нет доступных аспектов.");
|
||||
}
|
||||
else
|
||||
{
|
||||
shell.WriteLine("Список доступных аспектов:");
|
||||
foreach (var aspectId in aspectIds)
|
||||
{
|
||||
shell.WriteLine(aspectId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Fun)]
|
||||
public sealed class RunAspectCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "runaspect";
|
||||
public string Description => "Запускает аспект по его ID.";
|
||||
public string Help => "runaspect <aspectId>";
|
||||
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
{
|
||||
shell.WriteError("Использование: runaspect <aspectId>");
|
||||
return;
|
||||
}
|
||||
|
||||
var aspectId = args[0];
|
||||
var aspectManager = EntitySystem.Get<AspectManager>();
|
||||
var result = aspectManager.RunAspect(aspectId);
|
||||
shell.WriteLine(result);
|
||||
}
|
||||
}
|
||||
|
||||
[AdminCommand(AdminFlags.Fun)]
|
||||
public sealed class RunRandomAspectCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "runrandomaspect";
|
||||
public string Description => "Запускает случайный аспект.";
|
||||
public string Help => "runrandomaspect";
|
||||
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var aspectManager = EntitySystem.Get<AspectManager>();
|
||||
var result = aspectManager.RunRandomAspect();
|
||||
shell.WriteLine(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
382
Content.Server/_White/AspectsSystem/Managers/AspectManager.cs
Normal file
382
Content.Server/_White/AspectsSystem/Managers/AspectManager.cs
Normal file
@@ -0,0 +1,382 @@
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server._White.AspectsSystem.Base;
|
||||
using Content.Shared.GameTicking;
|
||||
using Content.Shared.White;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server._White.AspectsSystem.Managers
|
||||
{
|
||||
/// <summary>
|
||||
/// Manager for aspects.
|
||||
/// </summary>
|
||||
public sealed class AspectManager : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly GameTicker _gameTicker = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
|
||||
private ISawmill _sawmill = default!;
|
||||
|
||||
private bool AspectsEnabled { get; set; }
|
||||
|
||||
private double Chance { get; set; }
|
||||
|
||||
private string? ForcedAspect { get; set; }
|
||||
|
||||
private void SetEnabled(bool value) => AspectsEnabled = value;
|
||||
|
||||
private void SetChance(double value) => Chance = value;
|
||||
|
||||
private void SetForcedAspect(string? value) => ForcedAspect = value;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_sawmill = Logger.GetSawmill("aspects");
|
||||
|
||||
_cfg.OnValueChanged(WhiteCVars.IsAspectsEnabled, SetEnabled, true);
|
||||
_cfg.OnValueChanged(WhiteCVars.AspectChance, SetChance, true);
|
||||
|
||||
SubscribeLocalEvent<RoundStartedEvent>(OnRoundStarted);
|
||||
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRestart);
|
||||
}
|
||||
|
||||
#region Handlers
|
||||
|
||||
private void OnRoundStarted(RoundStartedEvent ev)
|
||||
{
|
||||
if (!AspectsEnabled)
|
||||
return;
|
||||
|
||||
if (ForcedAspect != null)
|
||||
{
|
||||
RunAspect(ForcedAspect);
|
||||
|
||||
SetForcedAspect(null);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (_random.NextDouble() <= Chance)
|
||||
{
|
||||
RunRandomAspect();
|
||||
}
|
||||
}
|
||||
|
||||
// Put here needed cleanup.
|
||||
private void OnRestart(RoundRestartCleanupEvent ev)
|
||||
{
|
||||
_cfg.SetCVar(WhiteCVars.DamageModifier, 1.0f);
|
||||
_cfg.SetCVar(WhiteCVars.DamageGetModifier, 1.0f);
|
||||
_cfg.SetCVar(WhiteCVars.SlipPowerModifier, 1.0f);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PublicApi
|
||||
|
||||
/// <summary>
|
||||
/// Forces a specific aspect by its prototype ID.
|
||||
/// </summary>
|
||||
/// <param name="aspectProtoId">The prototype ID of the aspect to be forced.</param>
|
||||
public string ForceAspect(string aspectProtoId)
|
||||
{
|
||||
if (!AspectsEnabled)
|
||||
{
|
||||
var disabledStr = "Aspects disabled.";
|
||||
_sawmill.Warning("Someone tried to force aspect when they disabled!");
|
||||
return disabledStr;
|
||||
}
|
||||
|
||||
if (!_prototype.TryIndex<EntityPrototype>(aspectProtoId, out var entityPrototype))
|
||||
{
|
||||
var response = "Aspect not found. Can`t find proto";
|
||||
_sawmill.Warning("Someone tried to force invalid Aspect!");
|
||||
return response;
|
||||
}
|
||||
|
||||
if (!entityPrototype.TryGetComponent<AspectComponent>(out _))
|
||||
{
|
||||
var errStr = $"Aspect with ID '{aspectProtoId}' not found or does not have an AspectComponent!";
|
||||
_sawmill.Error(errStr);
|
||||
return errStr;
|
||||
}
|
||||
|
||||
if (ForcedAspect == aspectProtoId)
|
||||
{
|
||||
var errStr = $"Aspect with ID '{aspectProtoId}' already forced!";
|
||||
_sawmill.Error(errStr);
|
||||
return errStr;
|
||||
}
|
||||
|
||||
SetForcedAspect(aspectProtoId);
|
||||
|
||||
var str = $"Successfully forced Aspect with ID '{aspectProtoId}'";
|
||||
_sawmill.Info(str);
|
||||
return str;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DeForces a ForcedAspect, if any.
|
||||
/// </summary>
|
||||
public string DeForceAspect()
|
||||
{
|
||||
string response;
|
||||
|
||||
if (ForcedAspect != null)
|
||||
{
|
||||
response = $"DeForced Aspect : {ForcedAspect}";
|
||||
SetForcedAspect(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
response = "How to DeForce if no aspect forced, retard..";
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves information about the currently forced aspect, if any.
|
||||
/// </summary>
|
||||
public string GetForcedAspect()
|
||||
{
|
||||
var response = ForcedAspect != null
|
||||
? $"Current forced Aspect : {ForcedAspect}"
|
||||
: "No forced Aspects";
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a list of IDs for all available aspects.
|
||||
/// </summary>
|
||||
/// <returns>A list of IDs for available aspects.</returns>
|
||||
public List<string> GetAllAspectIds()
|
||||
{
|
||||
var availableAspects = AllAspects();
|
||||
var aspectIds = new List<string>();
|
||||
|
||||
foreach (var (proto, aspect) in availableAspects)
|
||||
{
|
||||
var initialAspectId = proto.ID;
|
||||
var returnedAspectId = proto.ID;
|
||||
|
||||
if (aspect.Requires != null)
|
||||
{
|
||||
returnedAspectId += $" (Requires: {aspect.Requires})";
|
||||
}
|
||||
|
||||
if (aspect.IsForbidden)
|
||||
{
|
||||
returnedAspectId += " (ShitSpawn)";
|
||||
}
|
||||
|
||||
if (ForcedAspect == initialAspectId)
|
||||
{
|
||||
returnedAspectId += " (Forced)";
|
||||
}
|
||||
|
||||
if (CheckIfAspectAlreadyRunning(initialAspectId))
|
||||
{
|
||||
returnedAspectId += " (Already Running)";
|
||||
}
|
||||
|
||||
aspectIds.Add(returnedAspectId);
|
||||
}
|
||||
|
||||
return aspectIds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs the specified aspect and adds it as a game rule.
|
||||
/// </summary>
|
||||
/// <param name="aspectId">The ID of the aspect to run.</param>
|
||||
public string RunAspect(string aspectId)
|
||||
{
|
||||
if (!AspectsEnabled)
|
||||
{
|
||||
var disabledStr = "Aspects disabled.";
|
||||
_sawmill.Warning("Someone tried to run aspects when they disabled!");
|
||||
return disabledStr;
|
||||
}
|
||||
|
||||
if (!_prototype.TryIndex<EntityPrototype>(aspectId, out var entityPrototype))
|
||||
{
|
||||
var response = "Aspect not found. Can`t find proto";
|
||||
_sawmill.Warning("Someone tried to run invalid Aspect!");
|
||||
return response;
|
||||
}
|
||||
|
||||
if (!entityPrototype.TryGetComponent<AspectComponent>(out var aspect))
|
||||
{
|
||||
var errStr = $"Aspect with ID '{aspectId}' not found or does not have an AspectComponent!";
|
||||
_sawmill.Error(errStr);
|
||||
return errStr;
|
||||
}
|
||||
|
||||
if (CheckIfAspectAlreadyRunning(aspectId))
|
||||
{
|
||||
var alreadyRunningStr = $"Aspect '{aspectId}' is already running!";
|
||||
_sawmill.Warning(alreadyRunningStr);
|
||||
return alreadyRunningStr;
|
||||
}
|
||||
|
||||
var ent = _gameTicker.AddGameRule(aspectId);
|
||||
var str = $"Ran {aspect.Name ?? "Unnamed Aspect"} ({ToPrettyString(ent)})!!";
|
||||
_sawmill.Info(str);
|
||||
return str;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs a random aspect and adds it as a game rule.
|
||||
/// </summary>
|
||||
public string RunRandomAspect()
|
||||
{
|
||||
if (!AspectsEnabled)
|
||||
{
|
||||
var disabledStr = "Aspects disabled.";
|
||||
_sawmill.Warning("Someone tried to run aspects when they disabled!");
|
||||
return disabledStr;
|
||||
}
|
||||
|
||||
var randomAspect = PickRandomAspect();
|
||||
|
||||
if (randomAspect == null)
|
||||
{
|
||||
var errStr = "Oopsie, no valid aspects found! Sorry.";
|
||||
_sawmill.Error(errStr);
|
||||
return errStr;
|
||||
}
|
||||
|
||||
var ent = _gameTicker.AddGameRule(randomAspect);
|
||||
var str = $"Ran {ToPrettyString(ent)}!!";
|
||||
_sawmill.Info(str);
|
||||
return str;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Picks a random aspect based on their weight.
|
||||
/// </summary>
|
||||
/// <param name="allowForbidden">Allow selecting forbidden aspects.</param>
|
||||
/// <returns>The ID of the selected aspect or null if no aspect was selected.</returns>
|
||||
private string? PickRandomAspect(bool allowForbidden = false)
|
||||
{
|
||||
var availableAspects = AllAspects();
|
||||
_sawmill.Info($"Picking from {availableAspects.Count} total available aspects");
|
||||
return FindAspect(availableAspects, allowForbidden);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds a suitable aspect from the available aspects.
|
||||
/// </summary>
|
||||
/// <param name="availableAspects">A dictionary of available aspects.</param>
|
||||
/// <param name="allowForbidden">Allow selecting forbidden aspects.</param>
|
||||
/// <returns>The ID of the selected aspect or null if no aspect was found.</returns>
|
||||
private string? FindAspect(Dictionary<EntityPrototype, AspectComponent> availableAspects, bool allowForbidden = false)
|
||||
{
|
||||
if (availableAspects.Count == 0)
|
||||
{
|
||||
_sawmill.Warning("No aspects were available to run!");
|
||||
return null;
|
||||
}
|
||||
|
||||
var sumOfWeights = 0;
|
||||
|
||||
foreach (var (_, aspect) in availableAspects)
|
||||
{
|
||||
if (!allowForbidden && aspect.IsForbidden)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sumOfWeights += (int)aspect.Weight;
|
||||
}
|
||||
|
||||
sumOfWeights = _random.Next(sumOfWeights);
|
||||
|
||||
foreach (var (proto, aspect) in availableAspects)
|
||||
{
|
||||
if (!allowForbidden && aspect.IsForbidden)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CheckIfAspectAlreadyRunning(proto.ID))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sumOfWeights -= (int)aspect.Weight;
|
||||
|
||||
if (sumOfWeights <= 0)
|
||||
{
|
||||
return proto.ID;
|
||||
}
|
||||
}
|
||||
|
||||
_sawmill.Error("Aspect was not found after weighted pick process!");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Checking if aspect is already running, needed to avoid repeating.
|
||||
/// </summary>
|
||||
private bool CheckIfAspectAlreadyRunning(string aspectId)
|
||||
{
|
||||
var activeRules = _gameTicker.GetActiveGameRules();
|
||||
|
||||
foreach (var gameRule in activeRules)
|
||||
{
|
||||
if (!HasComp<AspectComponent>(gameRule))
|
||||
continue;
|
||||
|
||||
if (!TryComp<MetaDataComponent>(gameRule, out var metaDataComponent))
|
||||
continue;
|
||||
|
||||
var runningAspectId = metaDataComponent.EntityPrototype?.ID;
|
||||
|
||||
if (runningAspectId == aspectId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a dictionary of all available aspects from prototypes.
|
||||
/// </summary>
|
||||
/// <returns>A dictionary of available aspects.</returns>
|
||||
private Dictionary<EntityPrototype, AspectComponent> AllAspects()
|
||||
{
|
||||
var allAspects = new Dictionary<EntityPrototype, AspectComponent>();
|
||||
foreach (var prototype in _prototype.EnumeratePrototypes<EntityPrototype>())
|
||||
{
|
||||
if (prototype.Abstract)
|
||||
continue;
|
||||
|
||||
if (!prototype.TryGetComponent<AspectComponent>(out var aspect))
|
||||
continue;
|
||||
|
||||
allAspects.Add(prototype, aspect);
|
||||
}
|
||||
|
||||
return allAspects;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user