Новые аспекты (#495)

* Add ReflectAspect

* Add SlipperyAspect

* Add TraitorRichAspect

* Add WhisperAspect

* Add DarknessAspect & StolenFloorAspect

* Add WindowLeakAspect

* Add CatEarsAspect

* Add NothingAspect

* Fix fast and furious clone

* Add SkeletonAspect

* Add cvar ceanup
This commit is contained in:
Aviu00
2023-10-19 02:32:18 +09:00
committed by Aviu00
parent d7f4a21b05
commit ecf3ecad81
48 changed files with 751 additions and 29 deletions

View File

@@ -13,6 +13,7 @@ using Content.Server.Speech.Components;
using Content.Server.Station.Components;
using Content.Server.Station.Systems;
using Content.Server.UtkaIntegration;
using Content.Server.White.AspectsSystem.Aspects.Components;
using Content.Server.White.Other.Speech;
using Content.Shared.ActionBlocker;
using Content.Shared.Administration;
@@ -63,6 +64,7 @@ public sealed partial class ChatSystem : SharedChatSystem
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
[Dependency] private readonly ReplacementAccentSystem _wordreplacement = default!;
[Dependency] private readonly INetConfigurationManager _netConfigurationManager = default!; // WD
[Dependency] private readonly GameTicker _gameTicker = default!; // WD
//WD-EDIT
[Dependency] private readonly UtkaTCPWrapper _utkaSockets = default!;
@@ -262,6 +264,12 @@ public sealed partial class ChatSystem : SharedChatSystem
}
}
if (desiredType == InGameICChatType.Speak &&
_gameTicker.GetActiveGameRules().Where(HasComp<WhisperAspectComponent>).Any()) // WD
{
desiredType = InGameICChatType.Whisper;
}
// Otherwise, send whatever type.
switch (desiredType)
{

View File

@@ -23,6 +23,10 @@ using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;
using Content.Server.Objectives;
using Content.Server.White.Administration;
using Content.Server.White.AspectsSystem.Aspects;
using Content.Server.White.AspectsSystem.Aspects.Components;
using Content.Server.White.Reputation;
using Content.Shared.White.Mood;
@@ -44,7 +48,8 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
[Dependency] private readonly SharedRoleSystem _roleSystem = default!;
[Dependency] private readonly SharedJobSystem _jobs = default!;
[Dependency] private readonly ObjectivesSystem _objectives = default!;
[Dependency] private readonly RoleSystem _roles = default!; // WD
//WD EDIT
[Dependency] private readonly GameTicker _gameTicker = default!;
private ISawmill _sawmill = default!;
@@ -190,7 +195,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
{
return false;
}*/
if (_roles.MindIsAntagonist(mindId))
if (_roleSystem.MindIsAntagonist(mindId))
{
return false;
}
@@ -200,6 +205,15 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
if (_jobs.MindTryGetJob(mindId, out _, out var prototype))
startingBalance = Math.Max(startingBalance - prototype.AntagAdvantage, 0);
// WD START
var richAspect = false;
if (_gameTicker.GetActiveGameRules().Where(HasComp<TraitorRichAspectComponent>).Any())
{
startingBalance += 10;
richAspect = true;
}
// WD END
// Give traitors their codewords and uplink code to keep in their character info menu
var briefing = Loc.GetString("traitor-role-codewords-short", ("codewords", string.Join(", ", traitorRule.Codewords)));
Note[]? code = null;
@@ -236,6 +250,8 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
}, mind);
_roleSystem.MindPlaySound(mindId, traitorRule.GreetSoundNotification, mind);
SendTraitorBriefing(mindId, traitorRule.Codewords, code);
if (richAspect) // WD
TraitorRichAspect.NotifyTraitor(mind, _chatManager);
traitorRule.TraitorMinds.Add(mindId);
// Change the faction

View File

@@ -0,0 +1,105 @@
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.Humanoid;
using Content.Shared.Humanoid.Markings;
using Robust.Shared.Prototypes;
namespace Content.Server.White.AspectsSystem.Aspects;
public sealed class CatEarsAspect : AspectSystem<CatEarsAspectComponent>
{
[Dependency] private readonly IPrototypeManager _protoMan = default!;
private MarkingPrototype _ears = default!;
private MarkingPrototype _tail = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<PlayerSpawnCompleteEvent>(HandleLateJoin);
_ears = _protoMan.Index<MarkingPrototype>("FelinidEarsBasic");
_tail = _protoMan.Index<MarkingPrototype>("FelinidTailBasic");
}
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<RandomAppearanceAspectComponent, 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);
return;
}
default:
AddEars(appearance);
AddTail(appearance);
Dirty(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});
}
}
}

View File

@@ -0,0 +1,6 @@
namespace Content.Server.White.AspectsSystem.Aspects.Components;
[RegisterComponent]
public sealed partial class CatEarsAspectComponent : Component
{
}

View File

@@ -0,0 +1,6 @@
namespace Content.Server.White.AspectsSystem.Aspects.Components;
[RegisterComponent]
public sealed partial class DarknessAspectComponent : Component
{
}

View File

@@ -0,0 +1,6 @@
namespace Content.Server.White.AspectsSystem.Aspects.Components;
[RegisterComponent]
public sealed partial class NothingAspectComponent : Component
{
}

View File

@@ -0,0 +1,6 @@
namespace Content.Server.White.AspectsSystem.Aspects.Components;
[RegisterComponent]
public sealed partial class ReflectAspectComponent : Component
{
}

View File

@@ -0,0 +1,6 @@
namespace Content.Server.White.AspectsSystem.Aspects.Components;
[RegisterComponent]
public sealed partial class SkeletonAspectComponent : Component
{
}

View File

@@ -0,0 +1,6 @@
namespace Content.Server.White.AspectsSystem.Aspects.Components;
[RegisterComponent]
public sealed partial class SlipperyAspectComponent : Component
{
}

View File

@@ -0,0 +1,6 @@
namespace Content.Server.White.AspectsSystem.Aspects.Components;
[RegisterComponent]
public sealed partial class StolenFloorAspectComponent : Component
{
}

View File

@@ -0,0 +1,6 @@
namespace Content.Server.White.AspectsSystem.Aspects.Components;
[RegisterComponent]
public sealed partial class TraitorRichAspectComponent : Component
{
}

View File

@@ -0,0 +1,6 @@
namespace Content.Server.White.AspectsSystem.Aspects.Components;
[RegisterComponent]
public sealed partial class WhisperAspectComponent : Component
{
}

View File

@@ -0,0 +1,6 @@
namespace Content.Server.White.AspectsSystem.Aspects.Components;
[RegisterComponent]
public sealed partial class WindowLeakAspectComponent : Component
{
}

View File

@@ -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);
}
}
}

View File

@@ -1,7 +1,9 @@
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;
@@ -15,9 +17,11 @@ public sealed class FastAndFuriousAspect : AspectSystem<FastAndFuriousAspectComp
{
base.Initialize();
SubscribeLocalEvent<PlayerSpawnCompleteEvent>(HandleLateJoin);
SubscribeLocalEvent<MovementSpeedModifierComponent, CloningEvent>(HandleCloning);
}
protected override void Started(EntityUid uid, FastAndFuriousAspectComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
protected override void Started(EntityUid uid, FastAndFuriousAspectComponent component, GameRuleComponent gameRule,
GameRuleStartedEvent args)
{
base.Started(uid, component, gameRule, args);
var query = EntityQueryEnumerator<MovementSpeedModifierComponent>();
@@ -28,7 +32,8 @@ public sealed class FastAndFuriousAspect : AspectSystem<FastAndFuriousAspectComp
}
}
protected override void Ended(EntityUid uid, FastAndFuriousAspectComponent component, GameRuleComponent gameRule, GameRuleEndedEvent args)
protected override void Ended(EntityUid uid, FastAndFuriousAspectComponent component, GameRuleComponent gameRule,
GameRuleEndedEvent args)
{
base.Ended(uid, component, gameRule, args);
var query = EntityQueryEnumerator<MovementSpeedModifierComponent>();
@@ -39,7 +44,20 @@ public sealed class FastAndFuriousAspect : AspectSystem<FastAndFuriousAspectComp
}
}
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))
@@ -47,11 +65,6 @@ public sealed class FastAndFuriousAspect : AspectSystem<FastAndFuriousAspectComp
if (!GameTicker.IsGameRuleAdded(ruleEntity, gameRule))
continue;
if (!ev.LateJoin)
return;
var mob = ev.Mob;
if (!TryComp<MovementSpeedModifierComponent>(mob, out var speedModifierComponent))
return;

View File

@@ -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>
{
}

View 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;
}
}
}

View File

@@ -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<RandomAccentAspectComponent, 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);
}
}

View 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 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);
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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();
}
}

View File

@@ -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>
{
}

View File

@@ -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 Robust.Shared.Map;
namespace Content.Server.White.AspectsSystem.Aspects;
public sealed class WindowLeakAspect : AspectSystem<WindowLeakAspectComponent>
{
protected override void Started(EntityUid uid, WindowLeakAspectComponent component, GameRuleComponent gameRule,
GameRuleStartedEvent args)
{
base.Started(uid, component, gameRule, args);
HashSet<EntityCoordinates> coordinatesSet = new();
var query = EntityQuery<WindowMarkComponent, TransformComponent>();
foreach (var (window, windowXform) in query)
{
var coords = windowXform.Coordinates;
coordinatesSet.Add(coords);
var wall = EntityManager.SpawnEntity(window.ReplacementProto, coords.SnapToGrid(EntityManager));
EnsureComp<WallMarkComponent>(wall);
}
var xformQuery = EntityQueryEnumerator<TransformComponent>();
while (xformQuery.MoveNext(out var tileEnt, out var xform))
{
if (HasComp<WallMarkComponent>(tileEnt))
continue;
if (coordinatesSet.Contains(xform.Coordinates))
EntityManager.DeleteEntity(tileEnt);
}
}
}

View File

@@ -160,19 +160,28 @@ namespace Content.Server.White.AspectsSystem.Base
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 (!TryGetRandomStation(out targetStation))
{
targetStation = EntityUid.Invalid;
targetGrid = EntityUid.Invalid;
return false;
}
var possibleTargets = Comp<StationDataComponent>(targetStation.Value).Grids;
if (possibleTargets.Count == 0)
if (!TryGetStationGrids(out targetStation, out var possibleTargets))
{
targetGrid = EntityUid.Invalid;
return false;

View File

@@ -72,6 +72,7 @@ namespace Content.Server.White.AspectsSystem.Managers
{
_cfg.SetCVar(WhiteCVars.DamageModifier, 1.0f);
_cfg.SetCVar(WhiteCVars.DamageGetModifier, 1.0f);
_cfg.SetCVar(WhiteCVars.SlipPowerModifier, 1.0f);
}
#endregion

View File

@@ -0,0 +1,6 @@
namespace Content.Server.White.Other;
[RegisterComponent]
public sealed partial class LightMarkComponent : Component
{
}

View File

@@ -1,12 +1,12 @@
using System.Linq;
using Content.Server.Access.Systems;
using Content.Server.Humanoid;
using Content.Server.IdentityManagement;
using Content.Server.Mind.Components;
using Content.Server.PDA;
using Content.Server.Roles;
using Content.Shared.Access.Components;
using Content.Shared.Inventory;
using Content.Shared.Mind.Components;
using Content.Shared.NukeOps;
using Content.Shared.PDA;
using Content.Shared.Preferences;
@@ -20,6 +20,7 @@ public sealed class RandomHumanSystem : EntitySystem
[Dependency] private readonly IdCardSystem _card = default!;
[Dependency] private readonly PdaSystem _pda = default!;
[Dependency] private readonly IdentitySystem _identity = default!;
[Dependency] private readonly RoleSystem _roles = default!;
public override void Initialize()
{
@@ -34,8 +35,7 @@ public sealed class RandomHumanSystem : EntitySystem
_humanoid.LoadProfile(uid, newProfile);
if (TryComp(uid, out MindContainerComponent? mindContainer) && mindContainer.HasMind &&
mindContainer.Mind.Roles.OfType<NukeopsRole>().Any())
if (HasComp<NukeOperativeComponent>(uid))
return;
_metaData.SetEntityName(uid, newProfile.Name);

View File

@@ -0,0 +1,6 @@
namespace Content.Server.White.Other;
[RegisterComponent]
public sealed partial class ReflectAspectMarkComponent : Component
{
}

View File

@@ -0,0 +1,11 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.White.Other;
[RegisterComponent]
public sealed partial class WindowMarkComponent : Component
{
[DataField("replacementProto", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
public string ReplacementProto = default!;
}

View File

@@ -112,7 +112,7 @@ public sealed class TileSystem : EntitySystem
return true;
}
private bool DeconstructTile(TileRef tileRef)
public bool DeconstructTile(TileRef tileRef, bool spawnTile = true) // WD EDIT
{
if (tileRef.Tile.IsEmpty)
return false;
@@ -133,9 +133,12 @@ public sealed class TileSystem : EntitySystem
(_robustRandom.NextFloat() - 0.5f) * bounds,
(_robustRandom.NextFloat() - 0.5f) * bounds));
//Actually spawn the relevant tile item at the right position and give it some random offset.
var tileItem = Spawn(tileDef.ItemDropPrototypeName, coordinates);
Transform(tileItem).LocalRotation = _robustRandom.NextDouble() * Math.Tau;
if (spawnTile) // WD EDIT
{
//Actually spawn the relevant tile item at the right position and give it some random offset.
var tileItem = Spawn(tileDef.ItemDropPrototypeName, coordinates);
Transform(tileItem).LocalRotation = _robustRandom.NextDouble() * Math.Tau;
}
// Destroy any decals on the tile
var decals = _decal.GetDecalsInRange(gridUid, coordinates.SnapToGrid(EntityManager, _mapManager).Position, 0.5f);

View File

@@ -4,10 +4,12 @@ using Content.Shared.Inventory;
using Content.Shared.StatusEffect;
using Content.Shared.StepTrigger.Systems;
using Content.Shared.Stunnable;
using Content.Shared.White;
using Content.Shared.White.Mood;
using JetBrains.Annotations;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Configuration;
using Robust.Shared.Containers;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Systems;
@@ -23,6 +25,11 @@ public sealed class SlipperySystem : EntitySystem
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
// WD START
[Dependency] private readonly IConfigurationManager _cfg = default!;
private float SlipPowerModifier { get; set; }
// WD END
public override void Initialize()
{
@@ -33,6 +40,8 @@ public sealed class SlipperySystem : EntitySystem
SubscribeLocalEvent<NoSlipComponent, SlipAttemptEvent>(OnNoSlipAttempt);
// as long as slip-resistant mice are never added, this should be fine (otherwise a mouse-hat will transfer it's power to the wearer).
SubscribeLocalEvent<NoSlipComponent, InventoryRelayedEvent<SlipAttemptEvent>>((e, c, ev) => OnNoSlipAttempt(e, c, ev.Args));
_cfg.OnValueChanged(WhiteCVars.SlipPowerModifier, x => SlipPowerModifier = x, true); // WD
}
private void HandleStepTrigger(EntityUid uid, SlipperyComponent component, ref StepTriggeredEvent args)
@@ -73,11 +82,11 @@ public sealed class SlipperySystem : EntitySystem
RaiseLocalEvent(uid, ref ev);
if (TryComp(other, out PhysicsComponent? physics))
_physics.SetLinearVelocity(other, physics.LinearVelocity * component.LaunchForwardsMultiplier, body: physics);
_physics.SetLinearVelocity(other, physics.LinearVelocity * component.LaunchForwardsMultiplier * SlipPowerModifier, body: physics); // WD EDIT
var playSound = !_statusEffects.HasStatusEffect(other, "KnockedDown");
_stun.TryParalyze(other, TimeSpan.FromSeconds(component.ParalyzeTime), true);
_stun.TryParalyze(other, TimeSpan.FromSeconds(component.ParalyzeTime * SlipPowerModifier), true); // WD EDIT
RaiseLocalEvent(other, new MoodEffectEvent("MobSlipped")); // WD edit

View File

@@ -332,4 +332,7 @@ public sealed class WhiteCVars
*/
public static readonly CVarDef<bool> ReputationEnabled =
CVarDef.Create("white.reputation_enabled", true, CVar.SERVERONLY);
public static readonly CVarDef<float> SlipPowerModifier =
CVarDef.Create("white.slip_power_modifier", 1.0f, CVar.REPLICATED);
}

View File

@@ -1,4 +1,4 @@
- type: entity
- type: entity
id: Airlock
parent: BaseStructure
name: airlock
@@ -136,6 +136,7 @@
- Airlock
# This tag is used to nagivate the Airlock construction graph. It's needed because the construction graph is shared between Airlock, AirlockGlass, and HighSecDoor
- type: PryUnpowered
- type: ReflectAspectMark
placement:
mode: SnapgridCenter

View File

@@ -107,6 +107,7 @@
- type: DoorBolt
- type: AccessReader
access: [ [ "Engineering" ] ]
- type: ReflectAspectMark
- type: entity
id: Firelock

View File

@@ -56,6 +56,7 @@
key: walls
mode: NoSprite
- type: Occluder
- type: ReflectAspectMark
- type: entity
id: MetalDoor

View File

@@ -95,6 +95,7 @@
messagePerceivedByOthers: comp-window-knock
interactSuccessSound:
path: /Audio/Effects/glass_knock.ogg
- type: ReflectAspectMark
- type: entity
id: ShuttersNormal

View File

@@ -1,4 +1,4 @@
- type: entity
- type: entity
id: BaseWindoor
parent: BaseStructure
abstract: true
@@ -139,6 +139,7 @@
- type: StaticPrice
price: 100
- type: PryUnpowered
- type: ReflectAspectMark
- type: entity
id: BaseSecureWindoor

View File

@@ -60,6 +60,7 @@
max: 2
- !type:DoActsBehavior
acts: ["Destruction"]
- type: LightMark
placement:
mode: SnapgridCenter
snap:

View File

@@ -50,6 +50,7 @@
- type: RadiationBlocker
resistance: 2
- type: WallMark
- type: ReflectAspectMark
- type: entity
parent: BaseWall

View File

@@ -49,6 +49,8 @@
price: 60
- type: RadiationBlocker
resistance: 2
- type: WindowMark
replacementProto: WallSolid
- type: entity
id: PlasmaWindowDirectional

View File

@@ -48,6 +48,8 @@
trackAllDamage: true
damageOverlay:
sprite: Structures/Windows/cracks.rsi
- type: WindowMark
replacementProto: WallReinforced
- type: entity
parent: ReinforcedWindow

View File

@@ -52,6 +52,8 @@
sprite: Structures/Windows/cracks.rsi
- type: StaticPrice
price: 132
- type: WindowMark
replacementProto: WallReinforced
- type: entity
id: PlasmaReinforcedWindowDirectional

View File

@@ -52,6 +52,8 @@
price: 140
- type: RadiationBlocker
resistance: 5
- type: WindowMark
replacementProto: WallReinforced
- type: entity
parent: ReinforcedUraniumWindow

View File

@@ -53,6 +53,8 @@
sprite: Structures/Windows/cracks.rsi
- type: StaticPrice
price: 100
- type: WindowMark
replacementProto: WallShuttle
- type: entity
parent: ShuttleWindow

View File

@@ -50,6 +50,8 @@
price: 80
- type: RadiationBlocker
resistance: 3
- type: WindowMark
replacementProto: WallSolid
- type: entity
parent: UraniumWindow

View File

@@ -86,6 +86,9 @@
sprite: Structures/Windows/cracks.rsi
- type: StaticPrice
price: 100
- type: ReflectAspectMark
- type: WindowMark
replacementProto: WallSolid
- type: entity
id: WindowDirectional
@@ -175,6 +178,7 @@
sprite: Structures/Windows/cracks_directional.rsi
- type: StaticPrice
price: 10
- type: ReflectAspectMark
- type: entity
id: WindowFrostedDirectional

View File

@@ -206,3 +206,136 @@
path: /Audio/White/Aspects/accent.ogg
forbidden: true
- type: DancingAspect
- type: entity
id: ReflectAspect
parent: BaseGameRule
noSpawn: true
components:
- type: Aspect
name: "Reflect"
description: "Ваше отражение повсюду."
weight: 2
startAudio:
path: /Audio/White/Aspects/accent.ogg
- type: ReflectAspect
- type: entity
id: SlipperyAspect
parent: BaseGameRule
noSpawn: true
components:
- type: Aspect
name: "Slippery"
description: "Постарайтесь не поскальзываться!"
weight: 2
startAudio:
path: /Audio/White/Aspects/accent.ogg
- type: SlipperyAspect
- type: entity
id: TraitorRichAspect
parent: BaseGameRule
noSpawn: true
components:
- type: Aspect
name: "Extra TC"
description: "Синдикат выделил 10 дополнительных телекристаллов для предателей."
requires: "Traitors"
weight: 2
hidden: true
- type: TraitorRichAspect
- type: entity
id: WhisperAspect
parent: BaseGameRule
noSpawn: true
components:
- type: Aspect
name: "Whisper"
description: "Из-за боли в горле речь дается вам с трудом."
weight: 3
startAudio:
path: /Audio/White/Aspects/accent.ogg
- type: WhisperAspect
- type: entity
id: DarknessAspect
parent: BaseGameRule
noSpawn: true
components:
- type: Aspect
name: "Darkness"
description: "Почему все так темно?"
weight: 2
startAudio:
path: /Audio/White/Aspects/accent.ogg
- type: DarknessAspect
- type: entity
id: StolenFloorAspect
parent: BaseGameRule
noSpawn: true
components:
- type: Aspect
name: "Stolen Floor"
description: "Рабочие забыли положить плитку при строительстве станции."
weight: 3
startAudio:
path: /Audio/White/Aspects/accent.ogg
- type: StolenFloorAspect
- type: entity
id: WindowLeakAspect
parent: BaseGameRule
noSpawn: true
components:
- type: Aspect
name: "Are We In Dungeon"
description: "В связи с невероятной хрупкостью окон было решено заменить их на стены."
weight: 3
startAudio:
path: /Audio/White/Aspects/accent.ogg
- type: WindowLeakAspect
- type: entity
id: CatEarsAspect
parent: BaseGameRule
noSpawn: true
components:
- type: Aspect
name: "Cat Ears And Tail"
description: "Мяукайте."
weight: 3
startAudio:
path: /Audio/White/Aspects/accent.ogg
- type: CatEarsAspect
- type: entity
id: NothingAspect
parent: BaseGameRule
noSpawn: true
components:
- type: Aspect
name: "Nothing"
description: "Ничего."
weight: 3
startAudio:
path: /Audio/White/Aspects/accent.ogg
forbidden: true
hidden: true
- type: NothingAspect
# Disabled this cause polymorph breaks stuff
#- type: entity
# id: SkeletonAspect
# parent: BaseGameRule
# noSpawn: true
# components:
# - type: Aspect
# name: "Skeletons"
# description: "АЧК АЧК!"
# weight: 1
# startAudio:
# path: /Audio/White/Aspects/accent.ogg
# - type: SkeletonAspect

View File

@@ -0,0 +1,10 @@
- type: polymorph
id: AspectForcedSkeleton
entity: MobSkeletonPerson
forced: true
inventory: Transfer
transferName: true
transferDamage: true
transferHumanoidAppearance: true
revertOnCrit: false
revertOnDeath: false