Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -24,7 +24,7 @@ public sealed partial class ChangelingComponent : Component
|
||||
public float Accumulator;
|
||||
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
public float UpdateDelay = 8f;
|
||||
public float UpdateDelay = 6f;
|
||||
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
public bool IsRegenerating;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using Content.Shared._White.Cult.Structures;
|
||||
using Content.Shared._White.Keyhole.Components;
|
||||
using Content.Shared.Access.Components;
|
||||
using Content.Shared.Access.Systems;
|
||||
@@ -41,6 +42,7 @@ public abstract partial class SharedDoorSystem : EntitySystem
|
||||
[Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!;
|
||||
[Dependency] private readonly PryingSystem _pryingSystem = default!;
|
||||
[Dependency] protected readonly SharedPopupSystem Popup = default!;
|
||||
[Dependency] private readonly RunicDoorSystem _runicDoor = default!; // WD
|
||||
|
||||
[ValidatePrototypeId<TagPrototype>]
|
||||
public const string DoorBumpTag = "DoorBumpOpener";
|
||||
@@ -649,6 +651,9 @@ public abstract partial class SharedDoorSystem : EntitySystem
|
||||
|
||||
var otherUid = args.OtherEntity;
|
||||
|
||||
if (!_runicDoor.CanBumpOpen(uid, otherUid)) // WD
|
||||
return;
|
||||
|
||||
if (Tags.HasTag(otherUid, DoorBumpTag))
|
||||
TryOpen(uid, door, otherUid, quiet: door.State == DoorState.Denying);
|
||||
}
|
||||
@@ -762,6 +767,9 @@ public abstract partial class SharedDoorSystem : EntitySystem
|
||||
{
|
||||
foreach (var other in PhysicsSystem.GetContactingEntities(uid, physics, approximate: true))
|
||||
{
|
||||
if (!_runicDoor.CanBumpOpen(uid, other)) // WD
|
||||
continue;
|
||||
|
||||
if (Tags.HasTag(other, DoorBumpTag) && TryOpen(uid, door, other, quiet: true))
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -533,6 +533,11 @@ public abstract partial class SharedGunSystem : EntitySystem
|
||||
Dirty(gun);
|
||||
}
|
||||
// WD EDIT
|
||||
public void SetUseKey(GunComponent gun, bool useKey)
|
||||
{
|
||||
gun.UseKey = useKey;
|
||||
}
|
||||
|
||||
public void SetProjectileSpeed(EntityUid weapon, float projectileSpeed)
|
||||
{
|
||||
if(!TryComp<GunComponent>(weapon, out var gunComponent))
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._White.BetrayalDagger;
|
||||
|
||||
[RegisterComponent]
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class BlinkComponent : Component
|
||||
{
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
|
||||
13
Content.Shared/_White/Cult/Components/ConstructComponent.cs
Normal file
13
Content.Shared/_White/Cult/Components/ConstructComponent.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._White.Cult.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class ConstructComponent : Component
|
||||
{
|
||||
[DataField("actions")]
|
||||
public List<EntProtoId> Actions = new();
|
||||
|
||||
[ViewVariables]
|
||||
public List<EntityUid?> ActionEntities = new();
|
||||
}
|
||||
@@ -3,10 +3,16 @@ namespace Content.Shared._White.Cult.Components;
|
||||
[RegisterComponent]
|
||||
public sealed partial class CultBuffComponent : Component
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadOnly), DataField("buffTime")]
|
||||
[ViewVariables(VVAccess.ReadOnly), DataField]
|
||||
public TimeSpan BuffTime = TimeSpan.FromSeconds(60);
|
||||
|
||||
[ViewVariables(VVAccess.ReadOnly), DataField]
|
||||
public TimeSpan StartingBuffTime = TimeSpan.FromSeconds(60);
|
||||
|
||||
[ViewVariables(VVAccess.ReadOnly), DataField]
|
||||
public TimeSpan BuffLimit = TimeSpan.FromSeconds(55);
|
||||
|
||||
public static float NearbyTilesBuffRadius = 1f;
|
||||
|
||||
public static readonly TimeSpan CultTileBuffTime = TimeSpan.FromSeconds(5);
|
||||
public static readonly TimeSpan CultTileBuffTime = TimeSpan.FromSeconds(1);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Shared._White.Cult.Structures;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class RunicDoorComponent : Component
|
||||
{
|
||||
}
|
||||
144
Content.Shared/_White/Cult/Structures/RunicDoorSystem.cs
Normal file
144
Content.Shared/_White/Cult/Structures/RunicDoorSystem.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
using Content.Shared._White.Chaplain;
|
||||
using Content.Shared.Doors;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Stunnable;
|
||||
using Content.Shared._White.Cult.Components;
|
||||
using Content.Shared._White.Cult.Systems;
|
||||
using Content.Shared.Cuffs;
|
||||
using Content.Shared.Cuffs.Components;
|
||||
using Content.Shared.Doors.Components;
|
||||
using Content.Shared.Doors.Systems;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Content.Shared.Prying.Components;
|
||||
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;
|
||||
|
||||
namespace Content.Shared._White.Cult.Structures;
|
||||
|
||||
public sealed class RunicDoorSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedDoorSystem _doorSystem = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[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 SharedCuffableSystem _cuffable = default!;
|
||||
[Dependency] private readonly HolyWeaponSystem _holyWeapon = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<RunicDoorComponent, BeforeDoorOpenedEvent>(OnBeforeDoorOpened);
|
||||
SubscribeLocalEvent<RunicDoorComponent, BeforeDoorClosedEvent>(OnBeforeDoorClosed);
|
||||
// SubscribeLocalEvent<RunicDoorComponent, AttackedEvent>(OnGetAttacked);
|
||||
SubscribeLocalEvent<RunicDoorComponent, ConcealEvent>(OnConceal);
|
||||
SubscribeLocalEvent<RunicDoorComponent, BeforePryEvent>(OnBeforePry);
|
||||
}
|
||||
|
||||
private void OnBeforePry(Entity<RunicDoorComponent> ent, ref BeforePryEvent args)
|
||||
{
|
||||
args.Cancelled = true;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (!HasComp<HolyWeaponComponent>(args.Used) || !TryComp<DoorComponent>(ent, out var doorComp) ||
|
||||
doorComp.State is not DoorState.Closed)
|
||||
return;
|
||||
|
||||
_audio.PlayPvs(new SoundPathSpecifier("/Audio/Magic/knock.ogg"), ent);
|
||||
|
||||
_doorSystem.StartOpening(ent, doorComp);
|
||||
}
|
||||
|
||||
private void OnBeforeDoorOpened(EntityUid uid, RunicDoorComponent component, BeforeDoorOpenedEvent args)
|
||||
{
|
||||
args.Uncancel();
|
||||
|
||||
if (!args.User.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Process(uid, args.User.Value))
|
||||
{
|
||||
args.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBeforeDoorClosed(EntityUid uid, RunicDoorComponent component, BeforeDoorClosedEvent args)
|
||||
{
|
||||
args.Uncancel();
|
||||
|
||||
if (!args.User.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Process(uid, args.User.Value))
|
||||
{
|
||||
args.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private bool Process(EntityUid airlock, EntityUid user)
|
||||
{
|
||||
if (HasComp<CultistComponent>(user) || HasComp<ConstructComponent>(user))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// _doorSystem.Deny(airlock);
|
||||
|
||||
if (!HasComp<HumanoidAppearanceComponent>(user) || _holyWeapon.IsHoldingHolyWeapon(user) ||
|
||||
TryComp(airlock, out ConcealableComponent? concealable) && concealable.Concealed)
|
||||
return false;
|
||||
|
||||
var direction = _transform.GetMapCoordinates(user).Position - _transform.GetMapCoordinates(airlock).Position;
|
||||
var impulseVector = direction * 2000;
|
||||
|
||||
_physics.ApplyLinearImpulse(user, impulseVector);
|
||||
|
||||
_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);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ using Robust.Shared.Serialization;
|
||||
namespace Content.Shared._White.Cult.UI;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class TeleportSpellEuiState : EuiStateBase
|
||||
public sealed class CultTeleportSpellEuiState : EuiStateBase
|
||||
{
|
||||
public Dictionary<int, string> Runes = new();
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
using System.Linq;
|
||||
using Content.Shared._White.BetrayalDagger;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.UserInterface;
|
||||
using Content.Shared.Weapons.Ranged.Components;
|
||||
using Content.Shared.Weapons.Ranged.Systems;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._White.Wizard.SpellBlade;
|
||||
|
||||
public abstract class SharedSpellBladeSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
[Dependency] private readonly SharedHandsSystem _hands = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly SharedGunSystem _gun = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<SpellBladeComponent, SpellBladeSystemMessage>(OnMessage);
|
||||
SubscribeLocalEvent<SpellBladeComponent, ActivatableUIOpenAttemptEvent>(OnOpenAttempt);
|
||||
SubscribeLocalEvent<SpellBladeComponent, ExaminedEvent>(OnExamined);
|
||||
}
|
||||
|
||||
private void OnExamined(Entity<SpellBladeComponent> ent, ref ExaminedEvent args)
|
||||
{
|
||||
if (ent.Comp.ChosenAspect == string.Empty)
|
||||
{
|
||||
args.PushMarkup("Аспект не выбран.");
|
||||
return;
|
||||
}
|
||||
|
||||
var proto = _prototypeManager.Index(ent.Comp.ChosenAspect);
|
||||
|
||||
args.PushMarkup($"Выбранный аспект: {proto.Name}");
|
||||
}
|
||||
|
||||
private void OnOpenAttempt(Entity<SpellBladeComponent> ent, ref ActivatableUIOpenAttemptEvent args)
|
||||
{
|
||||
if (ent.Comp.ChosenAspect == string.Empty)
|
||||
return;
|
||||
|
||||
_popup.PopupEntity("Аспект уже выбран.", args.User, args.User);
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
private void OnMessage(Entity<SpellBladeComponent> ent, ref SpellBladeSystemMessage args)
|
||||
{
|
||||
if (ent.Comp.ChosenAspect != string.Empty)
|
||||
return;
|
||||
|
||||
switch (args.ProtoId)
|
||||
{
|
||||
case "AspectFire":
|
||||
ApplyFireAspect(ent);
|
||||
break;
|
||||
case "AspectFrost":
|
||||
ApplyFrostAspect(ent);
|
||||
break;
|
||||
case "AspectLightning":
|
||||
ApplyLightningAspect(ent);
|
||||
break;
|
||||
case "AspectBluespace":
|
||||
ApplyBluespaceAspect(ent);
|
||||
break;
|
||||
case "AspectMagicMissile":
|
||||
ApplyMagicMissileAspect(ent);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
ent.Comp.ChosenAspect = args.ProtoId;
|
||||
|
||||
_audio.PlayPvs(ent.Comp.AspectChosenSound, ent);
|
||||
|
||||
|
||||
Dirty(ent);
|
||||
}
|
||||
|
||||
protected virtual void ApplyFireAspect(EntityUid uid) { }
|
||||
|
||||
protected virtual void ApplyFrostAspect(EntityUid uid) { }
|
||||
|
||||
protected virtual void ApplyLightningAspect(EntityUid uid) { }
|
||||
|
||||
private void ApplyBluespaceAspect(EntityUid uid)
|
||||
{
|
||||
var blink = EnsureComp<BlinkComponent>(uid);
|
||||
blink.Distance = 15f;
|
||||
blink.BlinkRate = 1f;
|
||||
}
|
||||
|
||||
private void ApplyMagicMissileAspect(EntityUid uid)
|
||||
{
|
||||
var gun = EnsureComp<GunComponent>(uid);
|
||||
_gun.SetUseKey(gun, false);
|
||||
_gun.SetSound(uid, new SoundPathSpecifier("/Audio/Weapons/Guns/Gunshots/Magic/staff_healing.ogg"));
|
||||
_gun.SetFireRate(uid, 1.2f);
|
||||
var ammoProvider = EnsureComp<BasicEntityAmmoProviderComponent>(uid);
|
||||
ammoProvider.Proto = "ProjectileMagicMissile";
|
||||
}
|
||||
|
||||
public bool IsHoldingItemWithComponent<T>(EntityUid uid) where T : Component
|
||||
{
|
||||
return _hands.EnumerateHeld(uid).Any(HasComp<T>);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._White.Wizard.SpellBlade;
|
||||
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class SpellBladeComponent : Component
|
||||
{
|
||||
[ViewVariables, AutoNetworkedField]
|
||||
public string ChosenAspect = string.Empty;
|
||||
|
||||
[DataField]
|
||||
public List<EntProtoId> Aspects = new()
|
||||
{
|
||||
"AspectFire",
|
||||
"AspectFrost",
|
||||
"AspectLightning",
|
||||
"AspectBluespace",
|
||||
"AspectMagicMissile"
|
||||
};
|
||||
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public SoundSpecifier AspectChosenSound = new SoundPathSpecifier("/Audio/White/Magic/spellblade-aspect.ogg");
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class SpellBladeSystemMessage(EntProtoId protoId) : BoundUserInterfaceMessage
|
||||
{
|
||||
public EntProtoId ProtoId = protoId;
|
||||
}
|
||||
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum SpellBladeUiKey : byte
|
||||
{
|
||||
Key
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Content.Shared.Eui;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._White.Wizard.Teleport;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class WizardTeleportSpellEuiState : EuiStateBase
|
||||
{
|
||||
public Dictionary<int, string> Locations = new();
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class TeleportSpellTargetLocationSelected : EuiMessageBase
|
||||
{
|
||||
public int LocationUid;
|
||||
}
|
||||
Reference in New Issue
Block a user