Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Jabak
2024-06-13 09:07:23 +03:00
87 changed files with 1794 additions and 416 deletions

View File

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

View File

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

View File

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

View File

@@ -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)]

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

View File

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

View File

@@ -0,0 +1,6 @@
namespace Content.Shared._White.Cult.Structures;
[RegisterComponent]
public sealed partial class RunicDoorComponent : Component
{
}

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

View File

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

View File

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

View File

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

View File

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