Merge remote-tracking branch 'upstream/master' into ups
@@ -1,89 +1,37 @@
|
||||
using System.Numerics;
|
||||
using Content.Client.Gravity;
|
||||
using Content.Shared.Rotation;
|
||||
using Content.Shared._White.Animations;
|
||||
using Content.Shared.Movement.Components;
|
||||
using Content.Shared.Movement.Events;
|
||||
using Robust.Client.Animations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.Animations;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client.Movement.Systems;
|
||||
namespace Content.Client._White.Animations;
|
||||
|
||||
public sealed class WaddleAnimationSystem : EntitySystem
|
||||
public sealed class WaddleAnimationSystem : SharedWaddledAnimationSystem
|
||||
{
|
||||
[Dependency] private readonly AnimationPlayerSystem _animation = default!;
|
||||
[Dependency] private readonly GravitySystem _gravity = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly AppearanceSystem _appearance = default!; // WD EDIT
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<WaddleAnimationComponent, MoveInputEvent>(OnMovementInput);
|
||||
SubscribeLocalEvent<WaddleAnimationComponent, StartedWaddlingEvent>(OnStartedWalking);
|
||||
SubscribeLocalEvent<WaddleAnimationComponent, StoppedWaddlingEvent>(OnStoppedWalking);
|
||||
SubscribeLocalEvent<WaddleAnimationComponent, AnimationCompletedEvent>(OnAnimationCompleted);
|
||||
|
||||
SubscribeAllEvent<StartedWaddlingEvent>(ev => PlayAnimation(GetEntity(ev.User)));
|
||||
SubscribeAllEvent<StoppedWaddlingEvent>(ev => StopAnimation(GetEntity(ev.User)));
|
||||
}
|
||||
|
||||
private void OnMovementInput(EntityUid entity, WaddleAnimationComponent component, MoveInputEvent args)
|
||||
protected override void PlayAnimation(EntityUid uid)
|
||||
{
|
||||
// Prediction mitigation. Prediction means that MoveInputEvents are spammed repeatedly, even though you'd assume
|
||||
// they're once-only for the user actually doing something. As such do nothing if we're just repeating this FoR.
|
||||
if (!_timing.IsFirstTimePredicted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// WD EDIT
|
||||
_appearance.TryGetData<RotationState>(entity, RotationVisuals.RotationState, out var state);
|
||||
if (state is RotationState.Horizontal)
|
||||
return;
|
||||
// WD EDIT
|
||||
|
||||
if (!args.HasDirectionalMovement && component.IsCurrentlyWaddling)
|
||||
{
|
||||
component.IsCurrentlyWaddling = false;
|
||||
|
||||
var stopped = new StoppedWaddlingEvent(entity);
|
||||
|
||||
RaiseLocalEvent(entity, ref stopped);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Only start waddling if we're not currently AND we're actually moving.
|
||||
if (component.IsCurrentlyWaddling || !args.HasDirectionalMovement)
|
||||
if (!Timing.IsFirstTimePredicted)
|
||||
return;
|
||||
|
||||
component.IsCurrentlyWaddling = true;
|
||||
|
||||
var started = new StartedWaddlingEvent(entity);
|
||||
|
||||
RaiseLocalEvent(entity, ref started);
|
||||
}
|
||||
|
||||
private void OnStartedWalking(EntityUid uid, WaddleAnimationComponent component, StartedWaddlingEvent args)
|
||||
{
|
||||
if (_animation.HasRunningAnimation(uid, component.KeyName))
|
||||
{
|
||||
if (!TryComp<WaddleAnimationComponent>(uid, out var component))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryComp<InputMoverComponent>(uid, out var mover))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_gravity.IsWeightless(uid))
|
||||
{
|
||||
if (_animation.HasRunningAnimation(uid, component.KeyName))
|
||||
return;
|
||||
}
|
||||
|
||||
// WD EDIT
|
||||
_appearance.TryGetData<RotationState>(uid, RotationVisuals.RotationState, out var state);
|
||||
if (TryComp<SpriteComponent>(uid, out var sprite) && TryComp<RotationVisualsComponent>(uid, out var rotat) && state is RotationState.Horizontal)
|
||||
return;
|
||||
// WD EDIT
|
||||
|
||||
var tumbleIntensity = component.LastStep ? 360 - component.TumbleIntensity : component.TumbleIntensity;
|
||||
var len = mover.Sprinting ? component.AnimationLength * component.RunAnimationLengthMultiplier : component.AnimationLength;
|
||||
@@ -126,14 +74,15 @@ public sealed class WaddleAnimationSystem : EntitySystem
|
||||
_animation.Play(uid, anim, component.KeyName);
|
||||
}
|
||||
|
||||
private void OnStoppedWalking(EntityUid uid, WaddleAnimationComponent component, StoppedWaddlingEvent args)
|
||||
protected override void StopAnimation(EntityUid uid)
|
||||
{
|
||||
_animation.Stop(uid, component.KeyName);
|
||||
if (!TryComp<WaddleAnimationComponent>(uid, out var component))
|
||||
return;
|
||||
|
||||
if (!TryComp<SpriteComponent>(uid, out var sprite))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_animation.Stop(uid, component.KeyName);
|
||||
|
||||
sprite.Offset = new Vector2();
|
||||
sprite.Rotation = Angle.FromDegrees(0);
|
||||
@@ -142,13 +91,9 @@ public sealed class WaddleAnimationSystem : EntitySystem
|
||||
|
||||
private void OnAnimationCompleted(EntityUid uid, WaddleAnimationComponent component, AnimationCompletedEvent args)
|
||||
{
|
||||
if (args.Key is not "Waddle") // WD EDIT
|
||||
{
|
||||
component.IsCurrentlyWaddling = false;
|
||||
if (args.Key != component.KeyName)
|
||||
return;
|
||||
}
|
||||
|
||||
var started = new StartedWaddlingEvent(uid);
|
||||
RaiseLocalEvent(uid, ref started);
|
||||
PlayAnimation(uid);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
using Content.Shared._White.Item.PseudoItem;
|
||||
|
||||
namespace Content.Client._White.Items.PseudoItem;
|
||||
|
||||
public sealed class PseudoItemSystem : SharedPseudoItemSystem
|
||||
{
|
||||
}
|
||||
16
Content.Server/_White/Animations/WaddleAnimationSystem.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using Content.Shared._White.Animations;
|
||||
|
||||
namespace Content.Server._White.Animations;
|
||||
|
||||
public sealed class WaddleAnimationSystem : SharedWaddledAnimationSystem
|
||||
{
|
||||
protected override void PlayAnimation(EntityUid user)
|
||||
{
|
||||
RaiseNetworkEvent(new StartedWaddlingEvent(GetNetEntity(user)));
|
||||
}
|
||||
|
||||
protected override void StopAnimation(EntityUid user)
|
||||
{
|
||||
RaiseNetworkEvent(new StoppedWaddlingEvent(GetNetEntity(user)));
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,15 @@ namespace Content.Server._White.Carrying;
|
||||
[RegisterComponent]
|
||||
public sealed partial class CarriableComponent : Component
|
||||
{
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public TimeSpan DoAfterLength = TimeSpan.FromSeconds(4);
|
||||
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public float WalkModifier = 0.7f;
|
||||
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public float SprintModifier = 0.7f;
|
||||
|
||||
/// <summary>
|
||||
/// Number of free hands required
|
||||
/// to carry the entity
|
||||
@@ -13,4 +22,4 @@ public sealed partial class CarriableComponent : Component
|
||||
public int FreeHandsRequired = 2;
|
||||
|
||||
public CancellationTokenSource? CancelToken;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,9 +207,9 @@ public sealed class CarryingSystem : EntitySystem
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void StartCarryDoAfter(EntityUid carrier, EntityUid carried, CarriableComponent component)
|
||||
public void StartCarryDoAfter(EntityUid carrier, EntityUid carried, CarriableComponent component)
|
||||
{
|
||||
var length = TimeSpan.FromSeconds(6); // т.к. удалили систему разницы масс увеличу время с 3 до 6
|
||||
var length = component.DoAfterLength; // т.к. удалили систему разницы масс увеличу время с 3 до 6
|
||||
if (length >= TimeSpan.FromSeconds(9))
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("carry-too-heavy"), carried, carrier,
|
||||
@@ -230,7 +230,11 @@ public sealed class CarryingSystem : EntitySystem
|
||||
NeedHand = true
|
||||
};
|
||||
|
||||
_doAfterSystem.TryStartDoAfter(args);
|
||||
if(_doAfterSystem.TryStartDoAfter(args))
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("carry-start", ("carrier", carrier)), carried, carried,
|
||||
Shared.Popups.PopupType.SmallCaution);
|
||||
}
|
||||
}
|
||||
|
||||
private void Carry(EntityUid carrier, EntityUid carried)
|
||||
@@ -260,17 +264,22 @@ public sealed class CarryingSystem : EntitySystem
|
||||
_actionBlockerSystem.UpdateCanMove(carried);
|
||||
}
|
||||
|
||||
public void DropCarried(EntityUid carrier, EntityUid carried)
|
||||
public void DropCarried(EntityUid carrier,
|
||||
EntityUid carried,
|
||||
bool attachToGridOrMap = true,
|
||||
bool removeCanEscape = true)
|
||||
{
|
||||
RemComp<CarryingComponent>(carrier); // get rid of this first so we don't recusrively fire that event
|
||||
RemComp<CarryingSlowdownComponent>(carrier);
|
||||
RemComp<BeingCarriedComponent>(carried);
|
||||
RemComp<KnockedDownComponent>(carried);
|
||||
RemComp<CanEscapeInventoryComponent>(carried);
|
||||
if (removeCanEscape)
|
||||
RemComp<CanEscapeInventoryComponent>(carried);
|
||||
|
||||
_actionBlockerSystem.UpdateCanMove(carried);
|
||||
_virtualItemSystem.DeleteInHandsMatching(carrier, carried);
|
||||
_transform.AttachToGridOrMap(carried);
|
||||
if (attachToGridOrMap)
|
||||
_transform.AttachToGridOrMap(carried);
|
||||
_movementSpeed.RefreshMovementSpeedModifiers(carrier);
|
||||
}
|
||||
|
||||
@@ -302,4 +311,4 @@ public sealed class CarryingSystem : EntitySystem
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Content.Server._White.Cult.Items.Components;
|
||||
|
||||
public abstract partial class BaseMagicHandComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public string Speech;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using Content.Shared._White.Cult;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
|
||||
namespace Content.Server._White.Cult.Items.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class CultRitesHandComponent : BaseMagicHandComponent
|
||||
{
|
||||
[DataField]
|
||||
public SoundSpecifier HealSound = new SoundPathSpecifier("/Audio/White/Cult/rites.ogg");
|
||||
|
||||
[DataField]
|
||||
public SoundSpecifier SuckSound = new SoundPathSpecifier("/Audio/White/Cult/enter_blood.ogg");
|
||||
|
||||
[DataField]
|
||||
public float HealModifier = 0.5f;
|
||||
|
||||
[DataField(customTypeSerializer: typeof(PrototypeIdListSerializer<CultistFactoryProductionPrototype>))]
|
||||
public List<string> BloodRites = new ()
|
||||
{
|
||||
"FactoryCultBloodSpear",
|
||||
"FactoryCultBloodBarrage"
|
||||
};
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
namespace Content.Server._White.Cult.Items.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class CultStunHandComponent : Component
|
||||
public sealed partial class CultStunHandComponent : BaseMagicHandComponent
|
||||
{
|
||||
[DataField]
|
||||
public TimeSpan Duration = TimeSpan.FromSeconds(16);
|
||||
@@ -14,7 +14,4 @@ public sealed partial class CultStunHandComponent : Component
|
||||
|
||||
[DataField]
|
||||
public TimeSpan HaloMuteDuration = TimeSpan.FromSeconds(1);
|
||||
|
||||
[DataField]
|
||||
public string Speech = "Fuu ma'jin!";
|
||||
}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
using Content.Server._White.Cult.Items.Components;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Stunnable;
|
||||
using Content.Shared._White.Chaplain;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.StatusEffect;
|
||||
using Content.Shared.Weapons.Melee.Events;
|
||||
|
||||
namespace Content.Server._White.Cult.Items.Systems;
|
||||
|
||||
public sealed class CultStunHandSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly StunSystem _stun = default!;
|
||||
[Dependency] private readonly ChatSystem _chat = default!;
|
||||
[Dependency] private readonly HolyWeaponSystem _holyWeapon = default!;
|
||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||
[Dependency] private readonly BloodstreamSystem _bloodstream = default!;
|
||||
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<CultStunHandComponent, MeleeHitEvent>(OnHit);
|
||||
}
|
||||
|
||||
private void OnHit(Entity<CultStunHandComponent> ent, ref MeleeHitEvent args)
|
||||
{
|
||||
if (args.HitEntities.Count == 0)
|
||||
return;
|
||||
|
||||
var target = args.HitEntities[0];
|
||||
var (uid, comp) = ent;
|
||||
|
||||
QueueDel(uid);
|
||||
Spawn("CultStunFlashEffect", Transform(target).Coordinates);
|
||||
_chat.TrySendInGameICMessage(args.User, comp.Speech, InGameICChatType.Whisper, false);
|
||||
if (TryComp(args.User, out BloodstreamComponent? bloodstream))
|
||||
_bloodstream.TryModifyBloodLevel(args.User, -10, bloodstream, createPuddle: false);
|
||||
|
||||
if (_holyWeapon.IsHoldingHolyWeapon(target))
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("cult-magic-holy"), args.User, args.User, PopupType.MediumCaution);
|
||||
return;
|
||||
}
|
||||
|
||||
var halo = HasComp<PentagramComponent>(args.User);
|
||||
|
||||
_statusEffects.TryAddStatusEffect(target, "Muted", halo ? comp.HaloMuteDuration : comp.MuteDuration, true,
|
||||
"Muted");
|
||||
_stun.TryParalyze(target, halo ? comp.HaloDuration : comp.Duration, true);
|
||||
}
|
||||
}
|
||||
257
Content.Server/_White/Cult/Items/Systems/MagicHandSystem.cs
Normal file
@@ -0,0 +1,257 @@
|
||||
using System.Linq;
|
||||
using Content.Server._White.Cult.Items.Components;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.Hands.Systems;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Stunnable;
|
||||
using Content.Shared._White.Chaplain;
|
||||
using Content.Shared._White.Cult;
|
||||
using Content.Shared._White.Cult.Components;
|
||||
using Content.Shared._White.Cult.UI;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Fluids.Components;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.StatusEffect;
|
||||
using Content.Shared.UserInterface;
|
||||
using Content.Shared.Weapons.Melee.Events;
|
||||
using Robust.Server.Audio;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._White.Cult.Items.Systems;
|
||||
|
||||
public sealed class MagicHandSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly StunSystem _stun = default!;
|
||||
[Dependency] private readonly ChatSystem _chat = default!;
|
||||
[Dependency] private readonly HolyWeaponSystem _holyWeapon = default!;
|
||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||
[Dependency] private readonly BloodstreamSystem _bloodstream = default!;
|
||||
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageable = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||
[Dependency] private readonly AudioSystem _audio = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly TransformSystem _transform = default!;
|
||||
[Dependency] private readonly SolutionContainerSystem _solutionSystem = default!;
|
||||
[Dependency] private readonly HandsSystem _handsSystem = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _ui = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<CultStunHandComponent, MeleeHitEvent>(OnStunHit);
|
||||
SubscribeLocalEvent<CultRitesHandComponent, MeleeHitEvent>(OnRitesHit);
|
||||
SubscribeLocalEvent<CultRitesHandComponent, AfterInteractEvent>(OnInteract);
|
||||
SubscribeLocalEvent<CultRitesHandComponent, CultistFactoryItemSelectedMessage>(OnBloodRitesSelected);
|
||||
SubscribeLocalEvent<CultRitesHandComponent, ActivatableUIOpenAttemptEvent>(OnRitesSelectAttempt);
|
||||
SubscribeLocalEvent<CultRitesHandComponent, BeforeActivatableUIOpenEvent>(BeforeRitesSelect);
|
||||
SubscribeLocalEvent<CultRitesHandComponent, ExaminedEvent>(OnExamine);
|
||||
}
|
||||
|
||||
private void OnExamine(Entity<CultRitesHandComponent> ent, ref ExaminedEvent args)
|
||||
{
|
||||
var user = args.Examiner;
|
||||
if (user != Transform(ent).ParentUid || !TryComp(user, out CultistComponent? cultist))
|
||||
return;
|
||||
args.PushMarkup(Loc.GetString("cult-rites-examine", ("blood", cultist.RitesBloodAmount)));
|
||||
}
|
||||
|
||||
private void BeforeRitesSelect(Entity<CultRitesHandComponent> ent, ref BeforeActivatableUIOpenEvent args)
|
||||
{
|
||||
if (_ui.TryGetUi(ent, BloodRitesUi.Key, out var bui))
|
||||
_ui.SetUiState(bui, new CultistFactoryBUIState(ent.Comp.BloodRites));
|
||||
}
|
||||
|
||||
private void OnRitesSelectAttempt(Entity<CultRitesHandComponent> ent, ref ActivatableUIOpenAttemptEvent args)
|
||||
{
|
||||
if (!HasComp<CultistComponent>(args.User))
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
private void OnBloodRitesSelected(Entity<CultRitesHandComponent> ent, ref CultistFactoryItemSelectedMessage args)
|
||||
{
|
||||
var attachedEntity = args.Session.AttachedEntity;
|
||||
|
||||
if (!TryComp(attachedEntity, out CultistComponent? cultist))
|
||||
return;
|
||||
|
||||
if (!_prototypeManager.TryIndex<CultistFactoryProductionPrototype>(args.Item, out var prototype))
|
||||
return;
|
||||
|
||||
var uid = attachedEntity.Value;
|
||||
|
||||
if (cultist.RitesBloodAmount < prototype.BloodCost)
|
||||
{
|
||||
var message = Loc.GetString("cult-rites-no-blood", ("required", prototype.BloodCost),
|
||||
("blood", cultist.RitesBloodAmount));
|
||||
Popup(message, uid);
|
||||
return;
|
||||
}
|
||||
|
||||
Speak(uid, ent.Comp);
|
||||
Del(ent);
|
||||
|
||||
var success = false;
|
||||
foreach (var entity in prototype.Item.Select(item => Spawn(item, Transform(uid).Coordinates)))
|
||||
{
|
||||
if (_handsSystem.TryPickupAnyHand(uid, entity))
|
||||
{
|
||||
success = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
Popup(Loc.GetString("cult-rites-no-hand"), uid);
|
||||
QueueDel(entity);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!success)
|
||||
return;
|
||||
|
||||
cultist.RitesBloodAmount -= prototype.BloodCost;
|
||||
}
|
||||
|
||||
private void OnInteract(Entity<CultRitesHandComponent> ent, ref AfterInteractEvent args)
|
||||
{
|
||||
if (!args.CanReach || args.Target is not { } target)
|
||||
return;
|
||||
|
||||
var puddleQuery = GetEntityQuery<PuddleComponent>();
|
||||
if (!puddleQuery.HasComp(target))
|
||||
return;
|
||||
|
||||
if (!TryComp(args.User, out BloodstreamComponent? bloodstreamComponent) ||
|
||||
!TryComp(args.User, out CultistComponent? cultist))
|
||||
return;
|
||||
|
||||
var xform = Transform(target);
|
||||
|
||||
var entitiesInRange = _lookup.GetEntitiesInRange(_transform.GetMapCoordinates(xform), 1.5f);
|
||||
|
||||
var totalBloodAmount = FixedPoint2.Zero;
|
||||
|
||||
foreach (var solutionEntity in entitiesInRange.ToList())
|
||||
{
|
||||
if (!puddleQuery.TryComp(solutionEntity, out var puddleComponent))
|
||||
continue;
|
||||
|
||||
if (!_solutionSystem.TryGetSolution(solutionEntity, puddleComponent.SolutionName, out var solution))
|
||||
continue;
|
||||
|
||||
var hasBlood = false;
|
||||
foreach (var solutionContent in solution.Value.Comp.Solution.Contents.ToList()
|
||||
.Where(solutionContent => solutionContent.Reagent.Prototype == "Blood"))
|
||||
{
|
||||
hasBlood = true;
|
||||
totalBloodAmount += solutionContent.Quantity;
|
||||
|
||||
_bloodstream.TryModifyBloodLevel(args.User, solutionContent.Quantity / 6f, bloodstreamComponent);
|
||||
_solutionSystem.RemoveReagent((Entity<SolutionComponent>) solution, "Blood", FixedPoint2.MaxValue);
|
||||
}
|
||||
|
||||
if (hasBlood)
|
||||
Spawn("CultTileEffect", Transform(solutionEntity).Coordinates);
|
||||
}
|
||||
|
||||
if (totalBloodAmount <= FixedPoint2.Zero)
|
||||
return;
|
||||
|
||||
cultist.RitesBloodAmount += totalBloodAmount;
|
||||
|
||||
_audio.PlayPvs(ent.Comp.SuckSound, args.User);
|
||||
_popupSystem.PopupEntity(Loc.GetString("cult-rites-message", ("blood", cultist.RitesBloodAmount)),
|
||||
args.User, args.User);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnRitesHit(Entity<CultRitesHandComponent> ent, ref MeleeHitEvent args)
|
||||
{
|
||||
if (args.HitEntities.Count == 0)
|
||||
return;
|
||||
|
||||
var target = args.HitEntities[0];
|
||||
var (uid, comp) = ent;
|
||||
|
||||
QueueDel(uid);
|
||||
|
||||
if (!TryComp(args.User, out CultistComponent? cultist) || !TryComp(target, out DamageableComponent? damageable))
|
||||
return;
|
||||
|
||||
if (_mobState.IsDead(target))
|
||||
{
|
||||
Popup(Loc.GetString("cult-rites-dead"), args.User);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cultist.RitesBloodAmount <= FixedPoint2.Zero)
|
||||
{
|
||||
Popup(Loc.GetString("cult-rites-heal-no-blood"), args.User);
|
||||
return;
|
||||
}
|
||||
|
||||
var damage = damageable.Damage;
|
||||
var totalDamage = damage.GetTotal();
|
||||
if (totalDamage <= FixedPoint2.Zero)
|
||||
{
|
||||
Popup(Loc.GetString("cult-rites-already-healed"), args.User);
|
||||
return;
|
||||
}
|
||||
|
||||
var coef = FixedPoint2.Min(cultist.RitesBloodAmount * comp.HealModifier, totalDamage) / totalDamage;
|
||||
cultist.RitesBloodAmount =
|
||||
FixedPoint2.Max(FixedPoint2.Zero, cultist.RitesBloodAmount - totalDamage / comp.HealModifier);
|
||||
_damageable.TryChangeDamage(target, -damage * coef, true, false, damageable, args.User);
|
||||
Popup(Loc.GetString("cult-rites-after-heal", ("blood", cultist.RitesBloodAmount)), args.User);
|
||||
_audio.PlayPvs(comp.HealSound, target);
|
||||
Speak(args.User, comp);
|
||||
}
|
||||
|
||||
private void OnStunHit(Entity<CultStunHandComponent> ent, ref MeleeHitEvent args)
|
||||
{
|
||||
if (args.HitEntities.Count == 0)
|
||||
return;
|
||||
|
||||
var target = args.HitEntities[0];
|
||||
var (uid, comp) = ent;
|
||||
|
||||
QueueDel(uid);
|
||||
Spawn("CultStunFlashEffect", Transform(target).Coordinates);
|
||||
Speak(args.User, comp);
|
||||
if (TryComp(args.User, out BloodstreamComponent? bloodstream))
|
||||
_bloodstream.TryModifyBloodLevel(args.User, -10, bloodstream, createPuddle: false);
|
||||
|
||||
if (_holyWeapon.IsHoldingHolyWeapon(target))
|
||||
{
|
||||
Popup(Loc.GetString("cult-magic-holy"), args.User, PopupType.MediumCaution);
|
||||
return;
|
||||
}
|
||||
|
||||
var halo = HasComp<PentagramComponent>(args.User);
|
||||
|
||||
_statusEffects.TryAddStatusEffect(target, "Muted", halo ? comp.HaloMuteDuration : comp.MuteDuration, true,
|
||||
"Muted");
|
||||
_stun.TryParalyze(target, halo ? comp.HaloDuration : comp.Duration, true);
|
||||
}
|
||||
|
||||
private void Popup(string msg, EntityUid user, PopupType type = PopupType.Small)
|
||||
{
|
||||
_popupSystem.PopupEntity(msg, user, user, type);
|
||||
}
|
||||
|
||||
private void Speak(EntityUid user, BaseMagicHandComponent comp)
|
||||
{
|
||||
_chat.TrySendInGameICMessage(user, comp.Speech, InGameICChatType.Whisper, false);
|
||||
}
|
||||
}
|
||||
@@ -8,14 +8,9 @@ using Content.Server._White.Cult.UI;
|
||||
using Content.Server._White.Wizard.Magic;
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Shared._White.Chaplain;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Fluids.Components;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Stacks;
|
||||
using Content.Shared.StatusEffect;
|
||||
using Content.Shared.Stunnable;
|
||||
using Content.Shared._White.Cult.Actions;
|
||||
using Content.Shared._White.Cult.Components;
|
||||
@@ -25,8 +20,8 @@ using Content.Shared.Actions;
|
||||
using Content.Shared.Cuffs;
|
||||
using Content.Shared.Cuffs.Components;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Doors.Components;
|
||||
using Content.Shared.Maps;
|
||||
using Content.Shared.Mindshield.Components;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio;
|
||||
@@ -72,6 +67,21 @@ public partial class CultSystem
|
||||
SubscribeLocalEvent<CultistComponent, CultStunActionEvent>(OnStun);
|
||||
SubscribeLocalEvent<CultistComponent, ActionGettingRemovedEvent>(OnActionRemoved);
|
||||
SubscribeLocalEvent<CultistComponent, ShacklesEvent>(OnShackles);
|
||||
SubscribeLocalEvent<CultistComponent, TwistedConstructionEvent>(OnTwistedConstruction);
|
||||
}
|
||||
|
||||
private void OnTwistedConstruction(Entity<CultistComponent> ent, ref TwistedConstructionEvent args)
|
||||
{
|
||||
if (args.Cancelled)
|
||||
QueueDel(GetEntity(args.Effect));
|
||||
|
||||
if (args.Handled || args.Cancelled)
|
||||
return;
|
||||
|
||||
args.Handled = true;
|
||||
|
||||
Del(args.Target);
|
||||
Spawn(args.RunicDoor, GetCoordinates(args.Location));
|
||||
}
|
||||
|
||||
private void OnShackles(Entity<CultistComponent> ent, ref ShacklesEvent args)
|
||||
@@ -106,15 +116,7 @@ public partial class CultSystem
|
||||
|
||||
private void OnStun(EntityUid uid, CultistComponent component, CultStunActionEvent args)
|
||||
{
|
||||
var entity = Spawn("StunHand", Transform(uid).Coordinates);
|
||||
if (!_handsSystem.TryPickupAnyHand(uid, entity))
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("cult-magic-no-empty-hand"), uid, uid);
|
||||
QueueDel(entity);
|
||||
_actionsSystem.SetCooldown(args.Action, TimeSpan.FromSeconds(1));
|
||||
return;
|
||||
}
|
||||
args.Handled = true;
|
||||
GrantItem(uid, "StunHand", args);
|
||||
}
|
||||
|
||||
private void OnTeleport(EntityUid uid, CultistComponent component, CultTeleportTargetActionEvent args)
|
||||
@@ -123,22 +125,14 @@ public partial class CultSystem
|
||||
!TryComp<ActorComponent>(uid, out var actor))
|
||||
return;
|
||||
|
||||
if (_holyWeapon.IsHoldingHolyWeapon(args.Target))
|
||||
if (!HasComp<CultistComponent>(args.Target))
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("cult-magic-holy"), args.Performer, args.Performer,
|
||||
_popupSystem.PopupEntity("Цель должна быть культистом.", args.Performer, args.Performer,
|
||||
PopupType.MediumCaution);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!HasComp<CultistComponent>(args.Target) && !HasComp<ConstructComponent>(args.Target) &&
|
||||
_actionBlocker.CanInteract(args.Target, null))
|
||||
{
|
||||
_popupSystem.PopupEntity("Цель должна быть культистом, быть скованной или парализованной.", args.Performer,
|
||||
args.Performer, PopupType.MediumCaution);
|
||||
return;
|
||||
}
|
||||
|
||||
_bloodstreamSystem.TryModifyBloodLevel(uid, -5, bloodstream, createPuddle: false);
|
||||
_bloodstreamSystem.TryModifyBloodLevel(uid, -7, bloodstream, createPuddle: false);
|
||||
|
||||
var eui = new CultTeleportSpellEui(args.Performer, args.Target);
|
||||
_euiManager.OpenEui(eui, actor.PlayerSession);
|
||||
@@ -150,61 +144,7 @@ public partial class CultSystem
|
||||
|
||||
private void OnBloodRites(EntityUid uid, CultistComponent component, CultBloodRitesInstantActionEvent args)
|
||||
{
|
||||
if (!TryComp<BloodstreamComponent>(args.Performer, out var bloodstreamComponent))
|
||||
return;
|
||||
|
||||
var bruteDamageGroup = _prototypeManager.Index<DamageGroupPrototype>("Brute");
|
||||
var burnDamageGroup = _prototypeManager.Index<DamageGroupPrototype>("Burn");
|
||||
|
||||
var xform = Transform(uid);
|
||||
|
||||
var entitiesInRange = _lookup.GetEntitiesInRange(_transform.GetMapCoordinates(xform), 1.5f);
|
||||
|
||||
FixedPoint2 totalBloodAmount = 0f;
|
||||
|
||||
var breakLoop = false;
|
||||
foreach (var solutionEntity in entitiesInRange.ToList())
|
||||
{
|
||||
if (breakLoop)
|
||||
break;
|
||||
|
||||
if (!TryComp<PuddleComponent>(solutionEntity, out var puddleComponent))
|
||||
continue;
|
||||
|
||||
if (!_solutionSystem.TryGetSolution(solutionEntity, puddleComponent.SolutionName, out var solution))
|
||||
continue;
|
||||
|
||||
foreach (var solutionContent in solution.Value.Comp.Solution.Contents.ToList())
|
||||
{
|
||||
if (solutionContent.Reagent.Prototype != "Blood")
|
||||
continue;
|
||||
|
||||
totalBloodAmount += solutionContent.Quantity;
|
||||
|
||||
_bloodstreamSystem.TryModifyBloodLevel(uid, solutionContent.Quantity / 6f, bloodstreamComponent);
|
||||
_solutionSystem.RemoveReagent((Entity<SolutionComponent>) solution, "Blood", FixedPoint2.MaxValue);
|
||||
|
||||
/*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);
|
||||
|
||||
Speak(args);
|
||||
args.Handled = true;
|
||||
GrantItem(uid, "RitesHand", args);
|
||||
}
|
||||
|
||||
private static FixedPoint2 GetMissingBloodValue(BloodstreamComponent bloodstreamComponent)
|
||||
@@ -429,13 +369,47 @@ public partial class CultSystem
|
||||
if (!TryComp(args.Target, out CuffableComponent? cuffs) || cuffs.Container.ContainedEntities.Count > 0)
|
||||
return;
|
||||
|
||||
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, args.Performer, TimeSpan.FromSeconds(2),
|
||||
new ShacklesEvent(), args.Performer, args.Target)
|
||||
var doAfterArgs = new DoAfterArgs(EntityManager, args.Performer, TimeSpan.FromSeconds(2), new ShacklesEvent(),
|
||||
args.Performer, args.Target)
|
||||
{
|
||||
BreakOnMove = true,
|
||||
BreakOnDamage = true
|
||||
});
|
||||
};
|
||||
|
||||
if (!_doAfterSystem.TryStartDoAfter(doAfterArgs))
|
||||
return;
|
||||
|
||||
Speak(args);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void ConvertDoor(EntityUid uid, EntityUid target, BloodstreamComponent bloodstream,
|
||||
CultTwistedConstructionActionEvent args)
|
||||
{
|
||||
var meta = MetaData(target);
|
||||
if (meta.EntityPrototype?.ID == args.RunicDoor.Id)
|
||||
return;
|
||||
|
||||
var xform = Transform(target);
|
||||
if (!xform.Anchored)
|
||||
return;
|
||||
|
||||
var effect = Spawn(args.Effect, xform.Coordinates);
|
||||
var ev = new TwistedConstructionEvent(GetNetEntity(effect), args.RunicDoor, GetNetCoordinates(xform.Coordinates));
|
||||
var doAfterArgs = new DoAfterArgs(EntityManager, uid, args.Delay, ev, uid, target)
|
||||
{
|
||||
BreakOnDamage = true,
|
||||
BreakOnMove = true,
|
||||
};
|
||||
|
||||
if (!_doAfterSystem.TryStartDoAfter(doAfterArgs))
|
||||
{
|
||||
QueueDel(effect);
|
||||
return;
|
||||
}
|
||||
|
||||
_audio.PlayPvs(args.Sound, xform.Coordinates);
|
||||
_bloodstreamSystem.TryModifyBloodLevel(uid, -12, bloodstream, createPuddle: false);
|
||||
Speak(args);
|
||||
args.Handled = true;
|
||||
}
|
||||
@@ -451,6 +425,12 @@ public partial class CultSystem
|
||||
if (!TryComp<BloodstreamComponent>(args.Performer, out var bloodstreamComponent))
|
||||
return;
|
||||
|
||||
if (HasComp<DoorComponent>(args.Target))
|
||||
{
|
||||
ConvertDoor(uid, args.Target, bloodstreamComponent, args);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_entityManager.TryGetComponent<StackComponent>(args.Target, out var stack))
|
||||
return;
|
||||
|
||||
@@ -497,4 +477,17 @@ public partial class CultSystem
|
||||
{
|
||||
_spells.Speak(args, InGameICChatType.Whisper);
|
||||
}
|
||||
|
||||
public void GrantItem(EntityUid uid, string proto, InstantActionEvent args)
|
||||
{
|
||||
var entity = Spawn(proto, Transform(uid).Coordinates);
|
||||
if (!_handsSystem.TryPickupAnyHand(uid, entity))
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("cult-magic-no-empty-hand"), uid, uid);
|
||||
QueueDel(entity);
|
||||
_actionsSystem.SetCooldown(args.Action, TimeSpan.FromSeconds(1));
|
||||
return;
|
||||
}
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.GameTicking;
|
||||
using System.Linq;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server._White.Cult.GameRule;
|
||||
@@ -46,9 +47,10 @@ public partial class CultSystem
|
||||
|
||||
private void OnMapInit(EntityUid uid, ConstructComponent component, MapInitEvent args)
|
||||
{
|
||||
foreach (var id in component.Actions)
|
||||
foreach (var action in component.Actions.Select(id => _actionsSystem.AddAction(uid, id)))
|
||||
{
|
||||
component.ActionEntities.Add(_actionsSystem.AddAction(uid, id));
|
||||
_actionsSystem.StartUseDelay(action);
|
||||
component.ActionEntities.Add(action);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ public sealed partial class CultSystem : EntitySystem
|
||||
|
||||
SubscribeLocalEvent<CultEmpowerComponent, CultEmpowerSelectedBuiMessage>(OnEmpowerSelected);
|
||||
SubscribeLocalEvent<CultEmpowerComponent, UseInHandEvent>(OnUseInHand);
|
||||
SubscribeLocalEvent<CultEmpowerComponent, ActivateInWorldEvent>(OnActiveInWorld);
|
||||
SubscribeLocalEvent<CultEmpowerComponent, CultRuneInvokeEvent>(OnActiveInWorld);
|
||||
|
||||
// UI
|
||||
SubscribeLocalEvent<RuneDrawerProviderComponent, ActivatableUIOpenAttemptEvent>(OnRuneDrawAttempt);
|
||||
@@ -396,19 +396,19 @@ public sealed partial class CultSystem : EntitySystem
|
||||
|
||||
if (ev.Result)
|
||||
{
|
||||
OnAfterInvoke(uid, cultists);
|
||||
OnAfterInvoke(uid, cultists, ev.InvokePhraseOverride);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAfterInvoke(EntityUid rune, HashSet<EntityUid> cultists)
|
||||
private void OnAfterInvoke(EntityUid rune, HashSet<EntityUid> cultists, string? invokePhraseOverride = null)
|
||||
{
|
||||
if (!_entityManager.TryGetComponent<CultRuneBaseComponent>(rune, out var component))
|
||||
return;
|
||||
|
||||
foreach (var cultist in cultists)
|
||||
{
|
||||
_chat.TrySendInGameICMessage(cultist, component.InvokePhrase, component.InvokeChatType, false, false, null,
|
||||
null, null, false);
|
||||
_chat.TrySendInGameICMessage(cultist, invokePhraseOverride ?? component.InvokePhrase,
|
||||
component.InvokeChatType, false, false, null, null, null, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,16 +455,19 @@ public sealed partial class CultSystem : EntitySystem
|
||||
!HasComp<MindShieldComponent>(victim.Value))
|
||||
{
|
||||
result = Convert(uid, victim.Value, args.User, args.Cultists);
|
||||
args.InvokePhraseOverride = "Mah'weyh pleggh at e'ntrath!";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = Sacrifice(uid, victim.Value, args.User, args.Cultists);
|
||||
args.InvokePhraseOverride = "Barhah hra zar'garis!";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Жертва мертва, выполняется альтернативное действие
|
||||
result = SacrificeNonObjectiveDead(uid, victim.Value, args.User, args.Cultists);
|
||||
args.InvokePhraseOverride = "Barhah hra zar'garis!";
|
||||
}
|
||||
|
||||
args.Result = result;
|
||||
@@ -1217,13 +1220,14 @@ public sealed partial class CultSystem : EntitySystem
|
||||
* Empower rune start ----
|
||||
*/
|
||||
|
||||
private void OnActiveInWorld(EntityUid uid, CultEmpowerComponent component, ActivateInWorldEvent args)
|
||||
private void OnActiveInWorld(EntityUid uid, CultEmpowerComponent component, CultRuneInvokeEvent args)
|
||||
{
|
||||
if (!component.IsRune || !TryComp<CultistComponent>(args.User, out _) ||
|
||||
!TryComp<ActorComponent>(args.User, out var actor))
|
||||
return;
|
||||
|
||||
_ui.TryOpen(uid, CultEmpowerUiKey.Key, actor.PlayerSession);
|
||||
args.Result = !_ui.SessionHasOpenUi(uid, CultEmpowerUiKey.Key, actor.PlayerSession) &&
|
||||
_ui.TryOpen(uid, CultEmpowerUiKey.Key, actor.PlayerSession);
|
||||
}
|
||||
|
||||
private void OnUseInHand(EntityUid uid, CultEmpowerComponent component, UseInHandEvent args)
|
||||
@@ -1377,6 +1381,7 @@ public sealed partial class CultSystem : EntitySystem
|
||||
var shard = _entityManager.SpawnEntity("SoulShard", transform.Value);
|
||||
|
||||
_mindSystem.TransferTo(mindComponent.Mind.Value, shard);
|
||||
_mindSystem.UnVisit(mindComponent.Mind.Value);
|
||||
|
||||
_bodySystem.GibBody(target);
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ 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;
|
||||
@@ -17,7 +16,6 @@ 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)
|
||||
@@ -100,24 +98,8 @@ 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)
|
||||
@@ -130,36 +112,4 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
168
Content.Server/_White/Items/PseudoItem/PseudoItemSystem.cs
Normal file
@@ -0,0 +1,168 @@
|
||||
using Content.Server._White.Carrying;
|
||||
using Content.Shared.Verbs;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Server.Storage.EntitySystems;
|
||||
using Content.Server.Item;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Resist;
|
||||
using Content.Shared._White.Item.PseudoItem;
|
||||
using Content.Shared.Resist;
|
||||
using Content.Shared.Storage;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Containers;
|
||||
|
||||
namespace Content.Server._White.Items.PseudoItem;
|
||||
|
||||
public sealed class PseudoItemSystem : SharedPseudoItemSystem
|
||||
{
|
||||
[Dependency] private readonly TransformSystem _transform = default!;
|
||||
[Dependency] private readonly StorageSystem _storageSystem = default!;
|
||||
[Dependency] private readonly ItemSystem _itemSystem = default!;
|
||||
[Dependency] private readonly CarryingSystem _carrying = default!;
|
||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<PseudoItemComponent, EntGotRemovedFromContainerMessage>(OnEntRemoved);
|
||||
SubscribeLocalEvent<PseudoItemComponent, DropAttemptEvent>(OnDropAttempt);
|
||||
SubscribeLocalEvent<PseudoItemComponent, EscapeInventoryEvent>(OnEscape);
|
||||
SubscribeLocalEvent<StorageComponent, GetVerbsEvent<AlternativeVerb>>(AddAltVerb);
|
||||
SubscribeLocalEvent<StorageComponent, GetVerbsEvent<Verb>>(AddVerb);
|
||||
SubscribeLocalEvent<StorageComponent, PseudoItemInteractEvent>(OnInteract);
|
||||
}
|
||||
|
||||
private void OnInteract(Entity<StorageComponent> ent, ref PseudoItemInteractEvent args)
|
||||
{
|
||||
if (!TryComp(args.Used, out PseudoItemComponent? pseudoItem))
|
||||
return;
|
||||
|
||||
if (!TryInsert(ent.Owner, args.Used, args.User, pseudoItem, ent.Comp))
|
||||
return;
|
||||
|
||||
_carrying.DropCarried(args.User, args.Used, false, false);
|
||||
}
|
||||
|
||||
private void OnEscape(Entity<PseudoItemComponent> ent, ref EscapeInventoryEvent args)
|
||||
{
|
||||
NoLongerInContainer(ent.Owner, ent.Comp);
|
||||
}
|
||||
|
||||
private void AddAltVerb(Entity<StorageComponent> ent, ref GetVerbsEvent<AlternativeVerb> args)
|
||||
{
|
||||
if (!args.CanInteract || !args.CanAccess)
|
||||
return;
|
||||
|
||||
var user = args.User;
|
||||
|
||||
var (uid, comp) = ent;
|
||||
|
||||
if (!TryComp(user, out PseudoItemComponent? pseudoItem) || pseudoItem.Active)
|
||||
return;
|
||||
|
||||
if (Transform(uid).ParentUid == user)
|
||||
return;
|
||||
|
||||
AlternativeVerb verb = new()
|
||||
{
|
||||
Act = () =>
|
||||
{
|
||||
TryInsert(uid, user, user, pseudoItem, comp);
|
||||
},
|
||||
Text = Loc.GetString("action-name-insert-self"),
|
||||
};
|
||||
args.Verbs.Add(verb);
|
||||
}
|
||||
|
||||
private void AddVerb(Entity<StorageComponent> ent, ref GetVerbsEvent<Verb> args)
|
||||
{
|
||||
if (!args.CanInteract || !args.CanAccess)
|
||||
return;
|
||||
|
||||
var user = args.User;
|
||||
|
||||
var (uid, comp) = ent;
|
||||
|
||||
if (!TryComp(user, out CarryingComponent? carrying))
|
||||
return;
|
||||
|
||||
var carried = carrying.Carried;
|
||||
|
||||
if (!TryComp(carried, out PseudoItemComponent? pseudoItem))
|
||||
return;
|
||||
|
||||
Verb verb = new()
|
||||
{
|
||||
Act = () =>
|
||||
{
|
||||
if (TryInsert(uid, carried, user, pseudoItem, comp))
|
||||
_carrying.DropCarried(user, carried, false, false);
|
||||
},
|
||||
Text = Loc.GetString("action-name-insert-other"),
|
||||
};
|
||||
args.Verbs.Add(verb);
|
||||
}
|
||||
|
||||
private void OnEntRemoved(EntityUid uid, PseudoItemComponent component, EntGotRemovedFromContainerMessage args)
|
||||
{
|
||||
NoLongerInContainer(uid, component);
|
||||
}
|
||||
|
||||
protected override void OnGettingPickedUp(Entity<PseudoItemComponent> ent, GettingPickedUpAttemptEvent args)
|
||||
{
|
||||
base.OnGettingPickedUp(ent, args);
|
||||
|
||||
if (args.User == args.Item)
|
||||
return;
|
||||
|
||||
if (!TryComp(ent, out CarriableComponent? carriable))
|
||||
_transform.AttachToGridOrMap(ent);
|
||||
else if (_carrying.CanCarry(args.User, ent))
|
||||
_carrying.StartCarryDoAfter(args.User, ent, carriable);
|
||||
}
|
||||
|
||||
private void OnDropAttempt(EntityUid uid, PseudoItemComponent component, DropAttemptEvent args)
|
||||
{
|
||||
if (component.Active)
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
public bool TryInsert(EntityUid storageUid,
|
||||
EntityUid toInsert,
|
||||
EntityUid user,
|
||||
PseudoItemComponent component,
|
||||
StorageComponent? storage = null)
|
||||
{
|
||||
if (!Resolve(storageUid, ref storage))
|
||||
return false;
|
||||
|
||||
var item = EnsureComp<ItemComponent>(toInsert);
|
||||
_itemSystem.SetSize(toInsert, component.Size, item);
|
||||
_itemSystem.SetShape(toInsert, component.Shape, item);
|
||||
|
||||
Dirty(toInsert, component);
|
||||
if (!_storageSystem.Insert(storageUid, toInsert, out _, user, storage))
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("comp-storage-cant-insert"), user, user);
|
||||
component.Active = false;
|
||||
RemComp<ItemComponent>(toInsert);
|
||||
return false;
|
||||
}
|
||||
|
||||
component.Active = true;
|
||||
EnsureComp<CanEscapeInventoryComponent>(toInsert);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void NoLongerInContainer(EntityUid uid, PseudoItemComponent component)
|
||||
{
|
||||
if (!component.Active)
|
||||
return;
|
||||
|
||||
RemCompDeferred<CanEscapeInventoryComponent>(uid);
|
||||
RemCompDeferred<ItemComponent>(uid);
|
||||
component.Active = false;
|
||||
Dirty(uid, component);
|
||||
}
|
||||
}
|
||||
@@ -69,12 +69,18 @@ public sealed class OfferItemSystem : SharedOfferItemSystem
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("offer-item-give",
|
||||
("item", Identity.Entity(offerItem.Item.Value, EntityManager)),
|
||||
("target", Identity.Entity(uid, EntityManager))), component.Target.Value, component.Target.Value);
|
||||
("target", Identity.Entity(uid, EntityManager))),
|
||||
component.Target.Value,
|
||||
component.Target.Value);
|
||||
_popup.PopupEntity(Loc.GetString("offer-item-give-other",
|
||||
("user", Identity.Entity(component.Target.Value, EntityManager)),
|
||||
("item", Identity.Entity(offerItem.Item.Value, EntityManager)),
|
||||
("target", Identity.Entity(uid, EntityManager)))
|
||||
, component.Target.Value, Filter.PvsExcept(component.Target.Value, entityManager: EntityManager), true);
|
||||
("target", Identity.Entity(uid, EntityManager))),
|
||||
component.Target.Value,
|
||||
Filter.PvsExcept(component.Target.Value, entityManager: EntityManager),
|
||||
true);
|
||||
|
||||
RaiseLocalEvent(offerItem.Item.Value, new HandedEvent(component.Target.Value, uid));
|
||||
}
|
||||
|
||||
offerItem.Item = null;
|
||||
|
||||
@@ -24,6 +24,7 @@ using Content.Shared._White.Antag;
|
||||
using Content.Shared._White.BetrayalDagger;
|
||||
using Content.Shared._White.Cult.Components;
|
||||
using Content.Shared._White.Events;
|
||||
using Content.Shared._White.Item.PseudoItem;
|
||||
using Content.Shared._White.Wizard;
|
||||
using Content.Shared._White.Wizard.Magic;
|
||||
using Content.Shared.Actions;
|
||||
@@ -854,6 +855,9 @@ public sealed class WizardSpellsSystem : EntitySystem
|
||||
|
||||
public bool CanCast(BaseActionEvent msg)
|
||||
{
|
||||
if (TryComp(msg.Performer, out PseudoItemComponent? pseudoItem) && pseudoItem.Active)
|
||||
return false;
|
||||
|
||||
return !msg.Handled && CheckRequirements(msg.Action, msg.Performer) &&
|
||||
!_statusEffectsSystem.HasStatusEffect(msg.Performer, "Incorporeal");
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using Content.Shared.Clothing.Components;
|
||||
using Content.Shared.Movement.Components;
|
||||
using Content.Shared._White.Animations;
|
||||
using Content.Shared.Clothing.Components;
|
||||
using Content.Shared.Inventory.Events;
|
||||
|
||||
namespace Content.Client.Clothing.Systems;
|
||||
namespace Content.Shared.Clothing.EntitySystems;
|
||||
|
||||
public sealed class WaddleClothingSystem : EntitySystem
|
||||
{
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Shared._White.Item.PseudoItem;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Interaction;
|
||||
@@ -67,7 +68,8 @@ public abstract class SharedVirtualItemSystem : EntitySystem
|
||||
private void OnBeforeRangedInteract(Entity<VirtualItemComponent> ent, ref BeforeRangedInteractEvent args)
|
||||
{
|
||||
// No interactions with a virtual item, please.
|
||||
args.Handled = true;
|
||||
if (!HasComp<PseudoItemComponent>(ent.Comp.BlockingEntity))
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
#region Hands
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Frozen;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Content.Shared._White.Item.PseudoItem;
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
using Content.Shared.Coordinates;
|
||||
@@ -10,6 +11,7 @@ using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Implants.Components;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Inventory.VirtualItem;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Lock;
|
||||
using Content.Shared.Materials;
|
||||
@@ -223,6 +225,12 @@ public abstract class SharedStorageSystem : EntitySystem
|
||||
if (HasComp<PlaceableSurfaceComponent>(uid))
|
||||
return;
|
||||
|
||||
if (TryComp<VirtualItemComponent>(args.Used, out var virtualItem)) // WD
|
||||
{
|
||||
RaiseLocalEvent(uid, new PseudoItemInteractEvent(virtualItem.BlockingEntity, args.User));
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerInsertHeldEntity(uid, args.User, storageComp);
|
||||
// Always handle it, even if insertion fails.
|
||||
// We don't want to trigger any AfterInteract logic here.
|
||||
@@ -1072,7 +1080,7 @@ public abstract class SharedStorageSystem : EntitySystem
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
var saved = list[i];
|
||||
|
||||
|
||||
if (saved == location)
|
||||
{
|
||||
list.Remove(location);
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis;
|
||||
using System.Numerics;
|
||||
using Content.Shared._White.Containers;
|
||||
using Content.Shared._White.Events;
|
||||
using Content.Shared._White.Item.PseudoItem;
|
||||
using Content.Shared._White.WeaponModules;
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.Actions;
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
using Content.Shared.Movement.Events;
|
||||
using Content.Shared.Standing.Systems;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Shared._White.Animations;
|
||||
|
||||
public abstract class SharedWaddledAnimationSystem : EntitySystem
|
||||
{
|
||||
[Dependency] protected readonly IGameTiming Timing = default!;
|
||||
[Dependency] private readonly SharedStandingStateSystem _standingState = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<WaddleAnimationComponent, MoveInputEvent>(OnMovementInput);
|
||||
}
|
||||
|
||||
private void OnMovementInput(EntityUid uid, WaddleAnimationComponent component, MoveInputEvent args)
|
||||
{
|
||||
if (!Timing.IsFirstTimePredicted)
|
||||
return;
|
||||
|
||||
if (_standingState.IsDown(uid))
|
||||
return;
|
||||
|
||||
if (!args.HasDirectionalMovement && component.IsCurrentlyWaddling)
|
||||
{
|
||||
component.IsCurrentlyWaddling = false;
|
||||
|
||||
StopAnimation(uid);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (component.IsCurrentlyWaddling || !args.HasDirectionalMovement)
|
||||
return;
|
||||
|
||||
component.IsCurrentlyWaddling = true;
|
||||
|
||||
PlayAnimation(uid);
|
||||
}
|
||||
|
||||
protected abstract void PlayAnimation(EntityUid user);
|
||||
|
||||
protected abstract void StopAnimation(EntityUid user);
|
||||
}
|
||||
@@ -1,30 +1,20 @@
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Movement.Components;
|
||||
namespace Content.Shared._White.Animations;
|
||||
|
||||
/// <summary>
|
||||
/// Declares that an entity has started to waddle like a duck/clown.
|
||||
/// </summary>
|
||||
/// <param name="Entity">The newly be-waddled.</param>
|
||||
[ByRefEvent]
|
||||
public record struct StartedWaddlingEvent(EntityUid Entity)
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class StartedWaddlingEvent(NetEntity user) : EntityEventArgs
|
||||
{
|
||||
public EntityUid Entity = Entity;
|
||||
public NetEntity User = user;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Declares that an entity has stopped waddling like a duck/clown.
|
||||
/// </summary>
|
||||
/// <param name="Entity">The former waddle-er.</param>
|
||||
[ByRefEvent]
|
||||
public record struct StoppedWaddlingEvent(EntityUid Entity)
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class StoppedWaddlingEvent(NetEntity user) : EntityEventArgs
|
||||
{
|
||||
public EntityUid Entity = Entity;
|
||||
public NetEntity User = user;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines something as having a waddle animation when it moves.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class WaddleAnimationComponent : Component
|
||||
{
|
||||
@@ -1,5 +1,7 @@
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Magic;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._White.Cult.Actions;
|
||||
|
||||
@@ -7,6 +9,21 @@ public sealed partial class CultTwistedConstructionActionEvent : EntityTargetAct
|
||||
{
|
||||
[DataField("speech")]
|
||||
public string? Speech { get; private set; }
|
||||
|
||||
[DataField]
|
||||
public EntProtoId RunicDoor = "AirlockGlassCult";
|
||||
|
||||
[DataField]
|
||||
public EntProtoId Effect = "EffectConstructRed";
|
||||
|
||||
[DataField]
|
||||
public TimeSpan Delay = TimeSpan.FromSeconds(4);
|
||||
|
||||
[DataField]
|
||||
public SoundSpecifier? Sound = new SoundPathSpecifier("/Audio/Machines/airlock_creaking.ogg")
|
||||
{
|
||||
Params = AudioParams.Default.WithVolume(-3f),
|
||||
};
|
||||
}
|
||||
|
||||
public sealed partial class CultSummonDaggerActionEvent : InstantActionEvent, ISpeakSpell
|
||||
|
||||
30
Content.Shared/_White/Cult/Actions/CultEvents.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Content.Shared.DoAfter;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._White.Cult.Actions;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class ShacklesEvent : SimpleDoAfterEvent
|
||||
{
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class TwistedConstructionEvent : DoAfterEvent
|
||||
{
|
||||
public NetEntity Effect { get; private set; }
|
||||
|
||||
public EntProtoId RunicDoor { get; private set; }
|
||||
|
||||
public NetCoordinates Location { get; private set; }
|
||||
|
||||
public TwistedConstructionEvent(NetEntity effect, EntProtoId runicDoor, NetCoordinates location)
|
||||
{
|
||||
Effect = effect;
|
||||
RunicDoor = runicDoor;
|
||||
Location = location;
|
||||
}
|
||||
|
||||
public override DoAfterEvent Clone() => this;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using Content.Shared.DoAfter;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._White.Cult.Actions;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class ShacklesEvent : SimpleDoAfterEvent
|
||||
{
|
||||
}
|
||||
@@ -3,7 +3,6 @@ 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;
|
||||
|
||||
@@ -51,13 +50,6 @@ public sealed partial class CultistComponent : Component
|
||||
CultSummonCombatEquipmentAction, CultStunAction, EmpPulseAction, ConcealPresenceAction, CultShadowShacklesAction
|
||||
};
|
||||
|
||||
[DataField("bloodRites", customTypeSerializer: typeof(PrototypeIdListSerializer<CultistFactoryProductionPrototype>))]
|
||||
public List<string> BloodRites = new ()
|
||||
{
|
||||
"FactoryCultBloodSpear",
|
||||
"FactoryCultBloodBarrage"
|
||||
};
|
||||
|
||||
[ViewVariables, NonSerialized]
|
||||
public Entity<BloodSpearComponent>? BloodSpear;
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ public sealed class CultRuneInvokeEvent : EntityEventArgs
|
||||
public HashSet<EntityUid> Cultists { get; }
|
||||
public bool Result { get; set; }
|
||||
|
||||
public string? InvokePhraseOverride { get; set; } = null;
|
||||
|
||||
public CultRuneInvokeEvent(EntityUid rune, EntityUid user, HashSet<EntityUid> cultists)
|
||||
{
|
||||
Rune = rune;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using Content.Shared._White.OfferItem;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Implants.Components;
|
||||
@@ -30,6 +31,7 @@ public sealed class HardlightSpearSystem : EntitySystem
|
||||
|
||||
SubscribeLocalEvent<HardlightSpearComponent, LandEvent>(OnLand);
|
||||
SubscribeLocalEvent<HardlightSpearComponent, DroppedEvent>(OnDrop);
|
||||
SubscribeLocalEvent<HardlightSpearComponent, HandedEvent>(OnHanded);
|
||||
SubscribeLocalEvent<HardlightSpearComponent, EntGotInsertedIntoContainerMessage>(OnInsert);
|
||||
SubscribeLocalEvent<HardlightSpearComponent, GettingPickedUpAttemptEvent>(OnPickupAttempt);
|
||||
SubscribeLocalEvent<HardlightSpearComponent, PreventCollideEvent>(OnPreventCollision);
|
||||
@@ -96,4 +98,9 @@ public sealed class HardlightSpearSystem : EntitySystem
|
||||
if (!HasComp<BodyComponent>(args.Container.Owner))
|
||||
EnsureComp<TimedDespawnComponent>(uid);
|
||||
}
|
||||
|
||||
private void OnHanded(EntityUid uid, HardlightSpearComponent component, ref HandedEvent args)
|
||||
{
|
||||
EnsureComp<TimedDespawnComponent>(uid);
|
||||
}
|
||||
}
|
||||
|
||||
22
Content.Shared/_White/Item/PseudoItem/PseudoItemComponent.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using Content.Shared.Item;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._White.Item.PseudoItem;
|
||||
|
||||
/// <summary>
|
||||
/// For entities that behave like an item under certain conditions,
|
||||
/// but not under most conditions.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class PseudoItemComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public ProtoId<ItemSizePrototype> Size = "Huge";
|
||||
|
||||
[DataField]
|
||||
public List<Box2i>? Shape = new() {new Box2i(0, 0, 4, 4)};
|
||||
|
||||
[AutoNetworkedField]
|
||||
public bool Active;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Item;
|
||||
|
||||
namespace Content.Shared._White.Item.PseudoItem;
|
||||
|
||||
public abstract class SharedPseudoItemSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<PseudoItemComponent, GettingPickedUpAttemptEvent>(OnGettingPickedUpAttempt);
|
||||
SubscribeLocalEvent<PseudoItemComponent, AttackAttemptEvent>(OnAttackAttempt);
|
||||
}
|
||||
|
||||
private void OnAttackAttempt(Entity<PseudoItemComponent> ent, ref AttackAttemptEvent args)
|
||||
{
|
||||
if (ent.Comp.Active)
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
private void OnGettingPickedUpAttempt(Entity<PseudoItemComponent> ent, ref GettingPickedUpAttemptEvent args)
|
||||
{
|
||||
args.Cancel();
|
||||
OnGettingPickedUp(ent, args);
|
||||
}
|
||||
|
||||
protected virtual void OnGettingPickedUp(Entity<PseudoItemComponent> ent, GettingPickedUpAttemptEvent args) {}
|
||||
}
|
||||
|
||||
public sealed class PseudoItemInteractEvent(EntityUid used, EntityUid user)
|
||||
: EntityEventArgs
|
||||
{
|
||||
public EntityUid Used { get; } = used;
|
||||
public EntityUid User { get; } = user;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using Robust.Shared.Serialization;
|
||||
using Content.Shared.DoAfter;
|
||||
|
||||
namespace Content.Shared.Item.PseudoItem
|
||||
{
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class PseudoItemInsertDoAfterEvent : SimpleDoAfterEvent
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -156,3 +156,11 @@ public abstract partial class SharedOfferItemSystem : EntitySystem
|
||||
return entity != null && Resolve(entity.Value, ref component, false) && component.IsInOfferMode;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public sealed class HandedEvent(EntityUid user, EntityUid target) : EntityEventArgs
|
||||
{
|
||||
public EntityUid User = user;
|
||||
public EntityUid Target = target;
|
||||
}
|
||||
|
||||
|
||||
BIN
Resources/Audio/White/Cult/rites.ogg
Normal file
@@ -6970,3 +6970,142 @@
|
||||
id: 425
|
||||
time: '2024-07-29T03:04:21.0000000+00:00'
|
||||
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/510
|
||||
- author: ThereDrD
|
||||
changes:
|
||||
- message: "\u0420\u041F\u0414 \u0442\u0435\u043F\u0435\u0440\u044C \u043C\u043E\
|
||||
\u0436\u0435\u0442 \u0441\u0442\u0440\u043E\u0438\u0442\u044C \u0442\u0440\u0443\
|
||||
\u0431\u044B \u0432 \u0441\u0442\u0435\u043D\u0430\u0445"
|
||||
type: Tweak
|
||||
- message: "\u041A\u0440\u0430\u0444\u0442 \u043C\u0435\u043D\u044E \u0442\u0435\
|
||||
\u043F\u0435\u0440\u044C \u0442\u043E\u0436\u0435 \u043C\u043E\u0436\u0435\u0442\
|
||||
\ \u0441\u0442\u0440\u043E\u0438\u0442\u044C \u0442\u0440\u0443\u0431\u044B\
|
||||
\ \u0432 \u0441\u0442\u0435\u043D\u0430\u0445"
|
||||
type: Tweak
|
||||
- message: "\u041F\u043E\u0444\u0438\u043A\u0448\u0435\u043D\u043E \u043F\u0435\u0447\
|
||||
\u0430\u0442\u0430\u043D\u0438\u0435 \u0437\u0430\u043F\u043E\u043B\u043D\u0435\
|
||||
\u043D\u043D\u044B\u0445 \u0420\u0426\u0414 \u0438 \u0420\u041F\u0414. \u0447\
|
||||
\u0442\u043E \u0434\u0430\u0432\u0430\u043B\u043E \u0432\u043E\u0437\u043C\u043E\
|
||||
\u0436\u043D\u043E\u0441\u0442\u044C \u0434\u044E\u043F\u0430\u0442\u044C \u043C\
|
||||
\u0430\u0442\u0435\u0440\u0438\u0430\u043B\u044B"
|
||||
type: Fix
|
||||
- message: "\u0412\u0440\u0435\u043C\u044F \u0441\u0442\u0440\u043E\u0438\u0442\u0435\
|
||||
\u043B\u044C\u0441\u0442\u0432\u0430 \u0443\u0441\u0442\u0440\u043E\u0439\u0441\
|
||||
\u0442\u0432 \u0441\u043C\u044B\u0432\u0430 \u0432 \u0420\u041F\u0414 \u0441\
|
||||
\u0442\u0430\u043B\u043E \u043F\u043E\u0431\u043E\u043B\u044C\u0448\u0435"
|
||||
type: Fix
|
||||
id: 426
|
||||
time: '2024-07-29T12:33:46.0000000+00:00'
|
||||
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/511
|
||||
- author: Spatison
|
||||
changes:
|
||||
- message: "\u0411\u043E\u0442\u0438\u043D\u043A\u0438 \u043A\u043B\u043E\u0443\u043D\
|
||||
\u0430 \u0441\u043D\u043E\u0432\u0430 \u0440\u0430\u0431\u043E\u0442\u0430\u044E\
|
||||
\u0442"
|
||||
type: Fix
|
||||
- message: "\u0421\u0432\u0435\u0442\u043E\u0432\u043E\u0435 \u043A\u043E\u043F\u044C\
|
||||
\u0435 \u0442\u0435\u043F\u0435\u0440\u044C \u0438\u0441\u0447\u0435\u0437\u0430\
|
||||
\u0435\u0442 \u0435\u0441\u043B\u0438 \u0435\u0433\u043E \u043F\u0435\u0440\u0435\
|
||||
\u0434\u0430\u0442\u044C"
|
||||
type: Fix
|
||||
id: 427
|
||||
time: '2024-07-30T00:13:05.0000000+00:00'
|
||||
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/513
|
||||
- author: Aviu
|
||||
changes:
|
||||
- message: "\u041F\u0435\u0440\u0435\u0440\u0430\u0431\u043E\u0442\u0430\u043D\u043E\
|
||||
\ \u0437\u0430\u043A\u043B\u0438\u043D\u0430\u043D\u0438\u0435 \u043A\u0440\u043E\
|
||||
\u0432\u0430\u0432\u044B\u0445 \u043E\u0431\u0440\u044F\u0434\u043E\u0432 \u043A\
|
||||
\u0443\u043B\u044C\u0442\u0430. \u0422\u0435\u043F\u0435\u0440\u044C \u043E\u043D\
|
||||
\u043E \u0434\u0430\u0451\u0442 \u0430\u0443\u0440\u0443, \u043A\u043E\u0442\
|
||||
\u043E\u0440\u043E\u0439 \u043D\u0430\u0434\u043E \u043A\u043B\u0438\u043A\u0430\
|
||||
\u0442\u044C \u043D\u0430 \u043A\u0440\u043E\u0432\u044C, \u0447\u0442\u043E\
|
||||
\u0431\u044B \u043F\u043E\u0433\u043B\u043E\u0442\u0438\u0442\u044C \u0435\u0451\
|
||||
. \u041F\u0440\u0438 \u043F\u043E\u0433\u043B\u043E\u0449\u0435\u043D\u0438\u0438\
|
||||
\ \u043E\u043D\u043E \u0431\u043E\u043B\u044C\u0448\u0435 \u043D\u0435 \u043B\
|
||||
\u0435\u0447\u0438\u0442, \u0442\u0435\u043F\u0435\u0440\u044C \u043D\u0443\u0436\
|
||||
\u043D\u043E \u0443\u0434\u0430\u0440\u0438\u0442\u044C \u0430\u0443\u0440\u043E\
|
||||
\u0439 \u043A\u0443\u043B\u044C\u0442\u0438\u0441\u0442\u0430 \u0438\u043B\u0438\
|
||||
\ \u043A\u043E\u043D\u0441\u0442\u0440\u0443\u043A\u0442\u0430 \u0434\u043B\u044F\
|
||||
\ \u043B\u0435\u0447\u0435\u043D\u0438\u044F, 1 \u0445\u043F \u0437\u0430 2\
|
||||
\ \u0432\u044B\u0441\u043E\u0441\u0430\u043D\u043D\u043E\u0439 \u043A\u0440\u043E\
|
||||
\u0432\u0438. \u0423\u0431\u0440\u0430\u043D\u044B \u043E\u0431\u0440\u044F\u0434\
|
||||
\u044B \u0438\u0437 \u0432\u0435\u0440\u0431\u0430, \u0442\u0435\u043F\u0435\
|
||||
\u0440\u044C \u043D\u0443\u0436\u043D\u043E \u0430\u043A\u0442\u0438\u0432\u0438\
|
||||
\u0440\u043E\u0432\u0430\u0442\u044C \u0430\u0443\u0440\u0443 \u0432 \u0440\u0443\
|
||||
\u043A\u0430\u0445, \u0447\u0442\u043E\u0431\u044B \u0432\u044B\u0431\u0440\u0430\
|
||||
\u0442\u044C \u043A\u043E\u043F\u044C\u0451 \u0438\u043B\u0438 \u0437\u0430\u043B\
|
||||
\u043F."
|
||||
type: Add
|
||||
- message: "\u0412\u0441\u0435 \u043A\u043E\u043D\u0441\u0442\u0440\u0443\u043A\u0442\
|
||||
\u044B \u043D\u0430\u0443\u0447\u0438\u043B\u0438\u0441\u044C \u0442\u0430\u0441\
|
||||
\u043A\u0430\u0442\u044C."
|
||||
type: Tweak
|
||||
- message: "\u0414\u0436\u0430\u0433\u0433\u0435\u0440\u043D\u0430\u0443\u0442 \u0438\
|
||||
\ \u0440\u0435\u043C\u0435\u0441\u043B\u0435\u043D\u043D\u0438\u043A \u0442\u0435\
|
||||
\u043F\u0435\u0440\u044C \u043D\u0435\u043C\u043D\u043E\u0433\u043E \u0431\u044B\
|
||||
\u0441\u0442\u0440\u0435\u0435."
|
||||
type: Tweak
|
||||
- message: "\u0422\u0435\u043F\u0435\u0440\u044C \u043F\u0440\u0438 \u043F\u043E\
|
||||
\u044F\u0432\u043B\u0435\u043D\u0438\u0438 \u043A\u043E\u043D\u0441\u0442\u0440\
|
||||
\u0443\u043A\u0442\u0430 \u0432\u0441\u0435 \u0435\u0433\u043E \u0441\u043F\u043E\
|
||||
\u0441\u043E\u0431\u043D\u043E\u0441\u0442\u0438 \u0438\u0437\u043D\u0430\u0447\
|
||||
\u0430\u043B\u044C\u043D\u043E \u0432 \u043A\u0434."
|
||||
type: Tweak
|
||||
- message: "\u0421 \u0441\u043E\u043A\u0440\u044B\u0442\u043E\u0439 \u0440\u0443\
|
||||
\u043D\u043E\u0439 \u043C\u043E\u0433\u0443\u0449\u0435\u0441\u0442\u0432\u0430\
|
||||
\ \u0431\u043E\u043B\u044C\u0448\u0435 \u043D\u0435\u043B\u044C\u0437\u044F\
|
||||
\ \u0432\u0437\u0430\u0438\u043C\u043E\u0434\u0435\u0439\u0441\u0442\u0432\u043E\
|
||||
\u0432\u0430\u0442\u044C."
|
||||
type: Tweak
|
||||
id: 428
|
||||
time: '2024-07-30T00:12:49.0000000+00:00'
|
||||
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/514
|
||||
- author: Aviu
|
||||
changes:
|
||||
- message: "\u0422\u0435\u043F\u0435\u0440\u044C \u0438\u0441\u043A\u0430\u0436\u0435\
|
||||
\u043D\u043D\u044B\u043C \u0432\u043E\u0437\u0434\u0435\u0439\u0441\u0442\u0432\
|
||||
\u0438\u0435\u043C \u043C\u043E\u0436\u043D\u043E \u043F\u0440\u0435\u0432\u0440\
|
||||
\u0430\u0442\u0438\u0442\u044C \u0448\u043B\u044E\u0437 \u0432 \u0440\u0443\u043D\
|
||||
\u0438\u0447\u0435\u0441\u043A\u0438\u0439 \u0448\u043B\u044E\u0437."
|
||||
type: Add
|
||||
- message: "\u0417\u0430\u043A\u043B\u0438\u043D\u0430\u043D\u0438\u0435 \u0442\u0435\
|
||||
\u043B\u0435\u043F\u043E\u0440\u0442\u0430 \u0442\u0435\u043F\u0435\u0440\u044C\
|
||||
\ \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442 \u0442\u043E\u043B\u044C\u043A\
|
||||
\u043E \u043D\u0430 \u043A\u0443\u043B\u044C\u0442\u0438\u0441\u0442\u043E\u0432\
|
||||
."
|
||||
type: Tweak
|
||||
- message: "\u0422\u043E\u0432\u0430\u0440\u044B \u0432 \u0438\u043D\u0436\u0435\
|
||||
\u043C\u0430\u0442\u0435 \u0442\u0435\u043F\u0435\u0440\u044C \u0431\u0435\u0441\
|
||||
\u043F\u043B\u0430\u0442\u043D\u044B\u0435."
|
||||
type: Tweak
|
||||
id: 429
|
||||
time: '2024-07-30T16:31:34.0000000+00:00'
|
||||
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/516
|
||||
- author: Aviu
|
||||
changes:
|
||||
- message: "\u0422\u0435\u043F\u0435\u0440\u044C \u0435\u0441\u043B\u0438 \u0432\
|
||||
\u0437\u044F\u0442\u044C \u043D\u0430 \u0440\u0443\u043A\u0438 \u0444\u0435\u043B\
|
||||
\u0438\u043D\u0438\u0434\u0430, \u0435\u0433\u043E \u043C\u043E\u0436\u043D\u043E\
|
||||
\ \u0437\u0430\u0441\u0443\u043D\u0443\u0442\u044C \u0432 \u0432\u0435\u0449\
|
||||
\u043C\u0435\u0448\u043E\u043A."
|
||||
type: Add
|
||||
- message: "\u0424\u0435\u043B\u0438\u043D\u0438\u0434\u044B \u043C\u043E\u0433\u0443\
|
||||
\u0442 \u0437\u0430\u043B\u0430\u0437\u0438\u0442\u044C \u0432 \u0432\u0435\u0449\
|
||||
\u043C\u0435\u0448\u043A\u0438."
|
||||
type: Add
|
||||
- message: "\u041F\u0440\u0438 \u043F\u043E\u043F\u044B\u0442\u043A\u0435 \u0432\
|
||||
\u0437\u044F\u0442\u044C \u043D\u0430 \u0440\u0443\u043A\u0438 \u0432\u044B\u0441\
|
||||
\u043A\u0430\u043A\u0438\u0432\u0430\u0435\u0442 \u043F\u043E\u043F\u0430\u043F\
|
||||
\ \u0443 \u0446\u0435\u043B\u0438."
|
||||
type: Add
|
||||
- message: "\u0424\u0435\u043B\u0438\u043D\u0438\u0434\u044B \u0431\u0435\u0440\u0443\
|
||||
\u0442\u0441\u044F \u043D\u0430 \u0440\u0443\u043A\u0438 \u0431\u044B\u0441\u0442\
|
||||
\u0440\u0435\u0435."
|
||||
type: Add
|
||||
- message: "\u0422\u0435\u043F\u0435\u0440\u044C \u0432\u0437\u044F\u0442\u0438\u0435\
|
||||
\ \u043D\u0430 \u0440\u0443\u043A\u0438 \u043F\u0440\u043E\u0438\u0441\u0445\
|
||||
\u043E\u0434\u0438\u0442 \u0431\u044B\u0441\u0442\u0440\u0435\u0435."
|
||||
type: Tweak
|
||||
id: 430
|
||||
time: '2024-07-30T16:32:26.0000000+00:00'
|
||||
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/515
|
||||
|
||||
@@ -20,10 +20,10 @@ juggernaut-create-wall-action-name = Щит
|
||||
juggernaut-create-wall-action-description = Это заклинание создает временное невидимое силовое поле для защиты себя и союзников от подавляющего огня.
|
||||
|
||||
ent-ActionCultTwistedConstruction = Искажённое Воздействие
|
||||
.desc = Зловещее заклинание, которое используют для превращения металла в рунический металл.
|
||||
.desc = Зловещее заклинание, которое используют для превращения металла в рунический металл и обычных дверей в рунические.
|
||||
|
||||
ent-ActionCultTeleport = Телепорт
|
||||
.desc = Полезное заклинание, которое телепортирует цель на выбранную руну телепотрации. Цель должна являются культистом или быть парализованной.
|
||||
.desc = Полезное заклинание, которое телепортирует культиста на выбранную руну телепотрации.
|
||||
|
||||
ent-ActionCultSummonCombatEquipment = Призыв Боевого Снаряжения
|
||||
.desc = Важное заклинание, которое позволяет вам вызвать полный набор боевого снаряжения.
|
||||
|
||||
@@ -8,6 +8,9 @@ ent-SoulShardGhost = камень душ
|
||||
ent-StunHand = оглушающая аура
|
||||
.desc = Оглушит и обезмолвит жертву при ударе.
|
||||
|
||||
ent-RitesHand = аура кровавых обрядов
|
||||
.desc = Впитывает кровь из всего, к чему прикасается. При ударе по культистам и конструктам может исцелить их. Используйте в руке, чтобы провести продвинутый обряд.
|
||||
|
||||
ent-ShadowShackles = теневые оковы
|
||||
.desc = Оковы, сковывающие запястья с помощью зловещей магии.
|
||||
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
cult-stun-component-extra-message = [color=darkgray]Выбросите ауру, чтобы навсегда избавиться от неё.[/color]
|
||||
cult-hand-component-extra-message = [color=darkgray]Выбросите ауру, чтобы навсегда избавиться от неё.[/color]
|
||||
cult-magic-holy = Сила священного предмета в руках цели препятствует магии!
|
||||
cult-magic-no-empty-hand = Вам нужна свободная рука для использования заклинания!
|
||||
|
||||
cult-rites-examine = [color=darkred]Всего высосано крови: { $blood }.[/color]
|
||||
cult-rites-message = Всего высосано крови: { $blood }.
|
||||
cult-rites-dead = Цель мертва.
|
||||
cult-rites-heal-no-blood = Нет крови для лечения.
|
||||
cult-rites-already-healed = Он не имеет повреждений.
|
||||
cult-rites-after-heal = Осталось крови: { $blood }.
|
||||
cult-rites-no-blood = Для обряда необходимо высосать { $required } крови с помощью заклинания Кровавые Обряды. Всего высосано: { $blood }.
|
||||
cult-rites-no-hand = Вам нужна свободная рука для обряда.
|
||||
|
||||
@@ -7,8 +7,3 @@ 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,4 +1,4 @@
|
||||
# Cult
|
||||
# Cult
|
||||
|
||||
ent-CultBola = магическая { ent-Bola }
|
||||
.desc = { ent-Bola.desc }
|
||||
@@ -8,3 +8,7 @@ ent-CultBola = магическая { ent-Bola }
|
||||
|
||||
ent-EnergyBola = энергобола
|
||||
.desc = Соверешенное слияние технологии и справедливости для отлова преступников.
|
||||
|
||||
action-name-insert-self = Залезть внутрь.
|
||||
action-name-insert-other = Засунуть внутрь.
|
||||
carry-start = { $carrier } пытается взять вас на руки!
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
- type: entity
|
||||
- type: entity
|
||||
id: EffectRCDBase
|
||||
abstract: true
|
||||
noSpawn: true
|
||||
@@ -15,7 +15,7 @@
|
||||
tags:
|
||||
- HideContextMenu
|
||||
- type: AnimationPlayer
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: EffectRCDBase
|
||||
id: EffectRCDDeconstructPreview
|
||||
@@ -23,7 +23,7 @@
|
||||
components:
|
||||
- type: Sprite
|
||||
state: deconstructPreview
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: EffectRCDBase
|
||||
id: EffectRCDConstruct0
|
||||
@@ -33,7 +33,7 @@
|
||||
state: construct0
|
||||
- type: TimedDespawn
|
||||
lifetime: 1.2
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: EffectRCDBase
|
||||
id: EffectRCDConstruct1
|
||||
@@ -43,7 +43,7 @@
|
||||
state: construct1
|
||||
- type: TimedDespawn
|
||||
lifetime: 2.2
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: EffectRCDBase
|
||||
id: EffectRCDConstruct2
|
||||
@@ -53,7 +53,7 @@
|
||||
state: construct2
|
||||
- type: TimedDespawn
|
||||
lifetime: 3.2
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: EffectRCDBase
|
||||
id: EffectRCDConstruct3
|
||||
@@ -63,7 +63,7 @@
|
||||
state: construct3
|
||||
- type: TimedDespawn
|
||||
lifetime: 4.2
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: EffectRCDBase
|
||||
id: EffectRCDConstruct4
|
||||
@@ -83,7 +83,7 @@
|
||||
state: deconstruct2
|
||||
- type: TimedDespawn
|
||||
lifetime: 3.2
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: EffectRCDBase
|
||||
id: EffectRCDDeconstruct4
|
||||
@@ -112,4 +112,4 @@
|
||||
- type: Sprite
|
||||
state: deconstruct8
|
||||
- type: TimedDespawn
|
||||
lifetime: 9.2
|
||||
lifetime: 9.2
|
||||
|
||||
@@ -235,8 +235,6 @@
|
||||
type: SpellSelectorBUI
|
||||
- key: enum.CultEmpowerRemoveUiKey.Key
|
||||
type: SpellRemoverBUI
|
||||
- key: enum.BloodRitesUi.Key
|
||||
type: CultistFactoryBUI
|
||||
# WD-EDIT END
|
||||
- type: Puller
|
||||
- type: Butcherable
|
||||
|
||||
@@ -524,6 +524,14 @@
|
||||
- MailingUnit
|
||||
- ToiletEmpty
|
||||
|
||||
- type: entity # WD
|
||||
id: RapidPipeDispenserEmpty
|
||||
parent: RapidPipeDispenser
|
||||
suffix: Empty
|
||||
components:
|
||||
- type: LimitedCharges
|
||||
charges: 0
|
||||
|
||||
- type: entity
|
||||
id: RCDRecharging
|
||||
parent: RCD
|
||||
|
||||
@@ -766,6 +766,7 @@
|
||||
normalState: normal-unshaded
|
||||
ejectState: eject-unshaded
|
||||
denyState: deny-unshaded
|
||||
priceMultiplier: 0.0
|
||||
- type: Sprite
|
||||
sprite: Structures/Machines/VendingMachines/engivend.rsi
|
||||
layers:
|
||||
|
||||
@@ -394,7 +394,7 @@
|
||||
targetNode: half
|
||||
category: construction-category-utilities
|
||||
placementMode: SnapgridCenter
|
||||
canBuildInImpassable: false
|
||||
canBuildInImpassable: true
|
||||
icon:
|
||||
sprite: Structures/Piping/Atmospherics/pipe.rsi
|
||||
state: pipeHalf
|
||||
@@ -408,7 +408,7 @@
|
||||
targetNode: straight
|
||||
category: construction-category-utilities
|
||||
placementMode: SnapgridCenter
|
||||
canBuildInImpassable: false
|
||||
canBuildInImpassable: true
|
||||
icon:
|
||||
sprite: Structures/Piping/Atmospherics/pipe.rsi
|
||||
state: pipeStraight
|
||||
@@ -422,7 +422,7 @@
|
||||
targetNode: bend
|
||||
category: construction-category-utilities
|
||||
placementMode: SnapgridCenter
|
||||
canBuildInImpassable: false
|
||||
canBuildInImpassable: true
|
||||
icon:
|
||||
sprite: Structures/Piping/Atmospherics/pipe.rsi
|
||||
state: pipeBend
|
||||
@@ -436,7 +436,7 @@
|
||||
targetNode: tjunction
|
||||
category: construction-category-utilities
|
||||
placementMode: SnapgridCenter
|
||||
canBuildInImpassable: false
|
||||
canBuildInImpassable: true
|
||||
icon:
|
||||
sprite: Structures/Piping/Atmospherics/pipe.rsi
|
||||
state: pipeTJunction
|
||||
@@ -450,7 +450,7 @@
|
||||
targetNode: fourway
|
||||
category: construction-category-utilities
|
||||
placementMode: SnapgridCenter
|
||||
canBuildInImpassable: false
|
||||
canBuildInImpassable: true
|
||||
icon:
|
||||
sprite: Structures/Piping/Atmospherics/pipe.rsi
|
||||
state: pipeFourway
|
||||
|
||||
@@ -123,7 +123,6 @@
|
||||
sprite: /Textures/White/Cult/actions_cult.rsi
|
||||
state: blood_rites
|
||||
event: !type:CultBloodRitesInstantActionEvent
|
||||
speech: "Fel'th Dol Ab'orod!"
|
||||
charges: 5
|
||||
temporary: true
|
||||
removeOnNoCharges: true
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
- type: entity
|
||||
id: CultTileSpawnEffect
|
||||
name: Sparkle
|
||||
id: CultTileEffect
|
||||
name: cult tile effect
|
||||
placement:
|
||||
mode: SnapgridCenter
|
||||
components:
|
||||
# Animation is like 3 something seconds so we just need to despawn it before then.
|
||||
- type: TimedDespawn
|
||||
lifetime: 0.5
|
||||
- type: EvaporationSparkle
|
||||
- type: Transform
|
||||
noRot: true
|
||||
anchored: true
|
||||
@@ -19,6 +17,14 @@
|
||||
netsync: false
|
||||
drawdepth: FloorObjects
|
||||
color: "#FF0000"
|
||||
|
||||
- type: entity
|
||||
parent: CultTileEffect
|
||||
id: CultTileSpawnEffect
|
||||
name: cult tile glow
|
||||
placement:
|
||||
mode: SnapgridCenter
|
||||
components:
|
||||
- type: PointLight
|
||||
color: "#FF0000"
|
||||
|
||||
@@ -26,10 +32,8 @@
|
||||
id: CultTeleportInEffect
|
||||
name: Teleport in
|
||||
components:
|
||||
# Animation is like 3 something seconds so we just need to despawn it before then.
|
||||
- type: TimedDespawn
|
||||
lifetime: 0.8
|
||||
- type: EvaporationSparkle
|
||||
- type: Transform
|
||||
noRot: true
|
||||
anchored: true
|
||||
@@ -47,10 +51,8 @@
|
||||
id: CultTeleportOutEffect
|
||||
name: Teleport out
|
||||
components:
|
||||
# Animation is like 3 something seconds so we just need to despawn it before then.
|
||||
- type: TimedDespawn
|
||||
lifetime: 0.8
|
||||
- type: EvaporationSparkle
|
||||
- type: Transform
|
||||
noRot: true
|
||||
anchored: true
|
||||
@@ -70,7 +72,6 @@
|
||||
components:
|
||||
- type: TimedDespawn
|
||||
lifetime: 1
|
||||
- type: EvaporationSparkle
|
||||
- type: Transform
|
||||
noRot: true
|
||||
anchored: true
|
||||
@@ -90,7 +91,6 @@
|
||||
components:
|
||||
- type: TimedDespawn
|
||||
lifetime: 1
|
||||
- type: EvaporationSparkle
|
||||
- type: Transform
|
||||
noRot: true
|
||||
anchored: true
|
||||
@@ -118,3 +118,13 @@
|
||||
duration: 0.5
|
||||
- type: TimedDespawn
|
||||
lifetime: 0.5
|
||||
|
||||
- type: entity
|
||||
parent: EffectRCDBase
|
||||
id: EffectConstructRed
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: Sprite
|
||||
state: construct_red
|
||||
- type: TimedDespawn
|
||||
lifetime: 5.2
|
||||
|
||||
74
Resources/Prototypes/_White/Entities/Cult/Items/hands.yml
Normal file
@@ -0,0 +1,74 @@
|
||||
- type: entity
|
||||
parent: BaseItem
|
||||
id: BaseCultHand
|
||||
abstract: true
|
||||
noSpawn: true
|
||||
name: magical aura
|
||||
description: A sinister looking aura that distorts the flow of reality around it.
|
||||
components:
|
||||
- type: Item
|
||||
size: Ginormous
|
||||
- type: MeleeWeapon
|
||||
canHeavyAttack: false
|
||||
canMiss: false
|
||||
attackRate: 2
|
||||
wideAnimationRotation: 180
|
||||
damage:
|
||||
types:
|
||||
Heat: 0
|
||||
- type: DeleteOnDropAttempt
|
||||
message: cult-hand-component-extra-message
|
||||
- type: Unremoveable
|
||||
deleteOnDrop: true
|
||||
- type: CultItem
|
||||
canPickUp: false
|
||||
|
||||
- type: entity
|
||||
parent: BaseCultHand
|
||||
id: StunHand
|
||||
name: stunning aura
|
||||
description: Will stun and mute a weak-minded victim on hit.
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: White/Cult/Entities/stun.rsi
|
||||
state: icon
|
||||
- type: Item
|
||||
sprite: White/Cult/Entities/stun.rsi
|
||||
- type: MeleeWeapon
|
||||
canAttackSelf: false
|
||||
attackWhitelist:
|
||||
components:
|
||||
- StatusEffects
|
||||
attackBlacklist:
|
||||
components:
|
||||
- Cultist
|
||||
- Construct
|
||||
- type: CultStunHand
|
||||
speech: "Fuu ma'jin!"
|
||||
|
||||
- type: entity
|
||||
parent: BaseCultHand
|
||||
id: RitesHand
|
||||
name: blood rite aura
|
||||
description: Absorbs blood from anything you touch. Touching cultists and constructs can heal them. Use in-hand to cast an advanced rite.
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: White/Cult/Entities/rites.rsi
|
||||
state: icon
|
||||
- type: Item
|
||||
sprite: White/Cult/Entities/rites.rsi
|
||||
- type: MeleeWeapon
|
||||
attackWhitelist:
|
||||
components:
|
||||
- Cultist
|
||||
- Construct
|
||||
- type: CultRitesHand
|
||||
speech: "Fel'th Dol Ab'orod!"
|
||||
- type: ActivatableUI
|
||||
key: enum.BloodRitesUi.Key
|
||||
inHandsOnly: true
|
||||
closeOnHandDeselect: true
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.BloodRitesUi.Key
|
||||
type: CultistFactoryBUI
|
||||
@@ -1,34 +0,0 @@
|
||||
- type: entity
|
||||
parent: BaseItem
|
||||
id: StunHand
|
||||
name: stunning aura
|
||||
description: Will stun and mute a weak-minded victim on hit.
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: White/Cult/Entities/stun.rsi
|
||||
state: icon
|
||||
- type: Item
|
||||
size: Ginormous
|
||||
sprite: White/Cult/Entities/stun.rsi
|
||||
- type: MeleeWeapon
|
||||
canHeavyAttack: false
|
||||
canAttackSelf: false
|
||||
canMiss: false
|
||||
attackWhitelist:
|
||||
components:
|
||||
- StatusEffects
|
||||
attackBlacklist:
|
||||
components:
|
||||
- Cultist
|
||||
- Construct
|
||||
wideAnimationRotation: 180
|
||||
damage:
|
||||
types:
|
||||
Heat: 0
|
||||
- type: CultStunHand
|
||||
- type: DeleteOnDropAttempt
|
||||
message: cult-stun-component-extra-message
|
||||
- type: Unremoveable
|
||||
deleteOnDrop: true
|
||||
- type: CultItem
|
||||
canPickUp: false
|
||||
@@ -30,6 +30,7 @@
|
||||
- type: Appearance
|
||||
- type: CultRuneBase
|
||||
invokePhrase: "Qu'laris ver'don, thal'sorin mik'thar!"
|
||||
gatherInvokers: false
|
||||
- type: CultRuneBuff
|
||||
- type: CultRune
|
||||
- type: Concealable
|
||||
@@ -47,6 +48,8 @@
|
||||
color: '#F80000'
|
||||
- type: Appearance
|
||||
- type: CultRuneBase
|
||||
invokePhrase: "H'drak v'loso, mir'kanas verbot!"
|
||||
gatherInvokers: false
|
||||
- type: CultEmpower
|
||||
isRune: true
|
||||
- type: UserInterface
|
||||
@@ -55,7 +58,6 @@
|
||||
type: SpellSelectorBUI
|
||||
- type: CultRune
|
||||
- type: Concealable
|
||||
examinableWhileConcealed: true
|
||||
|
||||
- type: entity
|
||||
parent: CollideRune
|
||||
@@ -91,7 +93,6 @@
|
||||
- type: Appearance
|
||||
- type: CultRuneBase
|
||||
invokePhrase: "N'ath reth sh'yro eth d'rekkathnor!"
|
||||
gatherInvokers: true
|
||||
- type: CultRuneSummoning
|
||||
- type: CultRune
|
||||
- type: Concealable
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
context: "human"
|
||||
- type: InputMover
|
||||
- type: MovementSpeedModifier
|
||||
baseWalkSpeed: 2.5
|
||||
baseSprintSpeed: 2.5
|
||||
baseWalkSpeed: 3
|
||||
baseSprintSpeed: 3
|
||||
- type: DamageOnHighSpeedImpact
|
||||
damage:
|
||||
types:
|
||||
@@ -61,6 +61,8 @@
|
||||
- type: ContentEye
|
||||
- type: Actions
|
||||
- type: Hands
|
||||
- type: Puller
|
||||
needsHands: false
|
||||
- type: ShowCultHud
|
||||
- type: IsDeadIC
|
||||
- type: NightVision
|
||||
@@ -138,8 +140,6 @@
|
||||
baseWalkSpeed: 3
|
||||
baseSprintSpeed: 3
|
||||
- type: MovementIgnoreGravity
|
||||
- type: Puller
|
||||
needsHands: false
|
||||
- type: MeleeWeapon
|
||||
canHeavyAttack: false
|
||||
hidden: true
|
||||
@@ -202,8 +202,6 @@
|
||||
150: Dead
|
||||
- type: Sprite
|
||||
state: harvester
|
||||
- type: Puller
|
||||
needsHands: false
|
||||
- type: MeleeWeapon
|
||||
canHeavyAttack: false
|
||||
hidden: true
|
||||
|
||||
@@ -143,6 +143,9 @@
|
||||
min: 0.74
|
||||
max: 0.85
|
||||
starting: 0.8
|
||||
- type: Carriable
|
||||
doAfterLength: 2
|
||||
- type: PseudoItem
|
||||
|
||||
- type: entity
|
||||
save: false
|
||||
|
||||
@@ -45,8 +45,6 @@
|
||||
type: SpellSelectorBUI
|
||||
- key: enum.CultEmpowerRemoveUiKey.Key
|
||||
type: SpellRemoverBUI
|
||||
- key: enum.BloodRitesUi.Key
|
||||
type: CultistFactoryBUI
|
||||
# WD-EDIT END
|
||||
- type: Sprite
|
||||
scale: 0.9, 0.9
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
prototype: GasPipeStraight
|
||||
cost: 1
|
||||
delay: 0
|
||||
collisionMask: InteractImpassable
|
||||
collisionMask: None
|
||||
rules:
|
||||
- MustBuildOnSubfloor
|
||||
rotation: User
|
||||
@@ -26,7 +26,7 @@
|
||||
prototype: GasPipeBend
|
||||
cost: 1
|
||||
delay: 0
|
||||
collisionMask: InteractImpassable
|
||||
collisionMask: None
|
||||
rules:
|
||||
- MustBuildOnSubfloor
|
||||
rotation: User
|
||||
@@ -42,7 +42,7 @@
|
||||
prototype: GasPipeTJunction
|
||||
cost: 1
|
||||
delay: 0
|
||||
collisionMask: InteractImpassable
|
||||
collisionMask: None
|
||||
rules:
|
||||
- MustBuildOnSubfloor
|
||||
rotation: User
|
||||
@@ -58,7 +58,7 @@
|
||||
prototype: GasPipeFourway
|
||||
cost: 1
|
||||
delay: 0
|
||||
collisionMask: InteractImpassable
|
||||
collisionMask: None
|
||||
rules:
|
||||
- MustBuildOnSubfloor
|
||||
rotation: User
|
||||
@@ -270,7 +270,7 @@
|
||||
prototype: DisposalPipe
|
||||
cost: 1
|
||||
delay: 0
|
||||
collisionMask: InteractImpassable
|
||||
collisionMask: None
|
||||
rules:
|
||||
- MustBuildOnSubfloor
|
||||
rotation: User
|
||||
@@ -286,7 +286,7 @@
|
||||
prototype: DisposalBend
|
||||
cost: 1
|
||||
delay: 0
|
||||
collisionMask: InteractImpassable
|
||||
collisionMask: None
|
||||
rules:
|
||||
- MustBuildOnSubfloor
|
||||
rotation: User
|
||||
@@ -302,7 +302,7 @@
|
||||
prototype: DisposalJunction
|
||||
cost: 1
|
||||
delay: 0
|
||||
collisionMask: InteractImpassable
|
||||
collisionMask: None
|
||||
rules:
|
||||
- MustBuildOnSubfloor
|
||||
rotation: User
|
||||
@@ -318,7 +318,7 @@
|
||||
prototype: DisposalJunctionFlipped
|
||||
cost: 1
|
||||
delay: 0
|
||||
collisionMask: InteractImpassable
|
||||
collisionMask: None
|
||||
rules:
|
||||
- MustBuildOnSubfloor
|
||||
rotation: User
|
||||
@@ -334,7 +334,7 @@
|
||||
prototype: DisposalYJunction
|
||||
cost: 1
|
||||
delay: 0
|
||||
collisionMask: InteractImpassable
|
||||
collisionMask: None
|
||||
rules:
|
||||
- MustBuildOnSubfloor
|
||||
rotation: User
|
||||
@@ -350,7 +350,7 @@
|
||||
prototype: DisposalRouter
|
||||
cost: 1
|
||||
delay: 0
|
||||
collisionMask: InteractImpassable
|
||||
collisionMask: None
|
||||
rules:
|
||||
- MustBuildOnSubfloor
|
||||
rotation: User
|
||||
@@ -366,7 +366,7 @@
|
||||
prototype: DisposalRouterFlipped
|
||||
cost: 1
|
||||
delay: 0
|
||||
collisionMask: InteractImpassable
|
||||
collisionMask: None
|
||||
rules:
|
||||
- MustBuildOnSubfloor
|
||||
rotation: User
|
||||
@@ -382,7 +382,7 @@
|
||||
prototype: DisposalTagger
|
||||
cost: 1
|
||||
delay: 0
|
||||
collisionMask: InteractImpassable
|
||||
collisionMask: None
|
||||
rules:
|
||||
- MustBuildOnSubfloor
|
||||
rotation: User
|
||||
@@ -398,7 +398,7 @@
|
||||
prototype: DisposalSignalRouter
|
||||
cost: 1
|
||||
delay: 0
|
||||
collisionMask: InteractImpassable
|
||||
collisionMask: None
|
||||
rules:
|
||||
- MustBuildOnSubfloor
|
||||
rotation: User
|
||||
@@ -414,7 +414,7 @@
|
||||
prototype: DisposalSignalRouterFlipped
|
||||
cost: 1
|
||||
delay: 0
|
||||
collisionMask: InteractImpassable
|
||||
collisionMask: None
|
||||
rules:
|
||||
- MustBuildOnSubfloor
|
||||
rotation: User
|
||||
@@ -430,7 +430,7 @@
|
||||
prototype: DisposalTrunk
|
||||
cost: 1
|
||||
delay: 0
|
||||
collisionMask: InteractImpassable
|
||||
collisionMask: None
|
||||
rules:
|
||||
- MustBuildOnSubfloor
|
||||
rotation: User
|
||||
@@ -447,10 +447,10 @@
|
||||
mode: ConstructObject
|
||||
prototype: DisposalUnit
|
||||
cost: 2
|
||||
delay: 1
|
||||
delay: 2
|
||||
collisionMask: InteractImpassable
|
||||
rotation: User
|
||||
fx: EffectRCDConstruct1
|
||||
fx: EffectRCDConstruct2
|
||||
|
||||
- type: rcd
|
||||
id: MailingUnit
|
||||
@@ -461,10 +461,10 @@
|
||||
mode: ConstructObject
|
||||
prototype: MailingUnit
|
||||
cost: 2
|
||||
delay: 1
|
||||
delay: 2
|
||||
collisionMask: InteractImpassable
|
||||
rotation: User
|
||||
fx: EffectRCDConstruct1
|
||||
fx: EffectRCDConstruct2
|
||||
|
||||
- type: rcd
|
||||
id: ToiletEmpty
|
||||
@@ -475,8 +475,8 @@
|
||||
mode: ConstructObject
|
||||
prototype: ToiletEmpty
|
||||
cost: 2
|
||||
delay: 1
|
||||
delay: 2
|
||||
collisionMask: InteractImpassable
|
||||
rotation: User
|
||||
fx: EffectRCDConstruct1
|
||||
fx: EffectRCDConstruct2
|
||||
|
||||
|
||||
@@ -170,16 +170,16 @@
|
||||
|
||||
- type: latheRecipe
|
||||
id: RapidPipeDispenserRecipe
|
||||
result: RapidPipeDispenser
|
||||
result: RapidPipeDispenserEmpty
|
||||
completetime: 1
|
||||
materials:
|
||||
Steel: 300
|
||||
Glass: 300
|
||||
Steel: 500
|
||||
Glass: 500
|
||||
|
||||
- type: latheRecipe
|
||||
id: RCDRecipe
|
||||
result: RCD
|
||||
result: RCDEmpty
|
||||
completetime: 1
|
||||
materials:
|
||||
Steel: 300
|
||||
Glass: 300
|
||||
Steel: 500
|
||||
Glass: 500
|
||||
|
||||
BIN
Resources/Textures/Effects/rcd.rsi/construct_red.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
@@ -25,7 +25,7 @@
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "construct1",
|
||||
"delays": [
|
||||
@@ -64,7 +64,7 @@
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "construct2",
|
||||
"delays": [
|
||||
@@ -201,7 +201,66 @@
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "construct_red",
|
||||
"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,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
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": "deconstruct2",
|
||||
"delays": [
|
||||
@@ -358,7 +417,7 @@
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "deconstruct8",
|
||||
"delays": [
|
||||
@@ -451,7 +510,7 @@
|
||||
0.05,
|
||||
0.05,
|
||||
0.05,
|
||||
0.05
|
||||
0.05
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
BIN
Resources/Textures/White/Cult/Entities/rites.rsi/icon.png
Normal file
|
After Width: | Height: | Size: 665 B |
BIN
Resources/Textures/White/Cult/Entities/rites.rsi/inhand-left.png
Normal file
|
After Width: | Height: | Size: 543 B |
|
After Width: | Height: | Size: 554 B |
66
Resources/Textures/White/Cult/Entities/rites.rsi/meta.json
Normal file
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/pull/49264/commits/d0dffe7ca643db2624424fdcebf45863f85c0448",
|
||||
"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
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 845 B After Width: | Height: | Size: 508 B |
|
Before Width: | Height: | Size: 843 B After Width: | Height: | Size: 504 B |