Cult update (#220)
* - tweak: Cult door not bump openable. * - tweak: Better summoning and Narsie * - tweak: Construct update. * - tweak: Eldrich blade fits in suit storage. * - tweak: More spell limit. * - fix: Fix pylon desc. * - tweak: Teleport works on cuffed targets. * - tweak: More popups if target is holy. * - fix: No rune drawing using fingers. * - tweak: Better pylon placement & less pylon healing range. * - tweak: More blood rites charge. * - fix: Fix max spell amount. * - tweak: Less cult door and wall health. * - fix: Constructs are dead IC. * - add: Revive rune now notifies player. * - add: Narsie summon rune eui. * - fix: Fix narsie summon sound not playing for reapers. * - tweak: Whatever. * - add: Conceal presence spell. * - tweak: Tweakz. * - add: Blood spear. * - add: Blood boil barrage. * - tweak: Artificer flies. * - tweak: Blood bolt color tweaks. * - tweak: Runic door is bump openable again. * - fix: Fix concealed door outline. * - add: Update concealable name and desc. * - tweak: Remove the unremoveable. * - tweak: Gift ignore. * - add: Organs regenerate on rejuvenate. * - tweak: Brainless cultist is fine. * - add: Added more fun. * - add: Add rune descriptions. * - fix: Fixes. * - tweak: Blood rites now uses verb. * - tweak: Bring it back.
@@ -0,0 +1,67 @@
|
||||
using System.Linq;
|
||||
using Content.Client.IconSmoothing;
|
||||
using Content.Client.Interactable.Components;
|
||||
using Content.Shared._White.Cult.Components;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client._White.Cult.Concealable;
|
||||
|
||||
public sealed class ConcealableVisualizer : VisualizerSystem<ConcealableComponent>
|
||||
{
|
||||
[Dependency] private readonly IconSmoothSystem _smooth = default!;
|
||||
|
||||
protected override void OnAppearanceChange(EntityUid uid, ConcealableComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
base.OnAppearanceChange(uid, component, ref args);
|
||||
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (!AppearanceSystem.TryGetData<bool>(uid, ConcealableAppearance.Concealed, out var concealed, args.Component))
|
||||
return;
|
||||
|
||||
if (component.IconSmooth)
|
||||
_smooth.SetEnabled(uid, concealed);
|
||||
|
||||
if (component.InteractionOutline)
|
||||
{
|
||||
if (concealed)
|
||||
{
|
||||
if (TryComp(uid, out InteractionOutlineComponent? outline))
|
||||
{
|
||||
outline.OnMouseLeave(uid);
|
||||
RemComp<InteractionOutlineComponent>(uid);
|
||||
}
|
||||
}
|
||||
else
|
||||
EnsureComp<InteractionOutlineComponent>(uid);
|
||||
}
|
||||
|
||||
if (concealed)
|
||||
{
|
||||
if (component.ConcealedSprite != null)
|
||||
{
|
||||
for (var i = 0; i < args.Sprite.AllLayers.Count(); i++)
|
||||
{
|
||||
args.Sprite.LayerSetRSI(i, component.ConcealedSprite.Value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
args.Sprite.Color = args.Sprite.Color.WithAlpha(0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (component.RevealedSprite != null)
|
||||
{
|
||||
for (var i = 0; i < args.Sprite.AllLayers.Count(); i++)
|
||||
{
|
||||
args.Sprite.LayerSetRSI(i, component.RevealedSprite.Value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
args.Sprite.Color = args.Sprite.Color.WithAlpha(1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Shared._White.Cult;
|
||||
using Content.Shared._White.Cult.Components;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Player;
|
||||
@@ -20,10 +21,15 @@ public sealed class ShowCultHudSystem : EntitySystem
|
||||
SubscribeLocalEvent<CultistComponent, PlayerAttachedEvent>(OnPlayerAttached);
|
||||
SubscribeLocalEvent<CultistComponent, PlayerDetachedEvent>(OnPlayerDetached);
|
||||
|
||||
SubscribeLocalEvent<ShowCultHudComponent, ComponentInit>(OnComponentInit);
|
||||
SubscribeLocalEvent<ShowCultHudComponent, ComponentRemove>(OnComponentRemoved);
|
||||
SubscribeLocalEvent<ShowCultHudComponent, PlayerAttachedEvent>(OnPlayerAttached);
|
||||
SubscribeLocalEvent<ShowCultHudComponent, PlayerDetachedEvent>(OnPlayerDetached);
|
||||
|
||||
_overlay = new CultHudOverlay(EntityManager);
|
||||
}
|
||||
|
||||
private void OnComponentInit(EntityUid uid, CultistComponent component, ComponentInit args)
|
||||
private void OnComponentInit(EntityUid uid, ShowCultHudComponent component, ComponentInit args)
|
||||
{
|
||||
if (_player.LocalSession?.AttachedEntity != uid)
|
||||
return;
|
||||
@@ -32,7 +38,7 @@ public sealed class ShowCultHudSystem : EntitySystem
|
||||
|
||||
}
|
||||
|
||||
private void OnComponentRemoved(EntityUid uid, CultistComponent component, ComponentRemove args)
|
||||
private void OnComponentRemoved(EntityUid uid, ShowCultHudComponent component, ComponentRemove args)
|
||||
{
|
||||
if (_player.LocalSession?.AttachedEntity != uid)
|
||||
return;
|
||||
@@ -41,7 +47,7 @@ public sealed class ShowCultHudSystem : EntitySystem
|
||||
|
||||
}
|
||||
|
||||
private void OnPlayerAttached(EntityUid uid, CultistComponent component, PlayerAttachedEvent args)
|
||||
private void OnPlayerAttached(EntityUid uid, ShowCultHudComponent component, PlayerAttachedEvent args)
|
||||
{
|
||||
if (_player.LocalSession != args.Player)
|
||||
return;
|
||||
@@ -49,7 +55,7 @@ public sealed class ShowCultHudSystem : EntitySystem
|
||||
_overlayManager.AddOverlay(_overlay);
|
||||
}
|
||||
|
||||
private void OnPlayerDetached(EntityUid uid, CultistComponent component, PlayerDetachedEvent args)
|
||||
private void OnPlayerDetached(EntityUid uid, ShowCultHudComponent component, PlayerDetachedEvent args)
|
||||
{
|
||||
if (_player.LocalSession != args.Player)
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
using Content.Client.Eui;
|
||||
using Content.Client.Ghost.UI;
|
||||
using Content.Shared._White.Cult.UI;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Graphics;
|
||||
|
||||
namespace Content.Client._White.Cult.UI.ApocalypseRuneEui;
|
||||
|
||||
[UsedImplicitly]
|
||||
public sealed class ApocalypseRuneEui : BaseEui
|
||||
{
|
||||
private readonly ApocalypseRuneMenu _menu;
|
||||
|
||||
public ApocalypseRuneEui()
|
||||
{
|
||||
_menu = new ApocalypseRuneMenu();
|
||||
|
||||
_menu.DenyButton.OnPressed += _ =>
|
||||
{
|
||||
SendMessage(new ApocalypseRuneDrawMessage(false));
|
||||
_menu.Close();
|
||||
};
|
||||
|
||||
_menu.AcceptButton.OnPressed += _ =>
|
||||
{
|
||||
SendMessage(new ApocalypseRuneDrawMessage(true));
|
||||
_menu.Close();
|
||||
};
|
||||
}
|
||||
|
||||
public override void Opened()
|
||||
{
|
||||
IoCManager.Resolve<IClyde>().RequestWindowAttention();
|
||||
_menu.OpenCentered();
|
||||
}
|
||||
|
||||
public override void Closed()
|
||||
{
|
||||
base.Closed();
|
||||
|
||||
SendMessage(new ApocalypseRuneDrawMessage(false));
|
||||
_menu.Close();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using System.Numerics;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using static Robust.Client.UserInterface.Controls.BoxContainer;
|
||||
|
||||
namespace Content.Client.Ghost.UI;
|
||||
|
||||
public sealed class ApocalypseRuneMenu : DefaultWindow
|
||||
{
|
||||
public readonly Button DenyButton;
|
||||
public readonly Button AcceptButton;
|
||||
|
||||
public ApocalypseRuneMenu()
|
||||
{
|
||||
Title = Loc.GetString("apocalypse-rune-title");
|
||||
|
||||
Contents.AddChild(new BoxContainer
|
||||
{
|
||||
Orientation = LayoutOrientation.Vertical,
|
||||
Children =
|
||||
{
|
||||
new BoxContainer
|
||||
{
|
||||
Orientation = LayoutOrientation.Vertical,
|
||||
Children =
|
||||
{
|
||||
(new Label()
|
||||
{
|
||||
Text = Loc.GetString("apocalypse-rune-text")
|
||||
}),
|
||||
new BoxContainer
|
||||
{
|
||||
Orientation = LayoutOrientation.Horizontal,
|
||||
Align = AlignMode.Center,
|
||||
Children =
|
||||
{
|
||||
(AcceptButton = new Button
|
||||
{
|
||||
Text = Loc.GetString("apocalypse-rune-accept-button"),
|
||||
}),
|
||||
|
||||
(new Control()
|
||||
{
|
||||
MinSize = new Vector2(20, 0)
|
||||
}),
|
||||
|
||||
(DenyButton = new Button
|
||||
{
|
||||
Text = Loc.GetString("apocalypse-rune-deny-button"),
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@ public sealed class CultistFactoryBUI : BoundUserInterface
|
||||
|
||||
_radialContainer = new RadialContainer();
|
||||
|
||||
_radialContainer.Closed += Close;
|
||||
|
||||
if (State != null)
|
||||
UpdateState(State);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Content.Client.Lathe.UI;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
@@ -7,19 +8,21 @@ using Robust.Shared.Prototypes;
|
||||
namespace Content.Client._White.Cult.UI.ListViewSelector;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public partial class ListViewSelectorWindow : DefaultWindow
|
||||
public sealed partial class ListViewSelectorWindow : DefaultWindow
|
||||
{
|
||||
public Action<string, int>? ItemSelected;
|
||||
|
||||
private readonly IPrototypeManager _prototypeManager;
|
||||
|
||||
public string TooltipText = string.Empty;
|
||||
|
||||
public ListViewSelectorWindow(IPrototypeManager prototypeManager)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
_prototypeManager = prototypeManager;
|
||||
}
|
||||
|
||||
public void PopulateList(List<string> items, bool isPrototypes)
|
||||
public void PopulateList(List<EntProtoId> items, bool isPrototypes)
|
||||
{
|
||||
ItemsContainer.RemoveAllChildren();
|
||||
|
||||
@@ -27,16 +30,16 @@ public partial class ListViewSelectorWindow : DefaultWindow
|
||||
{
|
||||
var button = new Button();
|
||||
var itemName = Loc.GetString($"ent-{item}");
|
||||
var itemDesc = string.Empty;
|
||||
|
||||
if (isPrototypes)
|
||||
if (isPrototypes && _prototypeManager.TryIndex<EntityPrototype>(item, out var itemPrototype))
|
||||
{
|
||||
if (_prototypeManager.TryIndex<EntityPrototype>(item, out var itemPrototype))
|
||||
{
|
||||
itemName = itemPrototype.Name;
|
||||
}
|
||||
itemName = itemPrototype.Name;
|
||||
itemDesc = itemPrototype.Description;
|
||||
}
|
||||
|
||||
button.Text = itemName;
|
||||
button.TooltipSupplier = _ => new RecipeTooltip(itemDesc);
|
||||
|
||||
button.OnPressed += _ => ItemSelected?.Invoke(item, items.IndexOf(item));
|
||||
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
using System.Linq;
|
||||
using Content.Client.Construction;
|
||||
using Content.Shared.Construction.Prototypes;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Client.Placement;
|
||||
using Robust.Client.Utility;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.Client._White.Cult.UI.StructureRadial;
|
||||
|
||||
public sealed class CultPylonPlacementHijack : PlacementHijack
|
||||
{
|
||||
private readonly ConstructionSystem _constructionSystem;
|
||||
private readonly IEntityManager _entMan;
|
||||
private readonly ConstructionPrototype? _prototype;
|
||||
private readonly EntityUid _player;
|
||||
|
||||
public override bool CanRotate { get; }
|
||||
|
||||
public CultPylonPlacementHijack(ConstructionPrototype? prototype, IEntityManager entMan, EntityUid player)
|
||||
{
|
||||
_prototype = prototype;
|
||||
_entMan = entMan;
|
||||
_player = player;
|
||||
_constructionSystem = entMan.System<ConstructionSystem>();
|
||||
CanRotate = prototype?.CanRotate ?? true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool HijackPlacementRequest(EntityCoordinates coordinates)
|
||||
{
|
||||
if (_prototype == null)
|
||||
return true;
|
||||
|
||||
if (CheckForStructure(coordinates))
|
||||
{
|
||||
var popup = _entMan.System<SharedPopupSystem>();
|
||||
popup.PopupClient(Loc.GetString("cult-structure-craft-another-structure-nearby"), _player, _player);
|
||||
return true;
|
||||
}
|
||||
|
||||
_constructionSystem.ClearAllGhosts();
|
||||
var dir = Manager.Direction;
|
||||
_constructionSystem.SpawnGhost(_prototype, coordinates, dir);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool CheckForStructure(EntityCoordinates coordinates)
|
||||
{
|
||||
var lookupSystem = _entMan.System<EntityLookupSystem>();
|
||||
var entities = lookupSystem.GetEntitiesInRange(coordinates, 10f);
|
||||
foreach (var ent in entities)
|
||||
{
|
||||
if (!_entMan.TryGetComponent<MetaDataComponent>(ent, out var metadata))
|
||||
continue;
|
||||
|
||||
if (metadata.EntityPrototype?.ID is "CultPylon")
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool HijackDeletion(EntityUid entity)
|
||||
{
|
||||
if (IoCManager.Resolve<IEntityManager>().HasComponent<ConstructionGhostComponent>(entity))
|
||||
{
|
||||
_constructionSystem.ClearGhost(entity.GetHashCode());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void StartHijack(PlacementManager manager)
|
||||
{
|
||||
base.StartHijack(manager);
|
||||
manager.CurrentTextures = _prototype?.Layers.Select(sprite => sprite.DirFrame0()).ToList();
|
||||
}
|
||||
}
|
||||
@@ -86,43 +86,23 @@ public sealed class StructureCraftBoundUserInterface : BoundUserInterface
|
||||
if (construct == null)
|
||||
return;
|
||||
|
||||
var player = _player.LocalPlayer?.ControlledEntity;
|
||||
var player = _player.LocalEntity;
|
||||
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
if (construct.ID == "CultPylon" && CheckForStructure(player, id))
|
||||
{
|
||||
var popup = _entMan.System<SharedPopupSystem>();
|
||||
popup.PopupClient(Loc.GetString("cult-structure-craft-another-structure-nearby"), player.Value, player.Value);
|
||||
return;
|
||||
}
|
||||
PlacementHijack hijack;
|
||||
|
||||
var constructSystem = _systemManager.GetEntitySystem<ConstructionSystem>();
|
||||
var hijack = new ConstructionPlacementHijack(constructSystem, construct);
|
||||
if (construct.ID == "CultPylon")
|
||||
{
|
||||
hijack = new CultPylonPlacementHijack(construct, _entMan, player.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
var constructSystem = _systemManager.GetEntitySystem<ConstructionSystem>();
|
||||
hijack = new ConstructionPlacementHijack(constructSystem, construct);
|
||||
}
|
||||
|
||||
_placement.BeginPlacing(newObj, hijack);
|
||||
}
|
||||
|
||||
private bool CheckForStructure(EntityUid? uid, string id)
|
||||
{
|
||||
if (uid == null)
|
||||
return false;
|
||||
|
||||
if (!_entMan.TryGetComponent<TransformComponent>(uid, out var transform))
|
||||
return false;
|
||||
|
||||
var lookupSystem = _entMan.System<EntityLookupSystem>();
|
||||
var entities = lookupSystem.GetEntitiesInRange(transform.Coordinates, 15f);
|
||||
foreach (var ent in entities)
|
||||
{
|
||||
if (!_entMan.TryGetComponent<MetaDataComponent>(ent, out var metadata))
|
||||
continue;
|
||||
|
||||
if (metadata.EntityPrototype?.ID == id)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,13 @@ public sealed class ChangelingRuleSystem : GameRuleSystem<ChangelingRuleComponen
|
||||
SubscribeLocalEvent<RoundRestartCleanupEvent>(ClearUsedNames);
|
||||
|
||||
SubscribeLocalEvent<ChangelingRuleComponent, ObjectivesTextGetInfoEvent>(OnObjectivesTextGetInfo);
|
||||
|
||||
SubscribeLocalEvent<ChangelingRoleComponent, GetBriefingEvent>(OnGetBriefing);
|
||||
}
|
||||
|
||||
private void OnGetBriefing(Entity<ChangelingRoleComponent> ent, ref GetBriefingEvent args)
|
||||
{
|
||||
args.Append(Loc.GetString("changeling-role-briefing-short"));
|
||||
}
|
||||
|
||||
protected override void ActiveTick(
|
||||
@@ -176,13 +183,6 @@ public sealed class ChangelingRuleSystem : GameRuleSystem<ChangelingRuleComponen
|
||||
PrototypeId = changelingRule.ChangelingPrototypeId
|
||||
}, mind);
|
||||
|
||||
var briefing = Loc.GetString("changeling-role-briefing-short");
|
||||
|
||||
_roleSystem.MindAddRole(mindId, new RoleBriefingComponent
|
||||
{
|
||||
Briefing = briefing
|
||||
}, mind, true);
|
||||
|
||||
_roleSystem.MindPlaySound(mindId, changelingRule.GreetSoundNotification, mind);
|
||||
SendChangelingBriefing(mindId);
|
||||
changelingRule.ChangelingMinds.Add(mindId);
|
||||
|
||||
@@ -24,6 +24,7 @@ public sealed class DoorSystem : SharedDoorSystem
|
||||
[Dependency] private readonly DoorBoltSystem _bolts = default!;
|
||||
[Dependency] private readonly AirtightSystem _airtightSystem = default!;
|
||||
[Dependency] private readonly PryingSystem _pryingSystem = default!;
|
||||
[Dependency] private readonly RunicDoorSystem _runicDoor = default!; // WD
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -142,6 +143,9 @@ public sealed class DoorSystem : SharedDoorSystem
|
||||
|
||||
var otherUid = args.OtherEntity;
|
||||
|
||||
if (!_runicDoor.CanBumpOpen(uid, otherUid)) // WD
|
||||
return;
|
||||
|
||||
if (Tags.HasTag(otherUid, "DoorBumpOpener"))
|
||||
TryOpen(uid, door, otherUid, quiet: door.State == DoorState.Denying);
|
||||
}
|
||||
@@ -201,6 +205,9 @@ public sealed class DoorSystem : SharedDoorSystem
|
||||
{
|
||||
foreach (var other in PhysicsSystem.GetContactingEntities(uid, physics, approximate: true))
|
||||
{
|
||||
if (!_runicDoor.CanBumpOpen(uid, other)) // WD
|
||||
continue;
|
||||
|
||||
if (Tags.HasTag(other, "DoorBumpOpener") && TryOpen(uid, door, other, quiet: true))
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ public sealed class RevolutionaryRuleSystem : GameRuleSystem<RevolutionaryRuleCo
|
||||
if (CheckCommandLose())
|
||||
{
|
||||
// WD EDIT START
|
||||
// Basically check for all in once gamemode
|
||||
// Check for all in once gamemode
|
||||
if (_gameTicker.GetActiveGameRules().Where(HasComp<RampingStationEventSchedulerComponent>).Any())
|
||||
_roundEnd.DoRoundEndBehavior(RoundEndBehavior.ShuttleCall, component.ShuttleCallTime);
|
||||
else
|
||||
|
||||
@@ -11,12 +11,26 @@ public sealed class ReturnToBodyEui : BaseEui
|
||||
|
||||
private readonly MindComponent _mind;
|
||||
|
||||
private readonly EntityUid _mindId;
|
||||
|
||||
private readonly EntityUid? _transferTo;
|
||||
|
||||
public ReturnToBodyEui(MindComponent mind, SharedMindSystem mindSystem)
|
||||
{
|
||||
_mind = mind;
|
||||
_mindSystem = mindSystem;
|
||||
}
|
||||
|
||||
// WD START
|
||||
public ReturnToBodyEui(MindComponent mind, SharedMindSystem mindSystem, EntityUid mindId, EntityUid? transferTo)
|
||||
{
|
||||
_mind = mind;
|
||||
_mindSystem = mindSystem;
|
||||
_mindId = mindId;
|
||||
_transferTo = transferTo;
|
||||
}
|
||||
// WD END
|
||||
|
||||
public override void HandleMessage(EuiMessageBase msg)
|
||||
{
|
||||
base.HandleMessage(msg);
|
||||
@@ -28,6 +42,9 @@ public sealed class ReturnToBodyEui : BaseEui
|
||||
return;
|
||||
}
|
||||
|
||||
if (_transferTo != null) // WD
|
||||
_mindSystem.TransferTo(_mindId, _transferTo, mind: _mind);
|
||||
|
||||
_mindSystem.UnVisit(_mind.Session);
|
||||
|
||||
Close();
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using System.Numerics;
|
||||
using Content.Server._White.Other.ChangeThrowForceSystem;
|
||||
using Content.Server.Damage.Components;
|
||||
using Content.Server.Inventory;
|
||||
using Content.Server.Pulling;
|
||||
using Content.Server.Stack;
|
||||
using Content.Server.Stunnable;
|
||||
using Content.Shared._White.Cult.Systems;
|
||||
using Content.Shared._White.MagGloves;
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.Body.Part;
|
||||
@@ -40,6 +42,7 @@ namespace Content.Server.Hands.Systems
|
||||
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
||||
[Dependency] private readonly PullingSystem _pullingSystem = default!;
|
||||
[Dependency] private readonly ThrowingSystem _throwingSystem = default!;
|
||||
[Dependency] private readonly CultItemSystem _cultItem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -194,6 +197,11 @@ namespace Content.Server.Hands.Systems
|
||||
!_actionBlockerSystem.CanThrow(player, throwEnt))
|
||||
return false;
|
||||
|
||||
// WD EDIT START
|
||||
if (HasComp<DamageOtherOnHitComponent>(throwEnt) && !_cultItem.CanThrow(player, throwEnt))
|
||||
return false;
|
||||
// WD EDIT END
|
||||
|
||||
if (_timing.CurTime < hands.NextThrowTime)
|
||||
return false;
|
||||
hands.NextThrowTime = _timing.CurTime + hands.ThrowCooldown;
|
||||
|
||||
@@ -62,13 +62,14 @@ public sealed partial class CultRuleComponent : Component
|
||||
|
||||
public List<ConstructComponent> Constructs = new();
|
||||
|
||||
public CultWinCondition WinCondition;
|
||||
public CultWinCondition WinCondition = CultWinCondition.CultDraw;
|
||||
}
|
||||
|
||||
public enum CultWinCondition : byte
|
||||
{
|
||||
CultDraw,
|
||||
CultWin,
|
||||
CultFailure
|
||||
CultFailure,
|
||||
}
|
||||
|
||||
public sealed class CultNarsieSummoned : EntityEventArgs
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
using System.Linq;
|
||||
using Content.Server._Miracle.Components;
|
||||
using Content.Server._Miracle.GulagSystem;
|
||||
using Content.Server.Actions;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Rules;
|
||||
using Content.Server.NPC.Systems;
|
||||
using Content.Server.Roles;
|
||||
using Content.Server.Roles.Jobs;
|
||||
using Content.Server.RoundEnd;
|
||||
using Content.Server.Shuttles.Components;
|
||||
using Content.Server.StationEvents.Components;
|
||||
using Content.Server.Storage.EntitySystems;
|
||||
using Content.Shared.Body.Systems;
|
||||
using Content.Shared.Humanoid;
|
||||
@@ -25,6 +26,7 @@ using Robust.Shared.Random;
|
||||
using Content.Shared._White;
|
||||
using Content.Shared._White.Chaplain;
|
||||
using Content.Shared._White.Cult.Components;
|
||||
using Content.Shared._White.Cult.Systems;
|
||||
using Content.Shared.Mind;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
|
||||
@@ -47,6 +49,7 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
|
||||
[Dependency] private readonly SharedMindSystem _mindSystem = default!;
|
||||
[Dependency] private readonly ActionsSystem _actions = default!;
|
||||
[Dependency] private readonly GulagSystem _gulag = default!;
|
||||
[Dependency] private readonly BloodSpearSystem _bloodSpear = default!;
|
||||
|
||||
private ISawmill _sawmill = default!;
|
||||
|
||||
@@ -69,6 +72,13 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
|
||||
SubscribeLocalEvent<CultistComponent, ComponentInit>(OnCultistComponentInit);
|
||||
SubscribeLocalEvent<CultistComponent, ComponentRemove>(OnCultistComponentRemoved);
|
||||
SubscribeLocalEvent<CultistComponent, MobStateChangedEvent>(OnCultistsStateChanged);
|
||||
|
||||
SubscribeLocalEvent<CultistRoleComponent, GetBriefingEvent>(OnGetBriefing);
|
||||
}
|
||||
|
||||
private void OnGetBriefing(Entity<CultistRoleComponent> ent, ref GetBriefingEvent args)
|
||||
{
|
||||
args.Append(Loc.GetString("cult-role-briefing-short"));
|
||||
}
|
||||
|
||||
private void OnCultistsStateChanged(EntityUid uid, CultistComponent component, MobStateChangedEvent ev)
|
||||
@@ -130,7 +140,7 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
|
||||
if (!TryComp<MobStateComponent>(owner, out var mobState))
|
||||
continue;
|
||||
|
||||
if (_mobStateSystem.IsAlive(owner, mobState))
|
||||
if (!_mobStateSystem.IsDead(owner, mobState))
|
||||
{
|
||||
aliveCultists++;
|
||||
}
|
||||
@@ -140,7 +150,10 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
|
||||
return;
|
||||
|
||||
cultistsRule.WinCondition = CultWinCondition.CultFailure;
|
||||
_roundEndSystem.EndRound();
|
||||
|
||||
// Check for all in once gamemode
|
||||
if (!GameTicker.GetActiveGameRules().Where(HasComp<RampingStationEventSchedulerComponent>).Any())
|
||||
_roundEndSystem.EndRound();
|
||||
}
|
||||
|
||||
private void OnCultistComponentInit(EntityUid uid, CultistComponent component, ComponentInit args)
|
||||
@@ -165,6 +178,8 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
|
||||
}
|
||||
|
||||
UpdateCultistsAppearance(cultistsRule);
|
||||
|
||||
component.OriginalMind = (mindComponent.Mind.Value, Comp<MindComponent>(mindComponent.Mind.Value));
|
||||
}
|
||||
|
||||
private void OnCultistComponentRemoved(EntityUid uid, CultistComponent component, ComponentRemove args)
|
||||
@@ -177,6 +192,8 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
|
||||
|
||||
cultistsRule.CurrentCultists.Remove(component);
|
||||
|
||||
_bloodSpear.DetachSpearFromUser((uid, component));
|
||||
|
||||
foreach (var empower in component.SelectedEmpowers)
|
||||
{
|
||||
_actions.RemoveAction(uid, GetEntity(empower));
|
||||
@@ -438,7 +455,7 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
|
||||
PrototypeId = cultistRule.CultistRolePrototype
|
||||
};
|
||||
|
||||
_roleSystem.MindAddRole(mindId, cultistComponent);
|
||||
_roleSystem.MindAddRole(mindId, cultistComponent, mind);
|
||||
EnsureComp<CultistComponent>(playerEntity);
|
||||
|
||||
_factionSystem.RemoveFaction(playerEntity, "NanoTrasen", false);
|
||||
@@ -478,19 +495,27 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
|
||||
|
||||
_roundEndSystem.EndRound();
|
||||
|
||||
var query = EntityQueryEnumerator<MobStateComponent, MindContainerComponent, CultistComponent>();
|
||||
var query =
|
||||
EntityQueryEnumerator<MobStateComponent, MindContainerComponent, CultistComponent, TransformComponent>();
|
||||
|
||||
while (query.MoveNext(out var uid, out _, out var mindContainer, out _))
|
||||
List<Entity<MindContainerComponent, TransformComponent>> cultists = new();
|
||||
|
||||
while (query.MoveNext(out var uid, out _, out var mindContainer, out _, out var transform))
|
||||
{
|
||||
if (!mindContainer.HasMind || mindContainer.Mind is null)
|
||||
cultists.Add((uid, mindContainer, transform));
|
||||
}
|
||||
|
||||
foreach (var ent in cultists)
|
||||
{
|
||||
if (ent.Comp1.Mind is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var reaper = Spawn(CultRuleComponent.ReaperPrototype, Transform(uid).Coordinates);
|
||||
_mindSystem.TransferTo(mindContainer.Mind.Value, reaper);
|
||||
var reaper = Spawn(CultRuleComponent.ReaperPrototype, ent.Comp2.Coordinates);
|
||||
_mindSystem.TransferTo(ent.Comp1.Mind.Value, reaper);
|
||||
|
||||
_bodySystem.GibBody(uid);
|
||||
_bodySystem.GibBody(ent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ using Content.Shared.Popups;
|
||||
using Content.Shared.Tag;
|
||||
using Content.Shared._White.Cult;
|
||||
using Content.Shared._White.Cult.Pylon;
|
||||
using Content.Shared._White.Cult.Systems;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Audio;
|
||||
@@ -40,6 +41,8 @@ public sealed class PylonSystem : EntitySystem
|
||||
[Dependency] private readonly BloodstreamSystem _blood = default!;
|
||||
[Dependency] private readonly TurfSystem _turf = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly PointLightSystem _pointLight = default!;
|
||||
[Dependency] private readonly PhysicsSystem _physics = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -47,6 +50,15 @@ public sealed class PylonSystem : EntitySystem
|
||||
|
||||
SubscribeLocalEvent<SharedPylonComponent, InteractHandEvent>(OnInteract);
|
||||
SubscribeLocalEvent<SharedPylonComponent, ComponentInit>(OnInit);
|
||||
SubscribeLocalEvent<SharedPylonComponent, ConcealEvent>(OnConceal);
|
||||
}
|
||||
|
||||
private void OnConceal(Entity<SharedPylonComponent> ent, ref ConcealEvent args)
|
||||
{
|
||||
ent.Comp.Activated = !args.Conceal;
|
||||
UpdateAppearance(ent, ent.Comp);
|
||||
_pointLight.SetEnabled(ent, !args.Conceal);
|
||||
_physics.SetCanCollide(ent, !args.Conceal);
|
||||
}
|
||||
|
||||
private void OnInit(EntityUid uid, SharedPylonComponent component, ComponentInit args)
|
||||
@@ -172,7 +184,7 @@ public sealed class PylonSystem : EntitySystem
|
||||
if (player.AttachedEntity is not { Valid: true } playerEntity)
|
||||
continue;
|
||||
|
||||
if (!EntityManager.TryGetComponent<CultistComponent>(playerEntity, out _))
|
||||
if (!HasComp<CultistComponent>(playerEntity) && !HasComp<ConstructComponent>(playerEntity))
|
||||
continue;
|
||||
|
||||
if (_mobStateSystem.IsDead(playerEntity))
|
||||
@@ -221,12 +233,7 @@ public sealed class PylonSystem : EntitySystem
|
||||
|
||||
UpdateAppearance(uid, comp);
|
||||
|
||||
if (!TryComp<PointLightComponent>(uid, out var light))
|
||||
return;
|
||||
|
||||
#pragma warning disable RA0002
|
||||
light.Enabled = comp.Activated;
|
||||
#pragma warning restore RA0002
|
||||
_pointLight.SetEnabled(uid, comp.Activated);
|
||||
|
||||
var toggleMsg = Loc.GetString(comp.Activated ? "pylon-toggle-on" : "pylon-toggle-off");
|
||||
_popupSystem.PopupEntity(toggleMsg, uid);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Server.UserInterface;
|
||||
using Content.Shared._White.Cult.UI;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._White.Cult;
|
||||
|
||||
@@ -11,5 +12,5 @@ public sealed partial class RuneDrawerProviderComponent : Component
|
||||
public Enum UserInterfaceKey = ListViewSelectorUiKey.Key;
|
||||
|
||||
[DataField("runePrototypes")]
|
||||
public List<string> RunePrototypes = new();
|
||||
public List<EntProtoId> RunePrototypes = new();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.Emp;
|
||||
using Content.Server.EUI;
|
||||
using Content.Server._White.Cult.UI;
|
||||
using Content.Shared._White.Chaplain;
|
||||
using Content.Shared._White.Cult;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
@@ -17,12 +19,19 @@ using Content.Shared.Stacks;
|
||||
using Content.Shared.StatusEffect;
|
||||
using Content.Shared.Stunnable;
|
||||
using Content.Shared._White.Cult.Actions;
|
||||
using Content.Shared._White.Cult.Components;
|
||||
using Content.Shared._White.Cult.Systems;
|
||||
using Content.Shared._White.Cult.UI;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Cuffs.Components;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Maps;
|
||||
using Content.Shared.Mindshield.Components;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Player;
|
||||
using CultistComponent = Content.Shared._White.Cult.Components.CultistComponent;
|
||||
|
||||
@@ -36,6 +45,13 @@ public partial class CultSystem
|
||||
[Dependency] private readonly EuiManager _euiManager = default!;
|
||||
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
||||
[Dependency] private readonly TransformSystem _transform = default!;
|
||||
[Dependency] private readonly MapSystem _mapSystem = default!;
|
||||
[Dependency] private readonly TileSystem _tile = default!;
|
||||
[Dependency] private readonly BloodSpearSystem _bloodSpear = default!;
|
||||
[Dependency] private readonly PhysicsSystem _physics = default!;
|
||||
|
||||
private const string TileId = "CultFloor";
|
||||
private const string ConcealedTileId = "CultFloorConcealed";
|
||||
|
||||
public void InitializeActions()
|
||||
{
|
||||
@@ -44,8 +60,10 @@ public partial class CultSystem
|
||||
SubscribeLocalEvent<CultistComponent, CultShadowShacklesTargetActionEvent>(OnShadowShackles);
|
||||
SubscribeLocalEvent<CultistComponent, CultElectromagneticPulseInstantActionEvent>(OnElectromagneticPulse);
|
||||
SubscribeLocalEvent<CultistComponent, CultSummonCombatEquipmentTargetActionEvent>(OnSummonCombatEquipment);
|
||||
SubscribeLocalEvent<CultistComponent, CultConcealPresenceWorldActionEvent>(OnConcealPresence);
|
||||
SubscribeLocalEvent<CultistComponent, CultConcealInstantActionEvent>(OnConcealPresence);
|
||||
SubscribeLocalEvent<CultistComponent, CultRevealInstantActionEvent>(OnConcealPresence);
|
||||
SubscribeLocalEvent<CultistComponent, CultBloodRitesInstantActionEvent>(OnBloodRites);
|
||||
SubscribeLocalEvent<CultistComponent, CultBloodSpearRecallInstantActionEvent>(OnBloodSpearRecall);
|
||||
SubscribeLocalEvent<CultistComponent, CultTeleportTargetActionEvent>(OnTeleport);
|
||||
SubscribeLocalEvent<CultistComponent, CultStunTargetActionEvent>(OnStunTarget);
|
||||
SubscribeLocalEvent<CultistComponent, ActionGettingRemovedEvent>(OnActionRemoved);
|
||||
@@ -74,9 +92,15 @@ public partial class CultSystem
|
||||
private void OnStunTarget(EntityUid uid, CultistComponent component, CultStunTargetActionEvent args)
|
||||
{
|
||||
if (args.Target == uid || !TryComp<BloodstreamComponent>(args.Performer, out var bloodstream) ||
|
||||
HasComp<HolyComponent>(args.Target) || !TryComp<StatusEffectsComponent>(args.Target, out var status))
|
||||
!TryComp<StatusEffectsComponent>(args.Target, out var status))
|
||||
return;
|
||||
|
||||
if (HasComp<HolyComponent>(args.Target))
|
||||
{
|
||||
_popupSystem.PopupEntity("Священная сила препятствует магии.", args.Performer, args.Performer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (HasComp<MindShieldComponent>(args.Target))
|
||||
{
|
||||
_popupSystem.PopupEntity("Он имплантирован чипом защиты разума.", args.Performer, args.Performer);
|
||||
@@ -94,14 +118,23 @@ public partial class CultSystem
|
||||
|
||||
private void OnTeleport(EntityUid uid, CultistComponent component, CultTeleportTargetActionEvent args)
|
||||
{
|
||||
if (!TryComp<BloodstreamComponent>(args.Performer, out var bloodstream) || !TryComp<ActorComponent>(uid, out var actor))
|
||||
if (!TryComp<BloodstreamComponent>(args.Performer, out var bloodstream) ||
|
||||
!TryComp<ActorComponent>(uid, out var actor))
|
||||
return;
|
||||
|
||||
if (!TryComp<CultistComponent>(args.Target, out _) &&
|
||||
!(TryComp<MobStateComponent>(args.Target, out var mobStateComponent) &&
|
||||
mobStateComponent.CurrentState is not MobState.Alive))
|
||||
if (HasComp<HolyComponent>(args.Target))
|
||||
{
|
||||
_popupSystem.PopupEntity("Цель должна быть культистом или лежать.", args.Performer, args.Performer);
|
||||
_popupSystem.PopupEntity("Священная сила препятствует магии.", args.Performer, args.Performer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!HasComp<CultistComponent>(args.Target) && !HasComp<ConstructComponent>(args.Target) &&
|
||||
(!TryComp<MobStateComponent>(args.Target, out var mobStateComponent) ||
|
||||
mobStateComponent.CurrentState is MobState.Alive) &&
|
||||
(!TryComp<CuffableComponent>(args.Target, out var cuffable) || cuffable.Container.Count == 0))
|
||||
{
|
||||
_popupSystem.PopupEntity("Цель должна быть культистом, быть связанной или лежать.", args.Performer,
|
||||
args.Performer);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -147,25 +180,28 @@ public partial class CultSystem
|
||||
|
||||
totalBloodAmount += solutionContent.Quantity;
|
||||
|
||||
_bloodstreamSystem.TryModifyBloodLevel(uid, solutionContent.Quantity / 6f);
|
||||
_bloodstreamSystem.TryModifyBloodLevel(uid, solutionContent.Quantity / 6f, bloodstreamComponent);
|
||||
_solutionSystem.RemoveReagent((Entity<SolutionComponent>) solution, "Blood", FixedPoint2.MaxValue);
|
||||
|
||||
if (GetMissingBloodValue(bloodstreamComponent) == 0)
|
||||
/*if (GetMissingBloodValue(bloodstreamComponent) == 0)
|
||||
{
|
||||
breakLoop = true;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
if (totalBloodAmount == 0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
component.RitesBloodAmount += totalBloodAmount;
|
||||
|
||||
_audio.PlayPvs("/Audio/White/Cult/enter_blood.ogg", uid, AudioParams.Default);
|
||||
_damageableSystem.TryChangeDamage(uid, new DamageSpecifier(bruteDamageGroup, -20));
|
||||
_damageableSystem.TryChangeDamage(uid, new DamageSpecifier(burnDamageGroup, -20));
|
||||
|
||||
_popupSystem.PopupEntity(Loc.GetString("verb-blood-rites-message", ("blood", component.RitesBloodAmount)), uid,
|
||||
uid);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
@@ -174,10 +210,163 @@ public partial class CultSystem
|
||||
return bloodstreamComponent.BloodMaxVolume - bloodstreamComponent.BloodSolution!.Value.Comp.Solution.Volume;
|
||||
}
|
||||
|
||||
private void OnConcealPresence(EntityUid uid, CultistComponent component, CultConcealPresenceWorldActionEvent args)
|
||||
private void OnBloodSpearRecall(Entity<CultistComponent> ent, ref CultBloodSpearRecallInstantActionEvent args)
|
||||
{
|
||||
if (!TryComp<BloodstreamComponent>(args.Performer, out _))
|
||||
if (ent.Comp.BloodSpear == null)
|
||||
{
|
||||
_bloodSpear.DetachSpearFromUser(ent);
|
||||
return;
|
||||
}
|
||||
|
||||
var spear = ent.Comp.BloodSpear.Value;
|
||||
var xform = Transform(spear);
|
||||
var coords = _transform.GetWorldPosition(xform);
|
||||
var userCoords = _transform.GetWorldPosition(ent);
|
||||
var distance = (userCoords - coords).Length();
|
||||
if (distance > 10f)
|
||||
{
|
||||
_popupSystem.PopupEntity("Копьё слишком далеко!", ent, ent);
|
||||
return;
|
||||
}
|
||||
|
||||
TryComp<PhysicsComponent>(spear, out var physics);
|
||||
_physics.SetBodyType(spear, BodyType.Dynamic, body: physics, xform: xform);
|
||||
_transform.AttachToGridOrMap(spear, xform);
|
||||
_transform.SetWorldPosition(xform, userCoords);
|
||||
_handsSystem.TryPickupAnyHand(ent, spear, animate: false);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnConcealPresence(EntityUid uid, CultistComponent component, CultConcealPresenceInstantActionEvent args)
|
||||
{
|
||||
if (!TryComp<BloodstreamComponent>(args.Performer, out var bloodstream) ||
|
||||
!TryComp<TransformComponent>(args.Performer, out var xform))
|
||||
return;
|
||||
|
||||
var conceal = args is CultConcealInstantActionEvent;
|
||||
|
||||
var concealableQuery = GetEntityQuery<ConcealableComponent>();
|
||||
var appearanceQuery = GetEntityQuery<AppearanceComponent>();
|
||||
|
||||
const float radius = 5f;
|
||||
|
||||
var entitiesInRange = _lookup.GetEntitiesInRange(_transform.GetMapCoordinates(xform), radius);
|
||||
|
||||
var success = false;
|
||||
|
||||
// Conceal/Reveal runes and structures
|
||||
foreach (var ent in entitiesInRange)
|
||||
{
|
||||
if (!concealableQuery.TryGetComponent(ent, out var concealable) ||
|
||||
!appearanceQuery.TryGetComponent(ent, out var appearance) ||
|
||||
!EntityManager.MetaQuery.TryGetComponent(ent, out var meta))
|
||||
continue;
|
||||
|
||||
if (concealable.Concealed == conceal)
|
||||
continue;
|
||||
|
||||
_appearanceSystem.SetData(ent, ConcealableAppearance.Concealed, conceal, appearance);
|
||||
|
||||
concealable.Concealed = conceal;
|
||||
|
||||
RaiseLocalEvent(ent, new ConcealEvent(conceal));
|
||||
|
||||
if (concealable.ChangeMeta)
|
||||
{
|
||||
if (conceal)
|
||||
{
|
||||
_metaDataSystem.SetEntityName(ent, concealable.ConcealedName, meta);
|
||||
_metaDataSystem.SetEntityDescription(ent, concealable.ConcealedDesc, meta);
|
||||
}
|
||||
else
|
||||
{
|
||||
_metaDataSystem.SetEntityName(ent, concealable.RevealedName, meta);
|
||||
_metaDataSystem.SetEntityDescription(ent, concealable.RevealedDesc, meta);
|
||||
}
|
||||
}
|
||||
|
||||
Dirty(ent, concealable, meta);
|
||||
|
||||
success = true;
|
||||
}
|
||||
|
||||
var gridUid = xform.GridUid;
|
||||
var pos = xform.Coordinates;
|
||||
|
||||
var cultTileDef = (ContentTileDefinition) _tileDefinition[TileId];
|
||||
var concealedTileDef = (ContentTileDefinition) _tileDefinition[ConcealedTileId];
|
||||
|
||||
// Conceal/Reveal tiles
|
||||
if (TryComp(gridUid, out MapGridComponent? mapGrid))
|
||||
{
|
||||
var tileRefs = _mapSystem.GetLocalTilesIntersecting(gridUid.Value, mapGrid,
|
||||
new Box2(pos.Position + new Vector2(-radius, -radius), pos.Position + new Vector2(radius, radius)));
|
||||
|
||||
foreach (var tile in tileRefs)
|
||||
{
|
||||
var tilePos = _turf.GetTileCenter(tile);
|
||||
|
||||
if (!pos.InRange(EntityManager, _transform, tilePos, radius))
|
||||
continue;
|
||||
|
||||
if (conceal)
|
||||
{
|
||||
if (tile.Tile.TypeId != cultTileDef.TileId)
|
||||
continue;
|
||||
|
||||
_tile.ReplaceTile(tile, concealedTileDef);
|
||||
success = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tile.Tile.TypeId != concealedTileDef.TileId)
|
||||
continue;
|
||||
|
||||
_tile.ReplaceTile(tile, cultTileDef);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
_audio.PlayPvs(conceal ? "/Audio/White/Cult/smoke.ogg" : "/Audio/White/Cult/enter_blood.ogg", uid,
|
||||
AudioParams.Default.WithMaxDistance(2f));
|
||||
_bloodstreamSystem.TryModifyBloodLevel(uid, -2, bloodstream, createPuddle: false);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
var spellQuery = GetEntityQuery<ConcealPresenceSpellComponent>();
|
||||
var actionQuery = GetEntityQuery<InstantActionComponent>();
|
||||
|
||||
// Alter spell concealing/revealing state
|
||||
foreach (var empower in component.SelectedEmpowers)
|
||||
{
|
||||
if (empower == null)
|
||||
continue;
|
||||
|
||||
var ent = GetEntity(empower.Value);
|
||||
|
||||
if (!spellQuery.TryGetComponent(ent, out var spell) ||
|
||||
!actionQuery.TryGetComponent(ent, out var action))
|
||||
continue;
|
||||
|
||||
if (conceal)
|
||||
{
|
||||
spell.Revealing = true;
|
||||
action.Icon = spell.RevealIcon;
|
||||
action.Event = spell.RevealEvent;
|
||||
}
|
||||
else
|
||||
{
|
||||
spell.Revealing = false;
|
||||
action.Icon = spell.ConcealIcon;
|
||||
action.Event = spell.ConcealEvent;
|
||||
}
|
||||
|
||||
Dirty(ent, action);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSummonCombatEquipment(
|
||||
@@ -300,7 +489,7 @@ public partial class CultSystem
|
||||
var xform = Transform(args.Performer).Coordinates;
|
||||
var dagger = _entityManager.SpawnEntity(RitualDaggerPrototypeId, xform);
|
||||
|
||||
_bloodstreamSystem.TryModifyBloodLevel(args.Performer, -20, bloodstreamComponent, false);
|
||||
_bloodstreamSystem.TryModifyBloodLevel(args.Performer, -10, bloodstreamComponent, false);
|
||||
_handsSystem.TryPickupAnyHand(args.Performer, dagger);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
@@ -10,10 +10,12 @@ using Content.Server.Hands.Systems;
|
||||
using Content.Server.Weapons.Ranged.Systems;
|
||||
using Content.Server._White.Cult.GameRule;
|
||||
using Content.Server._White.Cult.Runes.Comps;
|
||||
using Content.Server._White.Cult.UI;
|
||||
using Content.Server.Bible.Components;
|
||||
using Content.Server.Chemistry.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.Fluids.Components;
|
||||
using Content.Server.Ghost;
|
||||
using Content.Shared._White.Chaplain;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Cuffs.Components;
|
||||
@@ -36,10 +38,13 @@ using Content.Shared._White.Cult.Components;
|
||||
using Content.Shared._White.Cult.Runes;
|
||||
using Content.Shared._White.Cult.UI;
|
||||
using Content.Shared.Cuffs;
|
||||
using Content.Shared.GameTicking;
|
||||
using Content.Shared.Mindshield.Components;
|
||||
using Content.Shared.Pulling;
|
||||
using Content.Shared.UserInterface;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Components;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Physics.Events;
|
||||
@@ -92,7 +97,8 @@ public sealed partial class CultSystem : EntitySystem
|
||||
SubscribeLocalEvent<CultEmpowerComponent, ActivateInWorldEvent>(OnActiveInWorld);
|
||||
|
||||
// UI
|
||||
SubscribeLocalEvent<RuneDrawerProviderComponent, UseInHandEvent>(OnRuneDrawerUseInHand);
|
||||
SubscribeLocalEvent<RuneDrawerProviderComponent, ActivatableUIOpenAttemptEvent>(OnRuneDrawAttempt);
|
||||
SubscribeLocalEvent<RuneDrawerProviderComponent, BeforeActivatableUIOpenEvent>(BeforeRuneDraw);
|
||||
SubscribeLocalEvent<RuneDrawerProviderComponent, ListViewItemSelectedMessage>(OnRuneSelected);
|
||||
SubscribeLocalEvent<CultTeleportRuneProviderComponent, TeleportRunesListWindowItemSelectedMessage>(
|
||||
OnTeleportRuneSelected);
|
||||
@@ -107,6 +113,8 @@ public sealed partial class CultSystem : EntitySystem
|
||||
SubscribeLocalEvent<CultRuneBaseComponent, CultEraseEvent>(OnErase);
|
||||
SubscribeLocalEvent<CultRuneBaseComponent, StartCollideEvent>(HandleCollision);
|
||||
|
||||
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundRestart);
|
||||
|
||||
InitializeBuffSystem();
|
||||
InitializeNarsie();
|
||||
InitializeSoulShard();
|
||||
@@ -134,30 +142,30 @@ public sealed partial class CultSystem : EntitySystem
|
||||
|
||||
private readonly SoundPathSpecifier _magic = new("/Audio/White/Cult/magic.ogg");
|
||||
|
||||
private readonly SoundPathSpecifier _apocRuneStartDrawing = new("/Audio/White/Cult/startdraw.ogg");
|
||||
private readonly SoundPathSpecifier _apocRuneEndDrawing = new("/Audio/White/Cult/finisheddraw.ogg");
|
||||
private readonly SoundPathSpecifier _narsie40Sec = new("/Audio/White/Cult/40sec.ogg");
|
||||
|
||||
private Entity<AudioComponent>? _narsieSummonningAudio = null;
|
||||
|
||||
private void OnRoundRestart(RoundRestartCleanupEvent ev)
|
||||
{
|
||||
CultRuneReviveComponent.ChargesLeft = 3;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rune draw start ----
|
||||
*/
|
||||
|
||||
private void OnRuneDrawerUseInHand(EntityUid uid, RuneDrawerProviderComponent component, UseInHandEvent args)
|
||||
private void OnRuneDrawAttempt(Entity<RuneDrawerProviderComponent> ent, ref ActivatableUIOpenAttemptEvent args)
|
||||
{
|
||||
if (!_ui.TryGetUi(uid, component.UserInterfaceKey, out _))
|
||||
return;
|
||||
|
||||
if (!TryComp<ActorComponent>(args.User, out var actorComponent))
|
||||
return;
|
||||
|
||||
if (!HasComp<CultistComponent>(args.User))
|
||||
return;
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
if (_ui.TryGetUi(uid, ListViewSelectorUiKey.Key, out var bui))
|
||||
{
|
||||
_ui.SetUiState(bui, new ListViewBUIState(component.RunePrototypes, false));
|
||||
_ui.OpenUi(bui, actorComponent.PlayerSession);
|
||||
}
|
||||
private void BeforeRuneDraw(Entity<RuneDrawerProviderComponent> ent, ref BeforeActivatableUIOpenEvent args)
|
||||
{
|
||||
if (_ui.TryGetUi(ent, ListViewSelectorUiKey.Key, out var bui))
|
||||
_ui.SetUiState(bui, new ListViewBUIState(ent.Comp.RunePrototypes, true));
|
||||
}
|
||||
|
||||
private void OnRuneSelected(EntityUid uid, RuneDrawerProviderComponent component, ListViewItemSelectedMessage args)
|
||||
@@ -185,16 +193,20 @@ public sealed partial class CultSystem : EntitySystem
|
||||
if (HasComp<CultBuffComponent>(whoCalled))
|
||||
_timeToDraw /= 2;
|
||||
|
||||
if (runePrototype == ApocalypseRunePrototypeId)
|
||||
{
|
||||
_timeToDraw = 120.0f;
|
||||
_chat.DispatchGlobalAnnouncement(Loc.GetString("cult-started-drawing-rune-end"), "CULT", true,
|
||||
_apocRuneStartDrawing, colorOverride: Color.DarkRed);
|
||||
}
|
||||
|
||||
if (!IsAllowedToDraw(whoCalled))
|
||||
return false;
|
||||
|
||||
if (runePrototype == ApocalypseRunePrototypeId)
|
||||
{
|
||||
if (!_mindSystem.TryGetMind(whoCalled, out _, out var mind) ||
|
||||
mind.Session is not { } playerSession)
|
||||
return false;
|
||||
|
||||
_euiManager.OpenEui(new ApocalypseRuneEui(whoCalled, _entityManager), playerSession);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
var ev = new CultDrawEvent
|
||||
{
|
||||
Rune = runePrototype
|
||||
@@ -769,7 +781,7 @@ public sealed partial class CultSystem : EntitySystem
|
||||
_chat.DispatchGlobalAnnouncement(Loc.GetString("cult-ritual-started"), "CULT", false,
|
||||
colorOverride: Color.DarkRed);
|
||||
|
||||
_audio.PlayGlobal(_narsie40Sec, Filter.Broadcast(), false, AudioParams.Default.WithLoop(true).WithVolume(0.15f));
|
||||
_narsieSummonningAudio = _audio.PlayGlobal(_narsie40Sec, Filter.Broadcast(), false, AudioParams.Default.WithLoop(true).WithVolume(0.15f));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -778,6 +790,8 @@ public sealed partial class CultSystem : EntitySystem
|
||||
{
|
||||
_doAfterAlreadyStarted = false;
|
||||
|
||||
_audio.Stop(_narsieSummonningAudio?.Owner, _narsieSummonningAudio?.Comp);
|
||||
|
||||
if (args.Cancelled)
|
||||
{
|
||||
_chat.DispatchGlobalAnnouncement(Loc.GetString("cult-ritual-prevented"), "CULT", false,
|
||||
@@ -790,13 +804,13 @@ public sealed partial class CultSystem : EntitySystem
|
||||
if (transform == null)
|
||||
return;
|
||||
|
||||
_entityManager.SpawnEntity(NarsiePrototypeId, transform.Value);
|
||||
|
||||
_chat.DispatchGlobalAnnouncement(Loc.GetString("cult-narsie-summoned"), "CULT", true, _apocRuneEndDrawing,
|
||||
colorOverride: Color.DarkRed);
|
||||
|
||||
var ev = new CultNarsieSummoned();
|
||||
RaiseLocalEvent(ev);
|
||||
|
||||
_entityManager.SpawnEntity(NarsiePrototypeId, transform.Value);
|
||||
|
||||
//_chat.DispatchGlobalAnnouncement(Loc.GetString("cult-narsie-summoned"), "CULT", true, _apocRuneEndDrawing,
|
||||
// colorOverride: Color.DarkRed);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -852,6 +866,27 @@ public sealed partial class CultSystem : EntitySystem
|
||||
CultRuneReviveComponent.ChargesLeft--;
|
||||
|
||||
_entityManager.EventBus.RaiseLocalEvent(target, new RejuvenateEvent());
|
||||
|
||||
EntityUid? transferTo = null;
|
||||
|
||||
if (!_mindSystem.TryGetMind(target, out var mindId, out var mind))
|
||||
{
|
||||
if (!TryComp<CultistComponent>(target, out var cultist) || cultist.OriginalMind == null)
|
||||
return true;
|
||||
|
||||
(mindId, mind) = cultist.OriginalMind.Value;
|
||||
|
||||
transferTo = target;
|
||||
}
|
||||
|
||||
if (mind.Session is not { } playerSession)
|
||||
return true;
|
||||
|
||||
// notify them they're being revived.
|
||||
if (mind.CurrentEntity != target)
|
||||
{
|
||||
_euiManager.OpenEui(new ReturnToBodyEui(mind, _mindSystem, mindId, transferTo), playerSession);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1258,6 +1293,8 @@ public sealed partial class CultSystem : EntitySystem
|
||||
return;
|
||||
}
|
||||
|
||||
var damage = 10;
|
||||
|
||||
if (rune == ApocalypseRunePrototypeId)
|
||||
{
|
||||
if (!_entityManager.TryGetComponent(uid, out TransformComponent? transComp))
|
||||
@@ -1265,6 +1302,7 @@ public sealed partial class CultSystem : EntitySystem
|
||||
return;
|
||||
}
|
||||
|
||||
damage = 40;
|
||||
var pos = transComp.MapPosition;
|
||||
var x = (int) pos.X;
|
||||
var y = (int) pos.Y;
|
||||
@@ -1273,7 +1311,7 @@ public sealed partial class CultSystem : EntitySystem
|
||||
"CULT", true, _apocRuneEndDrawing, colorOverride: Color.DarkRed);
|
||||
}
|
||||
|
||||
var damageSpecifier = new DamageSpecifier(_prototypeManager.Index<DamageTypePrototype>("Slash"), 10);
|
||||
var damageSpecifier = new DamageSpecifier(_prototypeManager.Index<DamageTypePrototype>("Slash"), damage);
|
||||
_damageableSystem.TryChangeDamage(uid, damageSpecifier, true, false);
|
||||
|
||||
_xform.AttachToGridOrMap(_entityManager.SpawnEntity(rune, transform.Value));
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Linq;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Shared._White.Cult;
|
||||
using Content.Shared._White.Cult.Components;
|
||||
using Content.Shared._White.Cult.UI;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.Player;
|
||||
@@ -16,6 +17,7 @@ public sealed partial class CultSystem
|
||||
SubscribeLocalEvent<CultistComponent, CultEmpowerSelectedBuiMessage>(OnCultistEmpowerSelected);
|
||||
SubscribeLocalEvent<CultistComponent, CultEmpowerRemoveBuiMessage>(OnCultistEmpowerRemove);
|
||||
SubscribeLocalEvent<CultistComponent, SpellCreatedEvent>(OnSpellCreated);
|
||||
SubscribeLocalEvent<CultistComponent, CultistFactoryItemSelectedMessage>(OnBloodRitesSelected);
|
||||
}
|
||||
|
||||
private void OnCultistEmpowerRemove(Entity<CultistComponent> ent, ref CultEmpowerRemoveBuiMessage args)
|
||||
@@ -28,7 +30,7 @@ public sealed partial class CultSystem
|
||||
|
||||
private void OnSpellCreated(EntityUid ent, CultistComponent comp, SpellCreatedEvent args)
|
||||
{
|
||||
if (args.Cancelled || comp.SelectedEmpowers.Count >= 1)
|
||||
if (args.Cancelled || comp.SelectedEmpowers.Count >= 2)
|
||||
return;
|
||||
|
||||
var action = CultistComponent.CultistActions.FirstOrDefault(x => x.Equals(args.Spell));
|
||||
@@ -55,7 +57,7 @@ public sealed partial class CultSystem
|
||||
if (action == null)
|
||||
return;
|
||||
|
||||
if (comp.SelectedEmpowers.Count >= 1)
|
||||
if (comp.SelectedEmpowers.Count >= 2)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("verb-spell-create-too-much"), ent, ent);
|
||||
return;
|
||||
@@ -98,8 +100,24 @@ public sealed partial class CultSystem
|
||||
}
|
||||
};
|
||||
|
||||
var bloodRitesVerb = new Verb
|
||||
{
|
||||
Text = Loc.GetString("verb-blood-rites-text"),
|
||||
Message = Loc.GetString("verb-blood-rites-message", ("blood", ent.Comp.RitesBloodAmount)),
|
||||
Category = VerbCategory.Cult,
|
||||
Act = () =>
|
||||
{
|
||||
if (!_ui.TryGetUi(ent, BloodRitesUi.Key, out var bui))
|
||||
return;
|
||||
|
||||
_ui.SetUiState(bui, new CultistFactoryBUIState(ent.Comp.BloodRites));
|
||||
_ui.OpenUi(bui, actor.PlayerSession);
|
||||
}
|
||||
};
|
||||
|
||||
args.Verbs.Add(createSpellVerb);
|
||||
args.Verbs.Add(removeSpellVerb);
|
||||
args.Verbs.Add(bloodRitesVerb);
|
||||
}
|
||||
|
||||
private void RemoveSpell(Entity<CultistComponent> ent, ICommonSession session)
|
||||
@@ -112,4 +130,36 @@ public sealed partial class CultSystem
|
||||
|
||||
_ui.TryOpen(ent, CultEmpowerRemoveUiKey.Key, session);
|
||||
}
|
||||
|
||||
private void OnBloodRitesSelected(Entity<CultistComponent> ent, ref CultistFactoryItemSelectedMessage args)
|
||||
{
|
||||
if (!_prototypeManager.TryIndex<CultistFactoryProductionPrototype>(args.Item, out var prototype))
|
||||
return;
|
||||
|
||||
if (ent.Comp.RitesBloodAmount < prototype.BloodCost)
|
||||
{
|
||||
var message = Loc.GetString("verb-blood-rites-no-blood", ("required", prototype.BloodCost),
|
||||
("blood", ent.Comp.RitesBloodAmount));
|
||||
_popupSystem.PopupEntity(message, ent, ent);
|
||||
return;
|
||||
}
|
||||
|
||||
var success = false;
|
||||
foreach (var item in prototype.Item)
|
||||
{
|
||||
var entity = Spawn(item, Transform(ent).Coordinates);
|
||||
if (_handsSystem.TryPickupAnyHand(ent, entity))
|
||||
{
|
||||
success = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
_popupSystem.PopupEntity(Loc.GetString("verb-blood-rites-no-hand"), ent, ent);
|
||||
QueueDel(entity);
|
||||
break;
|
||||
}
|
||||
|
||||
if (success)
|
||||
ent.Comp.RitesBloodAmount -= prototype.BloodCost;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
using Content.Server.Doors.Systems;
|
||||
using Content.Server.Cuffs;
|
||||
using Content.Server.Doors.Systems;
|
||||
using Content.Shared._White.Chaplain;
|
||||
using Content.Shared.Doors;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Stunnable;
|
||||
using Content.Shared._White.Cult;
|
||||
using Content.Shared._White.Cult.Components;
|
||||
using Content.Shared._White.Cult.Systems;
|
||||
using Content.Shared.Cuffs.Components;
|
||||
using Content.Shared.Doors.Components;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Content.Shared.Weapons.Melee.Components;
|
||||
using Content.Shared.Weapons.Melee.Events;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using CultistComponent = Content.Shared._White.Cult.Components.CultistComponent;
|
||||
|
||||
@@ -19,6 +25,9 @@ public sealed class RunicDoorSystem : EntitySystem
|
||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||
[Dependency] private readonly SharedStunSystem _stunSystem = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly OccluderSystem _occluder = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||
[Dependency] private readonly CuffableSystem _cuffable = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -27,6 +36,31 @@ public sealed class RunicDoorSystem : EntitySystem
|
||||
SubscribeLocalEvent<RunicDoorComponent, BeforeDoorOpenedEvent>(OnBeforeDoorOpened);
|
||||
SubscribeLocalEvent<RunicDoorComponent, BeforeDoorClosedEvent>(OnBeforeDoorClosed);
|
||||
SubscribeLocalEvent<RunicDoorComponent, AttackedEvent>(OnGetAttacked);
|
||||
SubscribeLocalEvent<RunicDoorComponent, ConcealEvent>(OnConceal);
|
||||
}
|
||||
|
||||
private void OnConceal(Entity<RunicDoorComponent> ent, ref ConcealEvent args)
|
||||
{
|
||||
if (!TryComp(ent, out MetaDataComponent? meta))
|
||||
return;
|
||||
|
||||
if (TryComp(ent, out PhysicsComponent? physics))
|
||||
_occluder.SetEnabled(ent, args.Conceal && physics.CanCollide, meta: meta);
|
||||
|
||||
if (TryComp(ent, out DoorComponent? door))
|
||||
{
|
||||
door.Occludes = args.Conceal;
|
||||
Dirty(ent, door, meta);
|
||||
}
|
||||
|
||||
if (!TryComp(ent, out MeleeSoundComponent? meleeSound) || meleeSound.SoundGroups == null)
|
||||
return;
|
||||
|
||||
meleeSound.SoundGroups["Brute"] = args.Conceal
|
||||
? new SoundPathSpecifier("/Audio/Weapons/smash.ogg")
|
||||
: new SoundCollectionSpecifier("GlassSmash");
|
||||
|
||||
Dirty(ent, meleeSound, meta);
|
||||
}
|
||||
|
||||
private void OnGetAttacked(Entity<RunicDoorComponent> ent, ref AttackedEvent args)
|
||||
@@ -79,7 +113,8 @@ public sealed class RunicDoorSystem : EntitySystem
|
||||
|
||||
_doorSystem.Deny(airlock);
|
||||
|
||||
if (!HasComp<HumanoidAppearanceComponent>(user) || HasComp<HolyComponent>(user))
|
||||
if (!HasComp<HumanoidAppearanceComponent>(user) || HasComp<HolyComponent>(user) ||
|
||||
TryComp(airlock, out ConcealableComponent? concealable) && concealable.Concealed)
|
||||
return false;
|
||||
|
||||
var direction = Transform(user).MapPosition.Position - Transform(airlock).MapPosition.Position;
|
||||
@@ -90,4 +125,11 @@ public sealed class RunicDoorSystem : EntitySystem
|
||||
_stunSystem.TryParalyze(user, TimeSpan.FromSeconds(3), true);
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool CanBumpOpen(EntityUid uid, EntityUid otherUid)
|
||||
{
|
||||
return !HasComp<RunicDoorComponent>(uid) || !HasComp<ConstructComponent>(otherUid) &&
|
||||
(!HasComp<CultistComponent>(otherUid) || !_mobState.IsAlive(otherUid) ||
|
||||
TryComp(otherUid, out CuffableComponent? cuffable) && _cuffable.GetAllCuffs(cuffable).Count > 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using Content.Shared.Interaction;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared._White.Cult;
|
||||
using Content.Shared._White.Cult.Structures;
|
||||
using Content.Shared._White.Cult.Systems;
|
||||
using Content.Shared._White.Cult.UI;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
@@ -28,6 +29,7 @@ public sealed class CultistFactorySystem : EntitySystem
|
||||
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly PhysicsSystem _physics = default!;
|
||||
|
||||
private const string RitualDaggerPrototypeId = "RitualDagger";
|
||||
|
||||
@@ -42,6 +44,12 @@ public sealed class CultistFactorySystem : EntitySystem
|
||||
SubscribeLocalEvent<CultistFactoryComponent, InteractUsingEvent>(TryToggleAnchor);
|
||||
SubscribeLocalEvent<CultistFactoryComponent, CultAnchorDoAfterEvent>(OnAnchorDoAfter);
|
||||
SubscribeLocalEvent<CultistFactoryComponent, ExaminedEvent>(OnExamine);
|
||||
SubscribeLocalEvent<CultistFactoryComponent, ConcealEvent>(OnConceal);
|
||||
}
|
||||
|
||||
private void OnConceal(Entity<CultistFactoryComponent> ent, ref ConcealEvent args)
|
||||
{
|
||||
_physics.SetCanCollide(ent, !args.Conceal);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
|
||||
61
Content.Server/_White/Cult/UI/ApocalypseRuneEui.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.DoAfter;
|
||||
using Content.Server.EUI;
|
||||
using Content.Shared._White.Cult.Runes;
|
||||
using Content.Shared._White.Cult.UI;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Eui;
|
||||
using Robust.Server.Audio;
|
||||
using Robust.Shared.Audio;
|
||||
|
||||
namespace Content.Server._White.Cult.UI;
|
||||
|
||||
public sealed class ApocalypseRuneEui : BaseEui
|
||||
{
|
||||
private readonly SoundPathSpecifier _apocRuneStartDrawing = new("/Audio/White/Cult/startdraw.ogg");
|
||||
private const string ApocalypseRunePrototypeId = "ApocalypseRune";
|
||||
|
||||
private readonly EntityUid _whoCalled;
|
||||
private readonly IEntityManager _entityManager;
|
||||
|
||||
public ApocalypseRuneEui(EntityUid whoCalled, IEntityManager entityManager)
|
||||
{
|
||||
_whoCalled = whoCalled;
|
||||
_entityManager = entityManager;
|
||||
}
|
||||
|
||||
public override void HandleMessage(EuiMessageBase msg)
|
||||
{
|
||||
base.HandleMessage(msg);
|
||||
|
||||
if (msg is not ApocalypseRuneDrawMessage {Accepted: true})
|
||||
{
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
var ev = new CultDrawEvent
|
||||
{
|
||||
Rune = ApocalypseRunePrototypeId
|
||||
};
|
||||
|
||||
var argsDoAfterEvent = new DoAfterArgs(_entityManager, _whoCalled, 120f, ev, _whoCalled)
|
||||
{
|
||||
BreakOnUserMove = true,
|
||||
NeedHand = true
|
||||
};
|
||||
|
||||
if (!_entityManager.System<DoAfterSystem>().TryStartDoAfter(argsDoAfterEvent))
|
||||
{
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
_entityManager.System<ChatSystem>().DispatchGlobalAnnouncement(Loc.GetString("cult-started-drawing-rune-end"),
|
||||
"CULT", true, _apocRuneStartDrawing, colorOverride: Color.DarkRed);
|
||||
|
||||
_entityManager.System<AudioSystem>().PlayPvs("/Audio/White/Cult/butcher.ogg", _whoCalled,
|
||||
AudioParams.Default.WithMaxDistance(2f));
|
||||
Close();
|
||||
}
|
||||
}
|
||||
@@ -123,10 +123,10 @@ public abstract class SharedTentacleGun : EntitySystem
|
||||
foreach (var activeItem in _handsSystem.EnumerateHeld(args.Embedded))
|
||||
{
|
||||
if(!TryComp<PhysicsComponent>(activeItem, out var physicsComponent))
|
||||
return;
|
||||
continue;
|
||||
|
||||
var coords = Transform(args.Embedded).Coordinates;
|
||||
_handsSystem.TryDrop(args.Embedded, coords);
|
||||
_handsSystem.TryDrop(args.Embedded, activeItem, coords);
|
||||
|
||||
var force = physicsComponent.Mass * 2.5f / 2;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using Content.Shared._White.Cult.Components;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.IdentityManagement;
|
||||
@@ -7,12 +8,15 @@ using Content.Shared.Inventory.VirtualItem;
|
||||
using Content.Shared.Localizations;
|
||||
using Robust.Shared.Input.Binding;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Shared.Hands.EntitySystems;
|
||||
|
||||
public abstract partial class SharedHandsSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly INetManager _net = default!; // WD
|
||||
|
||||
private void InitializeInteractions()
|
||||
{
|
||||
SubscribeAllEvent<RequestSetHandEvent>(HandleSetHand);
|
||||
@@ -95,7 +99,17 @@ public abstract partial class SharedHandsSystem : EntitySystem
|
||||
private bool DropPressed(ICommonSession? session, EntityCoordinates coords, EntityUid netEntity)
|
||||
{
|
||||
if (TryComp(session?.AttachedEntity, out HandsComponent? hands) && hands.ActiveHand != null)
|
||||
// WD EDIT START
|
||||
{
|
||||
if (HasComp<BoltBarrageComponent>(hands.ActiveHandEntity))
|
||||
{
|
||||
if (_net.IsServer)
|
||||
QueueDel(hands.ActiveHandEntity.Value);
|
||||
return false;
|
||||
}
|
||||
TryDrop(session.AttachedEntity.Value, hands.ActiveHand, coords, handsComp: hands);
|
||||
}
|
||||
// WD EDIT END
|
||||
|
||||
// always send to server.
|
||||
return false;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
|
||||
|
||||
namespace Content.Shared.Weapons.Melee.Components;
|
||||
@@ -8,6 +9,7 @@ namespace Content.Shared.Weapons.Melee.Components;
|
||||
/// Plays the specified sound upon receiving damage of the specified type.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[NetworkedComponent, AutoGenerateComponentState] // WD
|
||||
public sealed partial class MeleeSoundComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
@@ -16,6 +18,7 @@ public sealed partial class MeleeSoundComponent : Component
|
||||
/// </summary>
|
||||
[DataField("soundGroups",
|
||||
customTypeSerializer: typeof(PrototypeIdDictionarySerializer<SoundSpecifier, DamageGroupPrototype>))]
|
||||
[AutoNetworkedField] // WD
|
||||
public Dictionary<string, SoundSpecifier>? SoundGroups;
|
||||
|
||||
/// <summary>
|
||||
@@ -24,10 +27,12 @@ public sealed partial class MeleeSoundComponent : Component
|
||||
/// </summary>
|
||||
[DataField("soundTypes",
|
||||
customTypeSerializer: typeof(PrototypeIdDictionarySerializer<SoundSpecifier, DamageTypePrototype>))]
|
||||
[AutoNetworkedField] // WD
|
||||
public Dictionary<string, SoundSpecifier>? SoundTypes;
|
||||
|
||||
/// <summary>
|
||||
/// Sound that plays if no damage is done.
|
||||
/// </summary>
|
||||
[AutoNetworkedField] // WD
|
||||
[DataField("noDamageSound")] public SoundSpecifier? NoDamageSound;
|
||||
}
|
||||
|
||||
48
Content.Shared/_White/Body/BodyRejuvenateSystem.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System.Linq;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Systems;
|
||||
using Content.Shared.Rejuvenate;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._White.Body;
|
||||
|
||||
public sealed class BodyRejuvenateSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedBodySystem _body = default!;
|
||||
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<BodyComponent, RejuvenateEvent>(OnRejuvenate);
|
||||
}
|
||||
|
||||
private void OnRejuvenate(Entity<BodyComponent> ent, ref RejuvenateEvent args)
|
||||
{
|
||||
if (ent.Comp.Prototype == null)
|
||||
return;
|
||||
|
||||
var prototype = _prototypeManager.Index(ent.Comp.Prototype.Value);
|
||||
var protoSlots = prototype.Slots.Values.ToList();
|
||||
|
||||
foreach (var (id, component) in _body.GetBodyChildren(ent.Owner, ent.Comp))
|
||||
{
|
||||
foreach (var organSlot in component.Organs.Values)
|
||||
{
|
||||
if (!_container.TryGetContainer(id, SharedBodySystem.GetOrganContainerId(organSlot.Id),
|
||||
out var container))
|
||||
continue;
|
||||
|
||||
if (container.Count > 0)
|
||||
continue;
|
||||
|
||||
var organ = protoSlots.Where(x => x.Organs.ContainsKey(organSlot.Id))
|
||||
.Select(x => x.Organs[organSlot.Id]).FirstOrDefault();
|
||||
|
||||
TrySpawnInContainer(organ, id, SharedBodySystem.GetOrganContainerId(organSlot.Id), out _);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,10 +30,23 @@ public sealed partial class CultSummonCombatEquipmentTargetActionEvent : EntityT
|
||||
{
|
||||
}
|
||||
|
||||
public sealed partial class CultConcealPresenceWorldActionEvent : WorldTargetActionEvent
|
||||
[Virtual]
|
||||
public partial class CultConcealPresenceInstantActionEvent : InstantActionEvent
|
||||
{
|
||||
}
|
||||
|
||||
public sealed partial class CultConcealInstantActionEvent : CultConcealPresenceInstantActionEvent
|
||||
{
|
||||
}
|
||||
|
||||
public sealed partial class CultRevealInstantActionEvent : CultConcealPresenceInstantActionEvent
|
||||
{
|
||||
}
|
||||
|
||||
public sealed partial class CultBloodRitesInstantActionEvent : InstantActionEvent
|
||||
{
|
||||
}
|
||||
|
||||
public sealed partial class CultBloodSpearRecallInstantActionEvent : InstantActionEvent
|
||||
{
|
||||
}
|
||||
|
||||
17
Content.Shared/_White/Cult/Components/BloodSpearComponent.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._White.Cult.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class BloodSpearComponent : Component
|
||||
{
|
||||
[ViewVariables]
|
||||
public Entity<CultistComponent>? User;
|
||||
|
||||
[DataField]
|
||||
public EntProtoId Action;
|
||||
|
||||
[DataField]
|
||||
public SoundSpecifier ShatterSound = new SoundCollectionSpecifier("GlassBreak");
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Content.Shared._White.Cult.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class BoltBarrageComponent : Component
|
||||
{
|
||||
public bool Unremoveable = true;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using Content.Shared.Actions;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared._White.Cult.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class ConcealPresenceSpellComponent : Component
|
||||
{
|
||||
[ViewVariables]
|
||||
public bool Revealing;
|
||||
|
||||
[DataField(required: true), NonSerialized]
|
||||
public InstantActionEvent? ConcealEvent;
|
||||
|
||||
[DataField(required: true), NonSerialized]
|
||||
public InstantActionEvent? RevealEvent;
|
||||
|
||||
[DataField]
|
||||
public SpriteSpecifier? ConcealIcon;
|
||||
|
||||
[DataField]
|
||||
public SpriteSpecifier? RevealIcon;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared._White.Cult.Components;
|
||||
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class ConcealableComponent : Component
|
||||
{
|
||||
[ViewVariables, AutoNetworkedField]
|
||||
public bool Concealed;
|
||||
|
||||
[DataField]
|
||||
public bool ExaminableWhileConcealed;
|
||||
|
||||
[DataField]
|
||||
public bool IconSmooth;
|
||||
|
||||
[DataField]
|
||||
public bool InteractionOutline;
|
||||
|
||||
[DataField]
|
||||
public ResPath? ConcealedSprite;
|
||||
|
||||
[DataField]
|
||||
public ResPath? RevealedSprite;
|
||||
|
||||
[DataField]
|
||||
public bool ChangeMeta;
|
||||
|
||||
[DataField]
|
||||
public string ConcealedName = string.Empty;
|
||||
|
||||
[DataField]
|
||||
public string ConcealedDesc = string.Empty;
|
||||
|
||||
[DataField]
|
||||
public string RevealedName = string.Empty;
|
||||
|
||||
[DataField]
|
||||
public string RevealedDesc = string.Empty;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum ConcealableAppearance
|
||||
{
|
||||
Concealed
|
||||
}
|
||||
@@ -9,8 +9,8 @@ public sealed partial class CultEmpowerComponent : Component
|
||||
[DataField("isRune")]
|
||||
public bool IsRune;
|
||||
|
||||
public int MaxAllowedCultistActions = 4;
|
||||
public int MinRequiredCultistActions = 1;
|
||||
public int MaxAllowedCultistActions = 5;
|
||||
public int MinRequiredCultistActions = 2;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using System.Threading;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Mind;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
|
||||
namespace Content.Shared._White.Cult.Components;
|
||||
|
||||
@@ -8,7 +11,7 @@ namespace Content.Shared._White.Cult.Components;
|
||||
/// This is used for tagging a mob as a cultist.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class CultistComponent : Component
|
||||
public sealed partial class CultistComponent : ShowCultHudComponent
|
||||
{
|
||||
[DataField("greetSound", customTypeSerializer: typeof(SoundSpecifierTypeSerializer))]
|
||||
public SoundSpecifier? CultistGreetSound = new SoundPathSpecifier("/Audio/CultSounds/fart.ogg");
|
||||
@@ -21,12 +24,17 @@ public sealed partial class CultistComponent : Component
|
||||
[AutoNetworkedField]
|
||||
public List<NetEntity?> SelectedEmpowers = new();
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public FixedPoint2 RitesBloodAmount = FixedPoint2.Zero;
|
||||
|
||||
public static string SummonCultDaggerAction = "InstantActionSummonCultDagger";
|
||||
|
||||
public static string BloodRitesAction = "InstantActionBloodRites";
|
||||
|
||||
public static string EmpPulseAction = "InstantActionEmpPulse";
|
||||
|
||||
public static string ConcealPresenceAction = "InstantActionConcealPresence";
|
||||
|
||||
public static string CultTwistedConstructionAction = "ActionCultTwistedConstruction";
|
||||
|
||||
public static string CultTeleportAction = "ActionCultTeleport";
|
||||
@@ -40,6 +48,22 @@ public sealed partial class CultistComponent : Component
|
||||
public static List<string> CultistActions = new()
|
||||
{
|
||||
SummonCultDaggerAction, BloodRitesAction, CultTwistedConstructionAction, CultTeleportAction,
|
||||
CultSummonCombatEquipmentAction, CultStunAction, EmpPulseAction, CultShadowShacklesAction
|
||||
CultSummonCombatEquipmentAction, CultStunAction, EmpPulseAction, ConcealPresenceAction, CultShadowShacklesAction
|
||||
};
|
||||
|
||||
[DataField("bloodRites", customTypeSerializer: typeof(PrototypeIdListSerializer<CultistFactoryProductionPrototype>))]
|
||||
public List<string> BloodRites = new ()
|
||||
{
|
||||
"FactoryCultBloodSpear",
|
||||
"FactoryCultBloodBarrage"
|
||||
};
|
||||
|
||||
[ViewVariables, NonSerialized]
|
||||
public Entity<BloodSpearComponent>? BloodSpear;
|
||||
|
||||
[ViewVariables, NonSerialized]
|
||||
public EntityUid? BloodSpearActionEntity;
|
||||
|
||||
[ViewVariables, NonSerialized]
|
||||
public Entity<MindComponent>? OriginalMind;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared._White.Cult.Components;
|
||||
|
||||
[Virtual, RegisterComponent, NetworkedComponent]
|
||||
public partial class ShowCultHudComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -17,6 +17,9 @@ public sealed class CultistFactoryProductionPrototype : IPrototype
|
||||
|
||||
[DataField("name", required: true)]
|
||||
public string Name = default!;
|
||||
|
||||
[DataField]
|
||||
public int BloodCost;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
|
||||
80
Content.Shared/_White/Cult/Systems/BloodSpearSystem.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using Content.Shared._White.Cult.Components;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.StatusEffect;
|
||||
using Content.Shared.Stunnable;
|
||||
using Content.Shared.Throwing;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Shared._White.Cult.Systems;
|
||||
|
||||
public sealed class BloodSpearSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
|
||||
[Dependency] private readonly SharedStunSystem _stunSystem = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly INetManager _net = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<BloodSpearComponent, ComponentRemove>(OnRemove);
|
||||
SubscribeLocalEvent<BloodSpearComponent, GotEquippedHandEvent>(OnEquip);
|
||||
SubscribeLocalEvent<BloodSpearComponent, ThrowDoHitEvent>(OnThrowDoHit);
|
||||
}
|
||||
|
||||
private void OnThrowDoHit(Entity<BloodSpearComponent> ent, ref ThrowDoHitEvent args)
|
||||
{
|
||||
if (!TryComp(args.Target, out StatusEffectsComponent? status))
|
||||
return;
|
||||
|
||||
if(!_stunSystem.TryParalyze(args.Target, TimeSpan.FromSeconds(6), true, status))
|
||||
return;
|
||||
|
||||
if (_net.IsClient)
|
||||
return;
|
||||
|
||||
_audio.PlayPvs(ent.Comp.ShatterSound, Transform(ent).Coordinates);
|
||||
QueueDel(ent);
|
||||
}
|
||||
|
||||
private void OnEquip(Entity<BloodSpearComponent> ent, ref GotEquippedHandEvent args)
|
||||
{
|
||||
if (!TryComp(args.User, out CultistComponent? cultist))
|
||||
return;
|
||||
|
||||
Entity<CultistComponent> user = (args.User, cultist);
|
||||
|
||||
if (cultist.BloodSpear == ent && ent.Comp.User == user)
|
||||
return;
|
||||
|
||||
if (ent.Comp.User != null)
|
||||
DetachSpearFromUser(ent.Comp.User.Value);
|
||||
DetachSpearFromUser(user);
|
||||
AttachSpearToUser(user, ent);
|
||||
}
|
||||
|
||||
public void DetachSpearFromUser(Entity<CultistComponent> user)
|
||||
{
|
||||
_actionsSystem.RemoveAction(user, user.Comp.BloodSpearActionEntity);
|
||||
user.Comp.BloodSpearActionEntity = null;
|
||||
if (user.Comp.BloodSpear != null)
|
||||
user.Comp.BloodSpear.Value.Comp.User = null;
|
||||
user.Comp.BloodSpear = null;
|
||||
}
|
||||
|
||||
public void AttachSpearToUser(Entity<CultistComponent> user, Entity<BloodSpearComponent> spear)
|
||||
{
|
||||
_actionsSystem.AddAction(user, ref user.Comp.BloodSpearActionEntity, spear.Comp.Action);
|
||||
user.Comp.BloodSpear = spear;
|
||||
spear.Comp.User = user;
|
||||
}
|
||||
|
||||
private void OnRemove(Entity<BloodSpearComponent> ent, ref ComponentRemove args)
|
||||
{
|
||||
if (ent.Comp.User != null)
|
||||
DetachSpearFromUser(ent.Comp.User.Value);
|
||||
}
|
||||
}
|
||||
91
Content.Shared/_White/Cult/Systems/BoltBarrageSystem.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
using System.Linq;
|
||||
using Content.Shared._White.Cult.Components;
|
||||
using Content.Shared.Ghost;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Weapons.Ranged.Events;
|
||||
using Content.Shared.Weapons.Ranged.Systems;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Shared._White.Cult.Systems;
|
||||
|
||||
public sealed class BoltBarrageSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedHandsSystem _hands = default!;
|
||||
[Dependency] private readonly INetManager _net = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<BoltBarrageComponent, AttemptShootEvent>(OnShootAttempt);
|
||||
SubscribeLocalEvent<BoltBarrageComponent, GunShotEvent>(OnGunShot);
|
||||
SubscribeLocalEvent<BoltBarrageComponent, DroppedEvent>(OnDrop);
|
||||
SubscribeLocalEvent<BoltBarrageComponent, UnequippedHandEvent>(OnUnequipHand);
|
||||
SubscribeLocalEvent<BoltBarrageComponent, ContainerGettingRemovedAttemptEvent>(OnRemoveAttempt);
|
||||
SubscribeLocalEvent<BoltBarrageComponent, OnEmptyGunShotEvent>(OnEmptyShot);
|
||||
}
|
||||
|
||||
private void OnUnequipHand(Entity<BoltBarrageComponent> ent, ref UnequippedHandEvent args)
|
||||
{
|
||||
if (_net.IsServer && ent.Comp.Unremoveable)
|
||||
QueueDel(ent);
|
||||
}
|
||||
|
||||
private void OnRemoveAttempt(Entity<BoltBarrageComponent> ent, ref ContainerGettingRemovedAttemptEvent args)
|
||||
{
|
||||
if (!_timing.ApplyingState && ent.Comp.Unremoveable)
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
private void OnEmptyShot(Entity<BoltBarrageComponent> ent, ref OnEmptyGunShotEvent args)
|
||||
{
|
||||
if (_net.IsServer)
|
||||
QueueDel(ent);
|
||||
}
|
||||
|
||||
private void OnDrop(Entity<BoltBarrageComponent> ent, ref DroppedEvent args)
|
||||
{
|
||||
if (_net.IsServer)
|
||||
QueueDel(ent);
|
||||
}
|
||||
|
||||
private void OnGunShot(Entity<BoltBarrageComponent> ent, ref GunShotEvent args)
|
||||
{
|
||||
if (!TryComp(args.User, out HandsComponent? hands))
|
||||
return;
|
||||
|
||||
foreach (var hand in _hands.EnumerateHands(args.User, hands))
|
||||
{
|
||||
if (!hand.IsEmpty)
|
||||
continue;
|
||||
|
||||
ent.Comp.Unremoveable = false;
|
||||
_hands.SetActiveHand(args.User, hand, hands);
|
||||
_hands.TryPickup(args.User, ent, hand, false, false, hands);
|
||||
ent.Comp.Unremoveable = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnShootAttempt(Entity<BoltBarrageComponent> ent, ref AttemptShootEvent args)
|
||||
{
|
||||
if (!HasComp<CultistComponent>(args.User) && !HasComp<GhostComponent>(args.User))
|
||||
{
|
||||
args.Cancelled = true;
|
||||
args.Message = Loc.GetString("bolt-barrage-component-not-cultist");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_hands.EnumerateHands(args.User).Any(hand => hand.IsEmpty))
|
||||
return;
|
||||
|
||||
args.Cancelled = true;
|
||||
args.Message = Loc.GetString("bolt-barrage-component-no-empty-hand");
|
||||
}
|
||||
}
|
||||
38
Content.Shared/_White/Cult/Systems/ConcealableSystem.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using Content.Shared._White.Cult.Components;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Interaction.Events;
|
||||
|
||||
namespace Content.Shared._White.Cult.Systems;
|
||||
|
||||
public sealed class ConcealableSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ConcealableComponent, ExamineAttemptEvent>(OnExamine);
|
||||
SubscribeLocalEvent<ConcealableComponent, InteractionAttemptEvent>(OnInteract);
|
||||
}
|
||||
|
||||
private void OnInteract(Entity<ConcealableComponent> ent, ref InteractionAttemptEvent args)
|
||||
{
|
||||
if (ent.Comp is {Concealed: true, ExaminableWhileConcealed: false})
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
private void OnExamine(Entity<ConcealableComponent> ent, ref ExamineAttemptEvent args)
|
||||
{
|
||||
if (ent.Comp is {Concealed: true, ExaminableWhileConcealed: false})
|
||||
args.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ConcealEvent : EntityEventArgs
|
||||
{
|
||||
public bool Conceal;
|
||||
|
||||
public ConcealEvent(bool conceal)
|
||||
{
|
||||
Conceal = conceal;
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,15 @@ public sealed class CultItemSystem : EntitySystem
|
||||
_popupSystem.PopupClient(Loc.GetString("cult-item-component-pickup-fail", ("name", Name(uid))), uid, args.User);
|
||||
}
|
||||
|
||||
public bool CanThrow(EntityUid player, EntityUid throwEnt)
|
||||
{
|
||||
if (!HasComp<CultItemComponent>(throwEnt) || CanUse(player))
|
||||
return true;
|
||||
|
||||
_popupSystem.PopupEntity(Loc.GetString("cult-item-component-throw-fail"), player, player);
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool CanUse(EntityUid? uid)
|
||||
{
|
||||
return HasComp<CultistComponent>(uid) || HasComp<GhostComponent>(uid);
|
||||
|
||||
15
Content.Shared/_White/Cult/UI/ApocalypseRuneDrawMessage.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Content.Shared.Eui;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._White.Cult.UI;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class ApocalypseRuneDrawMessage : EuiMessageBase
|
||||
{
|
||||
public readonly bool Accepted;
|
||||
|
||||
public ApocalypseRuneDrawMessage(bool accepted)
|
||||
{
|
||||
Accepted = accepted;
|
||||
}
|
||||
}
|
||||
9
Content.Shared/_White/Cult/UI/BloodRitesUi.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._White.Cult.UI;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum BloodRitesUi
|
||||
{
|
||||
Key
|
||||
}
|
||||
@@ -12,10 +12,10 @@ public enum ListViewSelectorUiKey
|
||||
[Serializable, NetSerializable]
|
||||
public class ListViewBUIState : BoundUserInterfaceState
|
||||
{
|
||||
public List<string> Items { get; set; }
|
||||
public List<EntProtoId> Items { get; set; }
|
||||
public bool IsUsingPrototypes { get; set; }
|
||||
|
||||
public ListViewBUIState(List<string> items, bool isUsingPrototypes)
|
||||
public ListViewBUIState(List<EntProtoId> items, bool isUsingPrototypes)
|
||||
{
|
||||
Items = items;
|
||||
IsUsingPrototypes = isUsingPrototypes;
|
||||
|
||||
BIN
Resources/Audio/White/Cult/smoke.ogg
Normal file
BIN
Resources/Audio/White/Cult/wand_teleport.ogg
Normal file
@@ -1,12 +1,15 @@
|
||||
cult-role-greeting =
|
||||
cult-role-greeting =
|
||||
Вы - член культа!
|
||||
Ваши цели перечислены в меню персонажа.
|
||||
В ваш рюкзак были добавлены предметы, которые помогут вам.
|
||||
И помните - вы не единственный.
|
||||
Слава Нар`си!
|
||||
|
||||
cult-role-briefing-short = Используйте '^' для связи с другими членами культа.
|
||||
|
||||
cult-cond-cultwin = Культ одержал победу
|
||||
cult-cond-cultfailure = Экипаж уничтожил культ
|
||||
cult-cond-cultdraw = Ничейный исход
|
||||
|
||||
cultists-list-start = Культистами были:
|
||||
cultists-list-name = - [color=White]{ $name }[/color] ([color=gray]{ $user }[/color])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
pylon-toggle-on = Кристалл воспаряет над пьедесталом, начиная пульсировать
|
||||
pylon-toggle-off = Кристалл перестаёт пульсировать, опускаясь на пьедестал
|
||||
ent-CultPylon = пилон
|
||||
.desc = Мистический конструкция.
|
||||
.desc = Мистическая конструкция.
|
||||
|
||||
@@ -1,11 +1,28 @@
|
||||
ent-OfferingRune = руна предпонесения
|
||||
ent-OfferingRune = руна предпонесения
|
||||
.desc = Мгновенно превращает обычного члена экипажа в культиста, для чего требуется 2 культиста вокруг руны. Члена экипажа с имплантом защиты разума нельзя перевоплотить, можно только принести в жертву, для чего нужно 3 культиста, которые встанут вокруг руны. Если цель мертва, то она будет принесена в жертву, для чего требуется 1 культист.
|
||||
|
||||
ent-BuffRune = руна усиления
|
||||
.desc = При активации усиливает вас, уменьшая затраты и ускоряя процесс подготовки заклинаний крови и черчения рун.
|
||||
|
||||
ent-EmpoweringRune = руна могущества
|
||||
.desc = Позволяет культистам приготовить до 5 заклинаний крови.
|
||||
|
||||
ent-TeleportRune = руна телепортации
|
||||
.desc = Эта руна при использовании переносит всё, что находится на ней, к другой руне телепортации.
|
||||
|
||||
ent-SummoningRune = руна призыва
|
||||
.desc = Эта руна позволяет мгновенно призвать к руне любого несвязанного культиста. Для использования требуются 2 культиста, стоящих вокруг руны.
|
||||
|
||||
ent-ReviveRune = руна воскрешения
|
||||
.desc = Каждый раз, когда кого-то приносят в жертву на Руне Преподнесения, этой руне добавляется один глобальный заряд. Размещение трупа культиста на руне и её активация вернет его к жизни, расходуя при этом заряд.
|
||||
|
||||
ent-BarrierRune = руна барьера
|
||||
.desc = При активации на создаёт барьер, блокирующую проход. Может быть повторно активирована, чтобы отменить заклинание.
|
||||
|
||||
ent-BloodBoilRune = руна кипящей крови
|
||||
.desc = При активации отнимает у призывателей некоторое количество крови, чтобы отправить несколько разрушительных импульсов любому не-культисту поблизости. Когда эффект закончится, руна ненадолго подожжет все, что находится вокруг нее. Для активации требуются 3 культиста, стоящих вокруг руны.
|
||||
|
||||
ent-ApocalypseRune = ритуал пространственного разрыва
|
||||
.desc = Руна призыва Нар'Си.
|
||||
|
||||
runes-window-title = Руны
|
||||
|
||||
@@ -35,3 +35,9 @@ ent-ActionCultShadowShackles = Теневые Узы
|
||||
|
||||
ent-InstantActionEmpPulse = Электромагнитный Импульс
|
||||
.desc = Большое заклинание, которое позволяет пользователю направлять темную энергию в ЭМИ.
|
||||
|
||||
ent-InstantActionConcealPresence = Сокрытие Присутствия
|
||||
.desc = Многофункциональное заклинание, чередующееся между скрытием и обнаружением ближайших рун и структур культа.
|
||||
|
||||
ent-InstantActionRecallBloodSpear = Призвать Кровавое Копьё
|
||||
.desc = Призывает кровавое копье в вашу руку.
|
||||
|
||||
2
Resources/Locale/ru-RU/cult/bolt-barrage.ftl
Normal file
@@ -0,0 +1,2 @@
|
||||
bolt-barrage-component-no-empty-hand = Вам нужно иметь свободную руку, чтобы стрелять.
|
||||
bolt-barrage-component-not-cultist = Вы не умеете пользоваться магией.
|
||||
@@ -1,3 +1,4 @@
|
||||
cult-item-component-pickup-fail = Вы не можете подобрать {$name}
|
||||
cult-item-component-attack-fail = Оружие не позволяет вам атаковать
|
||||
cult-item-component-equip-fail = Вы не можете это надеть
|
||||
cult-item-component-throw-fail = Оружие не позволяет вам его бросить
|
||||
|
||||
@@ -9,3 +9,9 @@ ent-CultMirrorShield = зеркальный щит
|
||||
.desc = Щит с зеркалом на лицевой стороне, на котором изображен какой-то религиозный знак.
|
||||
ent-CultOuterArmor = бронированная мантия
|
||||
.desc = С первого взгляда кажется, что это простая мантия, но на ней имеется элементы брони.
|
||||
ent-ShadowShackles = теневые оковы
|
||||
.desc = Оковы, сковывающие запястья с помощью зловещей магии.
|
||||
ent-BloodSpear = кровавое копьё
|
||||
.desc = Ужасающее копьё, полностью состоящее из кристаллизованной крови.
|
||||
ent-BloodBarrage = залп кровавых снарядов
|
||||
.desc = Кровь за кровь.
|
||||
|
||||
4
Resources/Locale/ru-RU/cult/gui.ftl
Normal file
@@ -0,0 +1,4 @@
|
||||
apocalypse-rune-title = Вы готовы к финальной битве?
|
||||
apocalypse-rune-text = Это последний шаг к вызову Нар'Си; это долгий, болезненный ритуал, и экипаж будет предупрежден о вашем присутствии.
|
||||
apocalypse-rune-accept-button = Жизнь за Нар'Си!
|
||||
apocalypse-rune-deny-button = Нет
|
||||
@@ -1,4 +1,4 @@
|
||||
pylon-toggle-on = Кристалл воспаряет над пьедесталом, начиная пульсировать
|
||||
pylon-toggle-off = Кристалл перестаёт пульсировать, опускаясь на пьедестал
|
||||
ent-CultPylon = пилон
|
||||
.desc = Мистический конструкция.
|
||||
.desc = Мистическая конструкция.
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
verb-categories-cult = Культ
|
||||
|
||||
verb-spell-create-text = Создать заклинание крови
|
||||
verb-spell-create-message = Вы можете создать одно заклинание крови без руны могущества.
|
||||
verb-spell-create-too-much = Начертите руну могущества, чтобы создать больше одного заклинания крови.
|
||||
verb-spell-create-message = Вы можете создать два заклинания крови без руны могущества.
|
||||
verb-spell-create-too-much = Начертите руну могущества, чтобы создать больше двух заклинаний крови.
|
||||
|
||||
verb-spell-remove-text = Удалить заклинание крови
|
||||
verb-spell-remove-message = Убрать любое из созданных заклинаний крови.
|
||||
verb-spell-remove-no-spells = Заклинания крови отсутствуют.
|
||||
|
||||
verb-blood-rites-text = Кровавые обряды
|
||||
verb-blood-rites-message = Всего высосано крови: { $blood }.
|
||||
verb-blood-rites-no-blood = Для обряда необходимо высосать { $required } крови с помощью заклинания Кровавые Обряды. Всего высосано: { $blood }.
|
||||
verb-blood-rites-no-hand = Вам нужна свободная рука для обряда.
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
cult-cond-cultwin = Экипаж пососал
|
||||
cult-cond-cultfailure = Экипаж не пососал
|
||||
cultists-list-start = Культистами были:
|
||||
cultists-list-name = - [color=White]{ $name }[/color] ([color=gray]{ $user }[/color])
|
||||
soul-shard-name = Душа { $soul }
|
||||
soul-shard-description = В этом камне заключена душа { $soul }
|
||||
cult-too-much-empowers = Слишком много способностей
|
||||
@@ -40,6 +40,7 @@
|
||||
whitelist:
|
||||
tags:
|
||||
- CartridgePistol
|
||||
- type: GiftIgnore
|
||||
|
||||
- type: entity
|
||||
id: MagazinePistolDebug
|
||||
@@ -55,6 +56,7 @@
|
||||
capacity: 1000
|
||||
- type: Sprite
|
||||
sprite: Objects/Weapons/Guns/Ammunition/Magazine/Pistol/pistol_mag.rsi
|
||||
- type: GiftIgnore
|
||||
|
||||
- type: entity
|
||||
id: BulletDebug
|
||||
@@ -103,6 +105,7 @@
|
||||
- type: Item
|
||||
size: Tiny
|
||||
sprite: Objects/Weapons/Melee/debug.rsi
|
||||
- type: GiftIgnore
|
||||
|
||||
- type: entity
|
||||
name: bang stick 100dmg
|
||||
@@ -116,6 +119,7 @@
|
||||
damage:
|
||||
types:
|
||||
Blunt: 100
|
||||
- type: GiftIgnore
|
||||
|
||||
- type: entity
|
||||
name: bang stick 200dmg
|
||||
@@ -129,3 +133,4 @@
|
||||
damage:
|
||||
types:
|
||||
Blunt: 200
|
||||
- type: GiftIgnore
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
- type: IgnoreUIRange
|
||||
- type: ShowRevIcons
|
||||
- type: ShowZombieIcons
|
||||
- type: ShowCultHud
|
||||
- type: Inventory
|
||||
templateId: aghost
|
||||
- type: InventorySlots
|
||||
|
||||
@@ -217,6 +217,8 @@
|
||||
type: SpellSelectorBUI
|
||||
- key: enum.CultEmpowerRemoveUiKey.Key
|
||||
type: SpellRemoverBUI
|
||||
- key: enum.BloodRitesUi.Key
|
||||
type: CultistFactoryBUI
|
||||
# WD-EDIT END
|
||||
- type: Puller
|
||||
- type: Butcherable
|
||||
|
||||
@@ -85,7 +85,6 @@
|
||||
preset: StorePresetUplink
|
||||
balance:
|
||||
Telecrystal: 20
|
||||
- type: GiftIgnore
|
||||
|
||||
- type: entity
|
||||
parent: BaseUplinkRadio
|
||||
@@ -96,7 +95,6 @@
|
||||
preset: StorePresetUplink
|
||||
balance:
|
||||
Telecrystal: 25
|
||||
- type: GiftIgnore
|
||||
|
||||
#this uplink MUST be used for nukeops, as it has the tag for filtering the listing.
|
||||
- type: entity
|
||||
@@ -111,7 +109,6 @@
|
||||
- type: Tag
|
||||
tags:
|
||||
- NukeOpsUplink
|
||||
- type: GiftIgnore
|
||||
|
||||
- type: entity
|
||||
parent: BaseUplinkRadio
|
||||
|
||||
@@ -340,6 +340,7 @@
|
||||
unshaded:
|
||||
True: { visible: true }
|
||||
False: { visible: false }
|
||||
- type: GiftIgnore
|
||||
|
||||
- type: entity
|
||||
name: force gun
|
||||
@@ -382,6 +383,7 @@
|
||||
unshaded:
|
||||
True: { visible: true }
|
||||
False: { visible: false }
|
||||
- type: GiftIgnore
|
||||
|
||||
- type: entity
|
||||
name: meteor launcher
|
||||
@@ -395,6 +397,7 @@
|
||||
tags:
|
||||
- CartridgeRocket
|
||||
proto: MeteorLarge
|
||||
- type: GiftIgnore
|
||||
|
||||
- type: entity
|
||||
name: immovable rod launcher
|
||||
@@ -408,3 +411,4 @@
|
||||
tags:
|
||||
- CartridgeRocket
|
||||
proto: ImmovableRodSlow
|
||||
- type: GiftIgnore
|
||||
|
||||
@@ -1379,3 +1379,19 @@
|
||||
shader: unshaded
|
||||
- type: ChangeTemperatureOnCollide
|
||||
temperature: -20
|
||||
|
||||
- type: entity
|
||||
name: blood bolt
|
||||
id: BloodBolt
|
||||
parent: BaseBullet
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: White/Cult/Entities/arcane_barrage.rsi
|
||||
state: bullet
|
||||
- type: Ammo
|
||||
muzzleFlash: null
|
||||
- type: Projectile
|
||||
damage:
|
||||
types:
|
||||
Piercing: 20
|
||||
|
||||
@@ -20,8 +20,10 @@
|
||||
size: Normal
|
||||
- type: Clothing
|
||||
sprite: Objects/Weapons/Melee/cult_dagger.rsi
|
||||
quickEquip: false
|
||||
slots:
|
||||
- back
|
||||
- suitStorage
|
||||
- type: DisarmMalus
|
||||
- type: RuneDrawerProvider
|
||||
runePrototypes: [ OfferingRune,
|
||||
@@ -33,6 +35,10 @@
|
||||
SummoningRune,
|
||||
BloodBoilRune,
|
||||
ApocalypseRune ]
|
||||
- type: ActivatableUI
|
||||
key: enum.ListViewSelectorUiKey.Key
|
||||
inHandsOnly: true
|
||||
closeOnHandDeselect: true
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.ListViewSelectorUiKey.Key
|
||||
@@ -64,8 +70,10 @@
|
||||
size: Huge
|
||||
- type: Clothing
|
||||
sprite: Objects/Weapons/Melee/cult_blade.rsi
|
||||
quickEquip: false
|
||||
slots:
|
||||
- back
|
||||
- suitStorage
|
||||
- type: DisarmMalus
|
||||
- type: CultItem
|
||||
|
||||
|
||||
@@ -197,13 +197,13 @@
|
||||
thresholds:
|
||||
- trigger:
|
||||
!type:DamageTrigger
|
||||
damage: 1200
|
||||
damage: 600
|
||||
behaviors:
|
||||
- !type:DoActsBehavior
|
||||
acts: ["Destruction"]
|
||||
- trigger:
|
||||
!type:DamageTrigger
|
||||
damage: 600
|
||||
damage: 300
|
||||
behaviors:
|
||||
- !type:PlaySoundBehavior
|
||||
sound:
|
||||
@@ -220,6 +220,16 @@
|
||||
- type: Construction
|
||||
graph: CultGirder
|
||||
node: wall
|
||||
- type: Appearance
|
||||
- type: Concealable
|
||||
examinableWhileConcealed: true
|
||||
concealedSprite: White/Cult/Structures/Concealed/cult.rsi
|
||||
revealedSprite: Structures/Walls/cult.rsi
|
||||
changeMeta: true
|
||||
concealedName: обычная стена
|
||||
concealedDesc: Удерживает воздух внутри, а ассистентов снаружи.
|
||||
revealedName: стена культа
|
||||
revealedDesc: Удерживает воздух внутри, а ассистентов снаружи.
|
||||
|
||||
- type: entity
|
||||
parent: BaseWall
|
||||
|
||||
@@ -45,6 +45,8 @@
|
||||
type: SpellSelectorBUI
|
||||
- key: enum.CultEmpowerRemoveUiKey.Key
|
||||
type: SpellRemoverBUI
|
||||
- key: enum.BloodRitesUi.Key
|
||||
type: CultistFactoryBUI
|
||||
# WD-EDIT END
|
||||
- type: Sprite
|
||||
scale: 0.9, 0.9
|
||||
|
||||
@@ -27,8 +27,6 @@
|
||||
- HumanoidAppearance
|
||||
- Cultist
|
||||
canTargetSelf: true
|
||||
deselectOnMiss: true
|
||||
repeat: false
|
||||
icon:
|
||||
sprite: /Textures/White/Cult/actions_cult.rsi
|
||||
state: teleport
|
||||
@@ -50,8 +48,6 @@
|
||||
- HumanoidAppearance
|
||||
- Cultist
|
||||
canTargetSelf: true
|
||||
deselectOnMiss: true
|
||||
repeat: false
|
||||
icon:
|
||||
sprite: /Textures/White/Cult/actions_cult.rsi
|
||||
state: armor
|
||||
@@ -72,8 +68,6 @@
|
||||
components:
|
||||
- HumanoidAppearance
|
||||
canTargetSelf: false
|
||||
deselectOnMiss: true
|
||||
repeat: false
|
||||
icon:
|
||||
sprite: /Textures/White/Cult/actions_cult.rsi
|
||||
state: stun
|
||||
@@ -94,8 +88,6 @@
|
||||
components:
|
||||
- HumanoidAppearance
|
||||
canTargetSelf: false
|
||||
deselectOnMiss: true
|
||||
repeat: false
|
||||
icon:
|
||||
sprite: /Textures/White/Cult/actions_cult.rsi
|
||||
state: shackles
|
||||
@@ -131,7 +123,7 @@
|
||||
sprite: /Textures/White/Cult/actions_cult.rsi
|
||||
state: blood_rites
|
||||
event: !type:CultBloodRitesInstantActionEvent
|
||||
charges: 4
|
||||
charges: 5
|
||||
temporary: true
|
||||
removeOnNoCharges: true
|
||||
|
||||
@@ -149,3 +141,27 @@
|
||||
charges: 1
|
||||
temporary: true
|
||||
removeOnNoCharges: true
|
||||
|
||||
- type: entity
|
||||
id: InstantActionConcealPresence
|
||||
name: Conceal Presence
|
||||
description: A multi-function spell that alternates between hiding and revealing nearby runes and cult structures.
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: InstantAction
|
||||
icon:
|
||||
sprite: /Textures/White/Cult/actions_cult.rsi
|
||||
state: gone
|
||||
event: !type:CultConcealInstantActionEvent
|
||||
charges: 10
|
||||
temporary: true
|
||||
removeOnNoCharges: true
|
||||
- type: ConcealPresenceSpell
|
||||
concealEvent: !type:CultConcealInstantActionEvent
|
||||
revealEvent: !type:CultRevealInstantActionEvent
|
||||
concealIcon:
|
||||
sprite: /Textures/White/Cult/actions_cult.rsi
|
||||
state: gone
|
||||
revealIcon:
|
||||
sprite: /Textures/White/Cult/actions_cult.rsi
|
||||
state: telerune
|
||||
|
||||
@@ -64,6 +64,18 @@
|
||||
doAfter: 1
|
||||
- node: airlock
|
||||
entity: AirlockGlassCult
|
||||
edges:
|
||||
- to: start
|
||||
completed:
|
||||
- !type:SpawnPrototype
|
||||
prototype: CultRunicMetal1
|
||||
amount: 1
|
||||
- !type:DeleteEntity { }
|
||||
conditions:
|
||||
- !type:EntityAnchored
|
||||
steps:
|
||||
- tool: Dagger
|
||||
cultistOnly: true
|
||||
|
||||
- type: constructionGraph
|
||||
id: CultPylon
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
- type: construction
|
||||
- type: construction
|
||||
id: CultGirder
|
||||
name: руническая балка
|
||||
description: Большой конструктивный элемент, изготовленный из металла. На этом есть руна.
|
||||
@@ -37,7 +37,7 @@
|
||||
- type: construction
|
||||
id: CultPylon
|
||||
name: пилон
|
||||
description: Мистический конструкция.
|
||||
description: Мистическая конструкция.
|
||||
graph: CultPylon
|
||||
startNode: start
|
||||
targetNode: pylon
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
- type: Construction
|
||||
graph: CultPylon
|
||||
node: pylon
|
||||
- type: Concealable
|
||||
|
||||
- type: entity
|
||||
id: AltarTome
|
||||
@@ -127,6 +128,7 @@
|
||||
- type: Construction
|
||||
graph: AltarTome
|
||||
node: tome
|
||||
- type: Concealable
|
||||
|
||||
- type: entity
|
||||
id: CultBloodAltar
|
||||
@@ -185,6 +187,7 @@
|
||||
- type: Construction
|
||||
graph: CultBloodAltar
|
||||
node: altar
|
||||
- type: Concealable
|
||||
|
||||
- type: entity
|
||||
id: CultForge
|
||||
@@ -247,6 +250,7 @@
|
||||
- type: Construction
|
||||
graph: CultForge
|
||||
node: forge
|
||||
- type: Concealable
|
||||
|
||||
- type: cultStructure
|
||||
id: CultStructureAltarTome
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
- type: entity
|
||||
name: blood bolt barrage
|
||||
parent: BaseItem
|
||||
id: BloodBarrage
|
||||
description: Blood for blood.
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: White/Cult/Entities/arcane_barrage.rsi
|
||||
state: icon
|
||||
- type: Item
|
||||
size: Ginormous
|
||||
sprite: White/Cult/Entities/arcane_barrage.rsi
|
||||
- type: AmmoCounter
|
||||
- type: Gun
|
||||
fireRate: 4
|
||||
selectedMode: SemiAuto
|
||||
availableModes:
|
||||
- SemiAuto
|
||||
soundEmpty: null
|
||||
soundGunshot:
|
||||
path: /Audio/White/Cult/wand_teleport.ogg
|
||||
- type: BasicEntityAmmoProvider
|
||||
proto: BloodBolt
|
||||
capacity: 25
|
||||
- type: BoltBarrage
|
||||
- type: GiftIgnore
|
||||
|
||||
- type: cultistFactoryProduction
|
||||
id: FactoryCultBloodBarrage
|
||||
name: Залп Кровавых Снарядов (300 крови)
|
||||
icon: "/Textures/White/Cult/Entities/arcane_barrage.rsi/icon.png"
|
||||
bloodCost: 300
|
||||
item:
|
||||
- BloodBarrage
|
||||
@@ -1,4 +1,4 @@
|
||||
- type: entity
|
||||
- type: entity
|
||||
name: soul shard
|
||||
description: Mysterious glowing shard.
|
||||
parent: BaseItem
|
||||
@@ -25,6 +25,7 @@
|
||||
True: { state: "soulstone2" }
|
||||
False: { state: "soulstone" }
|
||||
- type: Speech
|
||||
- type: IsDeadIC
|
||||
|
||||
- type: entity
|
||||
parent: SoulShard
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
- type: ShowHealthIcons
|
||||
damageContainers:
|
||||
- Biological
|
||||
- type: ShowSecurityIcons
|
||||
|
||||
- type: entity
|
||||
name: veil shifter
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
invokePhrase: "Mah'weyh pleggh at e'ntrath!"
|
||||
- type: CultRuneOffering
|
||||
- type: CultRune
|
||||
- type: Concealable
|
||||
|
||||
- type: entity
|
||||
parent: CollideRune
|
||||
@@ -31,6 +32,7 @@
|
||||
invokePhrase: "Qu'laris ver'don, thal'sorin mik'thar!"
|
||||
- type: CultRuneBuff
|
||||
- type: CultRune
|
||||
- type: Concealable
|
||||
|
||||
- type: entity
|
||||
parent: CollideRune
|
||||
@@ -52,6 +54,8 @@
|
||||
- key: enum.CultEmpowerUiKey.Key
|
||||
type: SpellSelectorBUI
|
||||
- type: CultRune
|
||||
- type: Concealable
|
||||
examinableWhileConcealed: true
|
||||
|
||||
- type: entity
|
||||
parent: CollideRune
|
||||
@@ -71,6 +75,7 @@
|
||||
- type: CultRuneTeleport
|
||||
label: "безымянная метка"
|
||||
- type: CultRune
|
||||
- type: Concealable
|
||||
|
||||
- type: entity
|
||||
parent: CollideRune
|
||||
@@ -89,6 +94,7 @@
|
||||
gatherInvokers: true
|
||||
- type: CultRuneSummoning
|
||||
- type: CultRune
|
||||
- type: Concealable
|
||||
|
||||
- type: entity
|
||||
parent: CollideRune
|
||||
@@ -106,6 +112,7 @@
|
||||
invokePhrase: "Pasnar val'keriam usinar. Savrae ines amutan. Yam'toth remium il'tarat!"
|
||||
- type: CultRuneRevive
|
||||
- type: CultRune
|
||||
- type: Concealable
|
||||
|
||||
- type: entity
|
||||
parent: CollideRune
|
||||
@@ -123,6 +130,7 @@
|
||||
invokePhrase: "Khari'd! Eske'te tannin!"
|
||||
- type: CultRuneBarrier
|
||||
- type: CultRune
|
||||
- type: Concealable
|
||||
|
||||
- type: entity
|
||||
parent: CollideRune
|
||||
@@ -141,6 +149,7 @@
|
||||
- type: CultRuneBloodBoil
|
||||
projectilePrototype: ProjectileCult
|
||||
- type: CultRune
|
||||
- type: Concealable
|
||||
|
||||
- type: entity
|
||||
parent: BaseRune
|
||||
@@ -155,4 +164,5 @@
|
||||
- type: Appearance
|
||||
- type: CultRuneBase
|
||||
invokePhrase: "TOK-LYR RQA-NAP G'OLT-ULOFT!"
|
||||
cultistGatheringRange: 1.5
|
||||
- type: CultRuneApocalypse
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
- type: entity
|
||||
name: blood spear
|
||||
parent: BaseItem
|
||||
id: BloodSpear
|
||||
description: A sickening spear composed entirely of crystallized blood.
|
||||
components:
|
||||
- type: EmbeddableProjectile
|
||||
offset: 0.15,0.15
|
||||
- type: ThrowingAngle
|
||||
angle: 225
|
||||
- type: Fixtures
|
||||
fixtures:
|
||||
fix1:
|
||||
shape: !type:PolygonShape
|
||||
vertices:
|
||||
- -0.20,-0.10
|
||||
- -0.10,-0.20
|
||||
- 0.40,0.30
|
||||
- 0.30,0.40
|
||||
density: 20
|
||||
mask:
|
||||
- ItemMask
|
||||
restitution: 0.3
|
||||
friction: 0.2
|
||||
- type: Sharp
|
||||
- type: Sprite
|
||||
sprite: White/Cult/Entities/blood_spear.rsi
|
||||
state: icon
|
||||
- type: MeleeWeapon
|
||||
wideAnimationRotation: -135
|
||||
damage:
|
||||
types:
|
||||
Piercing: 36
|
||||
angle: 0
|
||||
animation: WeaponArcThrust
|
||||
soundHit:
|
||||
path: /Audio/Weapons/bladeslice.ogg
|
||||
range: 2
|
||||
- type: DamageOtherOnHit
|
||||
damage:
|
||||
types:
|
||||
Piercing: 40
|
||||
- type: Item
|
||||
sprite: White/Cult/Entities/blood_spear.rsi
|
||||
size: Ginormous
|
||||
- type: Clothing
|
||||
slots:
|
||||
- back
|
||||
- type: Wieldable
|
||||
- type: IncreaseDamageOnWield
|
||||
damage:
|
||||
types:
|
||||
Piercing: 8
|
||||
- type: UseDelay
|
||||
- type: DisarmMalus
|
||||
- type: CultItem
|
||||
- type: BloodSpear
|
||||
action: InstantActionRecallBloodSpear
|
||||
- type: ChangeThrowForce
|
||||
throwForce: 20
|
||||
|
||||
- type: cultistFactoryProduction
|
||||
id: FactoryCultBloodSpear
|
||||
name: Кровавое Копьё (150 крови)
|
||||
icon: "/Textures/White/Cult/Entities/blood_spear.rsi/icon.png"
|
||||
bloodCost: 150
|
||||
item:
|
||||
- BloodSpear
|
||||
|
||||
- type: entity
|
||||
id: InstantActionRecallBloodSpear
|
||||
name: Recall Blood Spear
|
||||
description: Recalls blood spear to your hand.
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: InstantAction
|
||||
icon:
|
||||
sprite: /Textures/White/Cult/actions_cult.rsi
|
||||
state: bloodspear
|
||||
event: !type:CultBloodSpearRecallInstantActionEvent
|
||||
useDelay: 1
|
||||
temporary: true
|
||||
@@ -60,6 +60,18 @@
|
||||
- type: Pullable
|
||||
- type: ContentEye
|
||||
- type: Actions
|
||||
- type: Hands
|
||||
- type: ShowCultHud
|
||||
- type: IsDeadIC
|
||||
- type: NightVision
|
||||
toggleSound: null
|
||||
color: White
|
||||
- type: ShowWhiteHealthBars
|
||||
damageContainers:
|
||||
- Biological
|
||||
- type: ShowHealthIcons
|
||||
damageContainers:
|
||||
- Biological
|
||||
- type: Tag
|
||||
tags:
|
||||
- CannotSuicide
|
||||
@@ -77,17 +89,15 @@
|
||||
thresholds:
|
||||
0: Alive
|
||||
150: Dead
|
||||
- type: MovementSpeedModifier
|
||||
baseWalkSpeed: 2
|
||||
baseSprintSpeed: 2
|
||||
- type: Construct
|
||||
actions:
|
||||
- InstantActionJuggernautCreateWall
|
||||
- type: MeleeWeapon
|
||||
canHeavyAttack: false
|
||||
hidden: true
|
||||
angle: 30
|
||||
animation: WeaponArcFist
|
||||
attackRate: 0.25
|
||||
animation: WeaponArcSmash
|
||||
attackRate: 1
|
||||
damage:
|
||||
types:
|
||||
Structural: 90
|
||||
@@ -114,13 +124,18 @@
|
||||
InstantActionArtificerCreateCultistWall,
|
||||
InstantActionArtificerCreateCultistAirlock,
|
||||
]
|
||||
- type: MovementSpeedModifier
|
||||
baseWalkSpeed: 3
|
||||
baseSprintSpeed: 3
|
||||
- type: MovementIgnoreGravity
|
||||
- type: Puller
|
||||
needsHands: false
|
||||
- type: MeleeWeapon
|
||||
canHeavyAttack: false
|
||||
hidden: true
|
||||
angle: 30
|
||||
animation: WeaponArcFist
|
||||
attackRate: 0.85
|
||||
animation: WeaponArcPunch
|
||||
attackRate: 1
|
||||
damage:
|
||||
types:
|
||||
Blunt: 5
|
||||
@@ -133,8 +148,8 @@
|
||||
description: run...
|
||||
components:
|
||||
- type: MovementSpeedModifier
|
||||
baseWalkSpeed: 3.0
|
||||
baseSprintSpeed: 3.0
|
||||
baseWalkSpeed: 4.0
|
||||
baseSprintSpeed: 4.0
|
||||
- type: MobThresholds
|
||||
thresholds:
|
||||
0: Alive
|
||||
@@ -148,14 +163,16 @@
|
||||
actions: [InstantActionWraithPhase]
|
||||
- type: MovementIgnoreGravity
|
||||
- type: MeleeWeapon
|
||||
canHeavyAttack: false
|
||||
hidden: true
|
||||
angle: 30
|
||||
animation: WeaponArcFist
|
||||
attackRate: 0.5
|
||||
animation: WeaponArcPunch
|
||||
attackRate: 1
|
||||
damage:
|
||||
types:
|
||||
Blunt: 10
|
||||
Slash: 10
|
||||
Structural: 40
|
||||
|
||||
- type: entity
|
||||
id: ReaperConstruct
|
||||
@@ -165,8 +182,8 @@
|
||||
components:
|
||||
- type: MovementIgnoreGravity
|
||||
- type: MovementSpeedModifier
|
||||
baseWalkSpeed: 3.0
|
||||
baseSprintSpeed: 3.0
|
||||
baseWalkSpeed: 5.0
|
||||
baseSprintSpeed: 5.0
|
||||
- type: MobThresholds
|
||||
thresholds:
|
||||
0: Alive
|
||||
@@ -176,10 +193,11 @@
|
||||
- type: Puller
|
||||
needsHands: false
|
||||
- type: MeleeWeapon
|
||||
canHeavyAttack: false
|
||||
hidden: true
|
||||
angle: 30
|
||||
animation: WeaponArcFist
|
||||
attackRate: 0.9
|
||||
animation: WeaponArcPunch
|
||||
attackRate: 1
|
||||
damage:
|
||||
types:
|
||||
Blunt: 20
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
Brute:
|
||||
collection: GlassSmash
|
||||
- type: Sprite
|
||||
sprite: /Textures/White/Cult/Structures/cult_airlock.rsi
|
||||
sprite: White/Cult/Structures/cult_airlock.rsi
|
||||
layers:
|
||||
- state: closed
|
||||
map: ["enum.DoorVisualLayers.Base"]
|
||||
@@ -18,8 +18,8 @@
|
||||
- type: Occluder
|
||||
enabled: false
|
||||
- type: Door
|
||||
occludes: false
|
||||
bumpOpen: true
|
||||
occludes: false
|
||||
crushDamage:
|
||||
types:
|
||||
Blunt: 15
|
||||
@@ -27,8 +27,6 @@
|
||||
path: /Audio/Effects/stonedoor_openclose.ogg
|
||||
closeSound:
|
||||
path: /Audio/Effects/stonedoor_openclose.ogg
|
||||
denySound:
|
||||
path: /Audio/Machines/airlock_deny.ogg
|
||||
- type: Airtight
|
||||
fixVacuum: true
|
||||
noAirWhenFullyAirBlocked: false
|
||||
@@ -38,7 +36,7 @@
|
||||
thresholds:
|
||||
- trigger:
|
||||
!type:DamageTrigger
|
||||
damage: 500
|
||||
damage: 200
|
||||
behaviors:
|
||||
- !type:DoActsBehavior
|
||||
acts: ["Destruction"]
|
||||
@@ -48,6 +46,22 @@
|
||||
node: airlock
|
||||
- type: PlacementReplacement
|
||||
key: walls
|
||||
- type: Appearance
|
||||
- type: Concealable
|
||||
examinableWhileConcealed: true
|
||||
iconSmooth: true
|
||||
interactionOutline: true
|
||||
concealedSprite: White/Cult/Structures/Concealed/cult_airlock.rsi
|
||||
revealedSprite: White/Cult/Structures/cult_airlock.rsi
|
||||
changeMeta: true
|
||||
concealedName: обычная стена
|
||||
concealedDesc: Удерживает воздух внутри, а ассистентов снаружи.
|
||||
revealedName: рунический шлюз
|
||||
revealedDesc: Странный стеклянный шлюз с руной.
|
||||
- type: IconSmooth
|
||||
enabled: false
|
||||
key: walls
|
||||
mode: NoSprite
|
||||
placement:
|
||||
mode: SnapgridCenter
|
||||
|
||||
@@ -75,7 +89,7 @@
|
||||
- GlassAirlockLayer
|
||||
- type: InteractionOutline
|
||||
- type: Sprite
|
||||
sprite: /Textures/White/Cult/Structures/cult_girder.rsi
|
||||
sprite: White/Cult/Structures/cult_girder.rsi
|
||||
state: cultgirder
|
||||
- type: Damageable
|
||||
damageContainer: StructuralInorganic
|
||||
@@ -104,3 +118,13 @@
|
||||
- type: Construction
|
||||
graph: CultGirder
|
||||
node: girder
|
||||
- type: Appearance
|
||||
- type: Concealable
|
||||
examinableWhileConcealed: true
|
||||
concealedSprite: White/Cult/Structures/Concealed/cult_girder.rsi
|
||||
revealedSprite: White/Cult/Structures/cult_girder.rsi
|
||||
changeMeta: true
|
||||
concealedName: каркас
|
||||
concealedDesc: Большой металлический каркас; Необходимо покрыть листами металла, чтобы он считался стеной.
|
||||
revealedName: руническая балка
|
||||
revealedDesc: Большой конструктивный элемент, изготовленный из металла. На этом есть руна.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
- type: tile
|
||||
- type: tile
|
||||
id: CultFloor
|
||||
name: tiles-cult-floor
|
||||
sprite: /Textures/White/Cult/Tiles/cult_tile.rsi/cult.png
|
||||
@@ -10,3 +10,20 @@
|
||||
collection: FootstepFloor
|
||||
itemDrop: FloorTileItemSteel
|
||||
heatCapacity: 10000
|
||||
|
||||
- type: tile
|
||||
id: CultFloorConcealed
|
||||
name: tiles-steel-floor
|
||||
sprite: /Textures/White/Cult/Tiles/concealed.png
|
||||
variants: 3
|
||||
placementVariants:
|
||||
- 1.0
|
||||
- 1.0
|
||||
- 1.0
|
||||
baseTurf: Plating
|
||||
isSubfloor: false
|
||||
deconstructTools: [ Prying ]
|
||||
footstepSounds:
|
||||
collection: FootstepFloor
|
||||
itemDrop: FloorTileItemSteel
|
||||
heatCapacity: 10000
|
||||
|
||||
@@ -1,7 +1,20 @@
|
||||
- type: entity
|
||||
- type: entity
|
||||
id: Narsie
|
||||
parent: BaseMob
|
||||
name: Nar'si
|
||||
components:
|
||||
- type: AnnounceOnSpawn
|
||||
message: narsie-has-risen
|
||||
sender: narsie-has-risen-sender
|
||||
sound:
|
||||
path: /Audio/Misc/narsie_rises.ogg
|
||||
color: darkred
|
||||
- type: CargoSellBlacklist
|
||||
- type: ContentEye
|
||||
maxZoom: 2.0,2.0
|
||||
- type: WarpPoint
|
||||
follow: true
|
||||
location: Nar'Sie
|
||||
- type: Sprite
|
||||
layers:
|
||||
- map: [ "enum.NarsieLayer.Default" ]
|
||||
@@ -15,6 +28,8 @@
|
||||
- type: Narsie
|
||||
- type: Physics
|
||||
bodyType: Dynamic
|
||||
bodyStatus: InAir
|
||||
- type: CanMoveInAir
|
||||
- type: Fixtures
|
||||
fixtures:
|
||||
Penis:
|
||||
|
||||
|
After Width: | Height: | Size: 545 B |
|
After Width: | Height: | Size: 588 B |
|
After Width: | Height: | Size: 491 B |
|
After Width: | Height: | Size: 455 B |
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Taken from tgstation",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "icon"
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
],
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
],
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
],
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "inhand-right",
|
||||
"directions": 4,
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
],
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
],
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
],
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "bullet",
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
Resources/Textures/White/Cult/Entities/blood_spear.rsi/icon.png
Normal file
|
After Width: | Height: | Size: 441 B |
|
After Width: | Height: | Size: 556 B |
|
After Width: | Height: | Size: 553 B |
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Taken from yogstation",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "icon"
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-right",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "wielded-inhand-left",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "wielded-inhand-right",
|
||||
"directions": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 590 B |
|
After Width: | Height: | Size: 590 B |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1 @@
|
||||
{"version": 1, "size": {"x": 32, "y": 32}, "license": "CC-BY-SA-3.0", "copyright": "https://github.com/vgstation-coders/vgstation13/raw/99cc2ab62d65a3a7b554dc7b21ff5f57c835f973/icons/turf/walls.dmi", "states": [{"name": "cult0", "directions": 4}, {"name": "cult1", "directions": 4}, {"name": "cult2", "directions": 4}, {"name": "cult3", "directions": 4}, {"name": "cult4", "directions": 4}, {"name": "cult5", "directions": 4}, {"name": "cult6", "directions": 4}, {"name": "cult7", "directions": 4}, {"name": "full"}]}
|
||||