--- /dev/null
+
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Magic.Components;
+
+// Added to objects when they are made animate
+[RegisterComponent, NetworkedComponent]
+public sealed partial class AnimateComponent : Component;
+++ /dev/null
-using Content.Shared.Actions;
-using Robust.Shared.Prototypes;
-
-namespace Content.Shared.Magic.Events;
-
-public sealed partial class AnimateSpellEvent : EntityTargetActionEvent, ISpeakSpell
-{
- [DataField]
- public string? Speech { get; private set; }
-
- [DataField]
- public ComponentRegistry AddComponents = new();
-
- [DataField]
- public HashSet<string> RemoveComponents = new();
-}
-using Content.Shared.Actions;
+using Content.Shared.Actions;
using Robust.Shared.Prototypes;
namespace Content.Shared.Magic.Events;
// TODO allow it to set component data-fields?
// for now a Hackish way to do that is to remove & add, but that doesn't allow you to selectively set specific data fields.
- [DataField("toAdd")]
+ [DataField]
[AlwaysPushInheritance]
public ComponentRegistry ToAdd = new();
- [DataField("toRemove")]
+ [DataField]
[AlwaysPushInheritance]
public HashSet<string> ToRemove = new();
- [DataField("speech")]
+ [DataField]
public string? Speech { get; private set; }
+
+ [DataField]
+ public bool DoSpeech { get; private set; }
}
-using System.Linq;
using System.Numerics;
using Content.Shared.Actions;
using Content.Shared.Body.Components;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Network;
-using Robust.Shared.Physics;
-using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Systems;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
SubscribeLocalEvent<RandomGlobalSpawnSpellEvent>(OnRandomGlobalSpawnSpell);
SubscribeLocalEvent<MindSwapSpellEvent>(OnMindSwapSpell);
SubscribeLocalEvent<VoidApplauseSpellEvent>(OnVoidApplause);
- SubscribeLocalEvent<AnimateSpellEvent>(OnAnimateSpell);
}
private void OnBeforeCastSpell(Entity<MagicComponent> ent, ref BeforeCastSpellEvent args)
return;
ev.Handled = true;
- Speak(ev);
+ if (ev.DoSpeech)
+ Speak(ev);
RemoveComponents(ev.Target, ev.ToRemove);
AddComponents(ev.Target, ev.ToAdd);
_stun.TryParalyze(ev.Performer, ev.PerformerStunDuration, true);
}
- #endregion
- #region Animation Spells
-
- private void OnAnimateSpell(AnimateSpellEvent ev)
- {
- if (ev.Handled || !PassesSpellPrerequisites(ev.Action, ev.Performer) || !TryComp<FixturesComponent>(ev.Target, out var fixtures) ||
- !TryComp<PhysicsComponent>(ev.Target, out var physics))
- return;
-
- ev.Handled = true;
- //Speak(ev);
-
- RemoveComponents(ev.Target, ev.RemoveComponents);
- AddComponents(ev.Target, ev.AddComponents);
-
- var xform = Transform(ev.Target);
- var fixture = fixtures.Fixtures.First();
-
- _transform.Unanchor(ev.Target);
- _physics.SetCanCollide(ev.Target, true, true, false, fixtures, physics);
- _physics.SetCollisionMask(ev.Target, fixture.Key, fixture.Value, (int)CollisionGroup.FlyingMobMask, fixtures, physics);
- _physics.SetCollisionLayer(ev.Target, fixture.Key, fixture.Value, (int)CollisionGroup.FlyingMobLayer, fixtures, physics);
- _physics.SetBodyType(ev.Target, BodyType.KinematicController, fixtures, physics, xform);
- _physics.SetBodyStatus(ev.Target, physics, BodyStatus.InAir, true);
- _physics.SetFixedRotation(ev.Target, false, true, fixtures, physics);
- }
-
#endregion
// End Spells
#endregion
--- /dev/null
+using Content.Shared.Magic.Components;
+using Content.Shared.Physics;
+using Robust.Shared.Containers;
+using Robust.Shared.Physics;
+using Robust.Shared.Physics.Components;
+using Robust.Shared.Physics.Systems;
+using System.Linq;
+
+namespace Content.Shared.Magic.Systems;
+
+public sealed class AnimateSpellSystem : EntitySystem
+{
+ [Dependency] private readonly SharedPhysicsSystem _physics = default!;
+ [Dependency] private readonly SharedTransformSystem _transform = default!;
+ [Dependency] private readonly SharedContainerSystem _container = default!;
+
+ public override void Initialize()
+ {
+ SubscribeLocalEvent<AnimateComponent, MapInitEvent>(OnAnimate);
+ }
+
+ private void OnAnimate(Entity<AnimateComponent> ent, ref MapInitEvent args)
+ {
+ // Physics bullshittery necessary for object to behave properly
+
+ if (!TryComp<FixturesComponent>(ent, out var fixtures) || !TryComp<PhysicsComponent>(ent, out var physics))
+ return;
+
+ var xform = Transform(ent);
+ var fixture = fixtures.Fixtures.First();
+
+ _transform.Unanchor(ent); // If left anchored they are effectively stuck/immobile and not a threat
+ _physics.SetCanCollide(ent, true, true, false, fixtures, physics);
+ _physics.SetCollisionMask(ent, fixture.Key, fixture.Value, (int)CollisionGroup.FlyingMobMask, fixtures, physics);
+ _physics.SetCollisionLayer(ent, fixture.Key, fixture.Value, (int)CollisionGroup.FlyingMobLayer, fixtures, physics);
+ _physics.SetBodyType(ent, BodyType.KinematicController, fixtures, physics, xform);
+ _physics.SetBodyStatus(ent, physics, BodyStatus.InAir, true);
+ _physics.SetFixedRotation(ent, false, true, fixtures, physics);
+ _physics.SetHard(ent, fixture.Value, true, fixtures);
+ _container.AttachParentToContainerOrGrid((ent, xform)); // Items animated inside inventory now exit, they can't be picked up and so can't escape otherwise
+
+ var ev = new AnimateSpellEvent();
+ RaiseLocalEvent(ref ev);
+ }
+}
+
+[ByRefEvent]
+public readonly record struct AnimateSpellEvent;
itemIconStyle: BigAction
whitelist:
components:
- - Animateable # Currently on: SeatBase, TableBase, ClosetBase, BaseMachine, ConstructibleMachine, BaseComputer, BaseItem, CrateGeneric, StorageTank, GasCanister
+ - Animateable # Currently on: SeatBase, TableBase, ClosetBase, BaseMachine, ConstructibleMachine, BaseComputer, BaseItem, CrateGeneric, StorageTank, GasCanister, BaseTarget
blacklist:
components:
- MindContainer
- NukeDisk
- GravityGenerator
- AnomalyGenerator
+ - TegGenerator
+ - TegCirculator
+ - Artifact
canTargetSelf: false
interactOnMiss: false
sound: !type:SoundPathSpecifier
icon:
sprite: Objects/Magic/magicactions.rsi
state: spell_default
- event: !type:AnimateSpellEvent
- addComponents:
+ event: !type:ChangeComponentsSpellEvent
+ toAdd:
+ - type: Animate
- type: MindContainer
- type: InputMover
- type: MobMover
collection: MetalBreak
- type: Hands
- type: CanEscapeInventory
- removeComponents:
+ toRemove:
- RequireProjectileTarget
+ - BlockMovement
+ - Item
speech: action-speech-spell-animate
+ doSpeech: false
orGroup: Magics
- id: BlinkBook
orGroup: Magics
- - id: SmiteBook
- orGroup: Magics
- id: KnockSpellbook
orGroup: Magics
- id: FireballSpellbook
orGroup: Magics
- id: WeaponStaffPolymorphDoor
orGroup: Magics
+ - id: AnimationStaff
+ orGroup: Magics
+ - id: RGBStaff
+ orGroup: Magics
speech: action-speech-spell-summon-magic
hostile:
- PetsNT
- AllHostile
+ - Wizard
- type: npcFaction
id: Passive
- Zombie
- Xeno
- AllHostile
+ - Wizard
- type: npcFaction
id: SimpleHostile
hostile:
- NanoTrasen
- Dragon
+ - Mouse
+ - Passive
+ - PetsNT
- SimpleHostile
+ - SimpleNeutral
- Syndicate
- Xeno
- Zombie