Spells stuff (#153)
* -add: Create and remove blood spells using verbs. * - add: Blood spells now have charges and disappear. * - add: Localize spells. * - add: New blood spells.
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
using System.Linq;
|
||||
using Content.Client._White.UserInterface.Radial;
|
||||
using Content.Shared._White.Cult;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared._White.Cult.Components;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.Utility;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
using CultistComponent = Content.Shared._White.Cult.Components.CultistComponent;
|
||||
|
||||
namespace Content.Client._White.Cult.UI.SpellRemover;
|
||||
|
||||
public sealed class SpellRemoverBUI : BoundUserInterface
|
||||
{
|
||||
private RadialContainer? _radialContainer;
|
||||
|
||||
public SpellRemoverBUI(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
_radialContainer = new RadialContainer();
|
||||
_radialContainer.Closed += Close;
|
||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||
var ent = IoCManager.Resolve<IPlayerManager>().LocalEntity;
|
||||
|
||||
if (ent == null || !entityManager.TryGetComponent(ent, out CultistComponent? comp) ||
|
||||
comp.SelectedEmpowers.Count == 0)
|
||||
{
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
var metaQuery = entityManager.GetEntityQuery<MetaDataComponent>();
|
||||
var instantQuery = entityManager.GetEntityQuery<InstantActionComponent>();
|
||||
var targetQuery = entityManager.GetEntityQuery<EntityTargetActionComponent>();
|
||||
|
||||
foreach (var action in comp.SelectedEmpowers)
|
||||
{
|
||||
if (action == null)
|
||||
continue;
|
||||
|
||||
var spell = entityManager.GetEntity(action.Value);
|
||||
|
||||
if (!entityManager.EntityExists(spell))
|
||||
continue;
|
||||
|
||||
SpriteSpecifier? icon;
|
||||
if (instantQuery.TryGetComponent(spell, out var instantComp))
|
||||
icon = instantComp.Icon;
|
||||
else
|
||||
{
|
||||
if (!targetQuery.TryGetComponent(spell, out var targetComp))
|
||||
continue;
|
||||
icon = targetComp.Icon;
|
||||
}
|
||||
|
||||
if (icon == null)
|
||||
continue;
|
||||
|
||||
var texture = icon.Frame0();
|
||||
|
||||
if (!metaQuery.TryGetComponent(spell, out var meta))
|
||||
continue;
|
||||
|
||||
var button = _radialContainer.AddButton(meta.EntityName, texture);
|
||||
|
||||
button.Controller.OnPressed += _ =>
|
||||
{
|
||||
SendMessage(new CultEmpowerRemoveBuiMessage(action.Value));
|
||||
Close();
|
||||
};
|
||||
}
|
||||
|
||||
_radialContainer.OpenAttachedLocalPlayer();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
_radialContainer?.Close();
|
||||
}
|
||||
}
|
||||
@@ -179,7 +179,7 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
|
||||
|
||||
foreach (var empower in component.SelectedEmpowers)
|
||||
{
|
||||
_actions.RemoveAction(uid, empower);
|
||||
_actions.RemoveAction(uid, GetEntity(empower));
|
||||
}
|
||||
|
||||
RemoveCultistAppearance(uid);
|
||||
|
||||
@@ -4,6 +4,7 @@ using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.Emp;
|
||||
using Content.Server.EUI;
|
||||
using Content.Server._White.Cult.UI;
|
||||
using Content.Shared._White.Chaplain;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
@@ -15,8 +16,11 @@ using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Stacks;
|
||||
using Content.Shared.StatusEffect;
|
||||
using Content.Shared.Stunnable;
|
||||
using Content.Shared._White.Cult;
|
||||
using Content.Shared._White.Cult.Actions;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Cuffs.Components;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Mindshield.Components;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Player;
|
||||
@@ -38,38 +42,71 @@ public partial class CultSystem
|
||||
SubscribeLocalEvent<CultistComponent, CultTwistedConstructionActionEvent>(OnTwistedConstructionAction);
|
||||
SubscribeLocalEvent<CultistComponent, CultSummonDaggerActionEvent>(OnSummonDaggerAction);
|
||||
SubscribeLocalEvent<CultistComponent, CultShadowShacklesTargetActionEvent>(OnShadowShackles);
|
||||
SubscribeLocalEvent<CultistComponent, CultElectromagneticPulseTargetActionEvent>(OnElectromagneticPulse);
|
||||
SubscribeLocalEvent<CultistComponent, CultElectromagneticPulseInstantActionEvent>(OnElectromagneticPulse);
|
||||
SubscribeLocalEvent<CultistComponent, CultSummonCombatEquipmentTargetActionEvent>(OnSummonCombatEquipment);
|
||||
SubscribeLocalEvent<CultistComponent, CultConcealPresenceWorldActionEvent>(OnConcealPresence);
|
||||
SubscribeLocalEvent<CultistComponent, CultBloodRitesInstantActionEvent>(OnBloodRites);
|
||||
SubscribeLocalEvent<CultistComponent, CultTeleportTargetActionEvent>(OnTeleport);
|
||||
SubscribeLocalEvent<CultistComponent, CultStunTargetActionEvent>(OnStunTarget);
|
||||
SubscribeLocalEvent<CultistComponent, ActionGettingRemovedEvent>(OnActionRemoved);
|
||||
SubscribeLocalEvent<CultistComponent, ShacklesEvent>(OnShackles);
|
||||
}
|
||||
|
||||
private void OnShackles(Entity<CultistComponent> ent, ref ShacklesEvent args)
|
||||
{
|
||||
if (args.Cancelled || args.Target == null)
|
||||
return;
|
||||
|
||||
if (!TryComp(args.Target, out CuffableComponent? cuffable) || cuffable.Container.ContainedEntities.Count > 0)
|
||||
return;
|
||||
|
||||
var cuffs = Spawn("ShadowShackles", Transform(ent).Coordinates);
|
||||
if (!_cuffable.TryAddNewCuffs(args.Target.Value, args.User, cuffs, cuffable))
|
||||
QueueDel(cuffs);
|
||||
}
|
||||
|
||||
private void OnActionRemoved(Entity<CultistComponent> ent, ref ActionGettingRemovedEvent args)
|
||||
{
|
||||
ent.Comp.SelectedEmpowers.Remove(GetNetEntity(args.Action));
|
||||
Dirty(ent);
|
||||
}
|
||||
|
||||
private void OnStunTarget(EntityUid uid, CultistComponent component, CultStunTargetActionEvent args)
|
||||
{
|
||||
if (args.Target == uid || !HasComp<StatusEffectsComponent>(args.Target))
|
||||
if (args.Target == uid || !TryComp<BloodstreamComponent>(args.Performer, out var bloodstream) ||
|
||||
HasComp<HolyComponent>(args.Target) || !TryComp<StatusEffectsComponent>(args.Target, out var status))
|
||||
return;
|
||||
|
||||
if (_stunSystem.TryStun(args.Target, TimeSpan.FromSeconds(6), true))
|
||||
if (HasComp<MindShieldComponent>(args.Target))
|
||||
{
|
||||
args.Handled = true;
|
||||
_popupSystem.PopupEntity("Он имплантирован чипом защиты разума.", args.Performer, args.Performer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_stunSystem.TryParalyze(args.Target, TimeSpan.FromSeconds(6), true, status) &
|
||||
!_statusEffectsSystem.TryAddStatusEffect(args.Target, "Muted", TimeSpan.FromSeconds(12), true, "Muted",
|
||||
status))
|
||||
return;
|
||||
|
||||
_bloodstreamSystem.TryModifyBloodLevel(uid, -10, bloodstream, createPuddle: false);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnTeleport(EntityUid uid, CultistComponent component, CultTeleportTargetActionEvent args)
|
||||
{
|
||||
if (!TryComp<BloodstreamComponent>(args.Performer, out _) || !TryComp<ActorComponent>(uid, out var actor))
|
||||
if (!TryComp<BloodstreamComponent>(args.Performer, out var bloodstream) || !TryComp<ActorComponent>(uid, out var actor))
|
||||
return;
|
||||
|
||||
if (!TryComp<CultistComponent>(args.Target, out _) &&
|
||||
!(TryComp<MobStateComponent>(args.Target, out var mobStateComponent) &&
|
||||
mobStateComponent.CurrentState is not MobState.Alive))
|
||||
{
|
||||
_popupSystem.PopupEntity("Цель должна быть культистом или лежать", args.Performer);
|
||||
_popupSystem.PopupEntity("Цель должна быть культистом или лежать.", args.Performer, args.Performer);
|
||||
return;
|
||||
}
|
||||
|
||||
_bloodstreamSystem.TryModifyBloodLevel(uid, -5, bloodstream, createPuddle: false);
|
||||
|
||||
var eui = new TeleportSpellEui(args.Performer, args.Target);
|
||||
_euiManager.OpenEui(eui, actor.PlayerSession);
|
||||
eui.StateDirty();
|
||||
@@ -148,10 +185,10 @@ public partial class CultSystem
|
||||
CultistComponent component,
|
||||
CultSummonCombatEquipmentTargetActionEvent args)
|
||||
{
|
||||
if (!TryComp<BloodstreamComponent>(args.Performer, out _))
|
||||
if (!TryComp<BloodstreamComponent>(args.Performer, out var bloodstream))
|
||||
return;
|
||||
|
||||
_bloodstreamSystem.TryModifyBloodLevel(uid, -20, createPuddle: false);
|
||||
_bloodstreamSystem.TryModifyBloodLevel(uid, -20, bloodstream, createPuddle: false);
|
||||
|
||||
var coordinates = Transform(uid).Coordinates;
|
||||
var helmet = Spawn("ClothingHeadHelmetCult", coordinates);
|
||||
@@ -177,30 +214,42 @@ public partial class CultSystem
|
||||
private void OnElectromagneticPulse(
|
||||
EntityUid uid,
|
||||
CultistComponent component,
|
||||
CultElectromagneticPulseTargetActionEvent args)
|
||||
CultElectromagneticPulseInstantActionEvent args)
|
||||
{
|
||||
if (!TryComp<BloodstreamComponent>(args.Performer, out _))
|
||||
if (!TryComp<BloodstreamComponent>(args.Performer, out var bloodstream))
|
||||
return;
|
||||
|
||||
_bloodstreamSystem.TryModifyBloodLevel(uid, -20, createPuddle: false);
|
||||
_bloodstreamSystem.TryModifyBloodLevel(uid, -10, bloodstream, createPuddle: false);
|
||||
|
||||
var xform = Transform(uid);
|
||||
|
||||
_empSystem.EmpPulse(xform.MapPosition, 10, 100000, 10f);
|
||||
_bloodstreamSystem.TryModifyBloodLevel(uid, -20, createPuddle: false);
|
||||
_empSystem.EmpPulse(_transform.GetMapCoordinates(uid), 5, 100000, 10f);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnShadowShackles(EntityUid uid, CultistComponent component, CultShadowShacklesTargetActionEvent args)
|
||||
{
|
||||
if (!TryComp<BloodstreamComponent>(args.Performer, out _))
|
||||
if (args.Target == uid || !TryComp<BloodstreamComponent>(args.Performer, out var bloodstream))
|
||||
return;
|
||||
|
||||
_bloodstreamSystem.TryModifyBloodLevel(uid, -20, createPuddle: false);
|
||||
_bloodstreamSystem.TryModifyBloodLevel(uid, -5, bloodstream, createPuddle: false);
|
||||
|
||||
var cuffs = Spawn("CultistCuffs", Transform(uid).Coordinates);
|
||||
_handsSystem.TryPickupAnyHand(uid, cuffs);
|
||||
if (!HasComp<HolyComponent>(args.Target) &&
|
||||
_statusEffectsSystem.TryAddStatusEffect(args.Target, "Muted", TimeSpan.FromSeconds(10), true, "Muted"))
|
||||
{
|
||||
_popupSystem.PopupEntity("Цель обезмолвлена.", args.Performer, args.Performer);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
BreakOnTargetMove = true,
|
||||
BreakOnUserMove = true,
|
||||
BreakOnDamage = true
|
||||
});
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
@@ -229,14 +278,14 @@ public partial class CultSystem
|
||||
|
||||
var material = _entityManager.SpawnEntity(RunicMetalPrototypeId, transform);
|
||||
|
||||
_bloodstreamSystem.TryModifyBloodLevel(args.Performer, -15, bloodstreamComponent, false);
|
||||
_bloodstreamSystem.TryModifyBloodLevel(args.Performer, -stack.Count / 2f, bloodstreamComponent, false);
|
||||
|
||||
if (!_entityManager.TryGetComponent<StackComponent>(material, out var stackNew))
|
||||
return;
|
||||
|
||||
stackNew.Count = count;
|
||||
|
||||
_popupSystem.PopupEntity(Loc.GetString("Конвертируем сталь в руиник металл!"), args.Performer, args.Performer);
|
||||
_popupSystem.PopupEntity("Конвертируем сталь в руинический металл!", args.Performer, args.Performer);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
@@ -251,7 +300,7 @@ public partial class CultSystem
|
||||
var xform = Transform(args.Performer).Coordinates;
|
||||
var dagger = _entityManager.SpawnEntity(RitualDaggerPrototypeId, xform);
|
||||
|
||||
_bloodstreamSystem.TryModifyBloodLevel(args.Performer, -30, bloodstreamComponent, false);
|
||||
_bloodstreamSystem.TryModifyBloodLevel(args.Performer, -20, bloodstreamComponent, false);
|
||||
_handsSystem.TryPickupAnyHand(args.Performer, dagger);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ using Content.Server.Weapons.Ranged.Systems;
|
||||
using Content.Server._White.Cult.GameRule;
|
||||
using Content.Server._White.Cult.Runes.Comps;
|
||||
using Content.Shared._White.Chaplain;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Cuffs.Components;
|
||||
using Content.Shared.Damage;
|
||||
@@ -28,16 +27,15 @@ using Content.Shared.Popups;
|
||||
using Content.Shared.Projectiles;
|
||||
using Content.Shared.Pulling.Components;
|
||||
using Content.Shared.Rejuvenate;
|
||||
using Content.Shared.Roles.Jobs;
|
||||
using Content.Shared._White.Cult;
|
||||
using Content.Shared._White.Cult.Components;
|
||||
using Content.Shared._White.Cult.Runes;
|
||||
using Content.Shared._White.Cult.UI;
|
||||
using Content.Shared.Cuffs;
|
||||
using Content.Shared.Mindshield.Components;
|
||||
using Content.Shared.Pulling;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Components;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Physics.Events;
|
||||
@@ -65,6 +63,7 @@ public sealed partial class CultSystem : EntitySystem
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly FlammableSystem _flammableSystem = default!;
|
||||
[Dependency] private readonly SharedPullingSystem _pulling = default!;
|
||||
[Dependency] private readonly SharedCuffableSystem _cuffable = default!;
|
||||
|
||||
|
||||
public override void Initialize()
|
||||
@@ -110,6 +109,7 @@ public sealed partial class CultSystem : EntitySystem
|
||||
InitializeBarrierSystem();
|
||||
InitializeConstructsAbilities();
|
||||
InitializeActions();
|
||||
InitializeVerb();
|
||||
}
|
||||
|
||||
private float _timeToDraw;
|
||||
@@ -518,6 +518,14 @@ public sealed partial class CultSystem : EntitySystem
|
||||
_stunSystem.TryStun(target, TimeSpan.FromSeconds(2f), false);
|
||||
HealCultist(target);
|
||||
|
||||
if (TryComp(target, out CuffableComponent? cuffs) && cuffs.Container.ContainedEntities.Count >= 1)
|
||||
{
|
||||
var lastAddedCuffs = cuffs.LastAddedCuffs;
|
||||
_cuffable.Uncuff(target, user, lastAddedCuffs);
|
||||
}
|
||||
|
||||
_statusEffectsSystem.TryRemoveStatusEffect(target, "Muted");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1143,17 +1151,19 @@ public sealed partial class CultSystem : EntitySystem
|
||||
|
||||
if (component.IsRune)
|
||||
{
|
||||
if (comp.SelectedEmpowers.Count > component.MaxAllowedCultistActions)
|
||||
if (comp.SelectedEmpowers.Count >= component.MaxAllowedCultistActions)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("cult-too-much-empowers"), uid);
|
||||
return;
|
||||
}
|
||||
|
||||
comp.SelectedEmpowers.Add(_actionsSystem.AddAction(playerEntity.Value, action));
|
||||
comp.SelectedEmpowers.Add(GetNetEntity(_actionsSystem.AddAction(playerEntity.Value, action)));
|
||||
Dirty(playerEntity.Value, comp);
|
||||
}
|
||||
else if (comp.SelectedEmpowers.Count < component.MinRequiredCultistActions)
|
||||
{
|
||||
comp.SelectedEmpowers.Add(_actionsSystem.AddAction(playerEntity.Value, action));
|
||||
comp.SelectedEmpowers.Add(GetNetEntity(_actionsSystem.AddAction(playerEntity.Value, action)));
|
||||
Dirty(playerEntity.Value, comp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
115
Content.Server/_White/Cult/Runes/Systems/CultSystem.Verb.cs
Normal file
115
Content.Server/_White/Cult/Runes/Systems/CultSystem.Verb.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Shared._White.Cult;
|
||||
using Content.Shared._White.Cult.Components;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server._White.Cult.Runes.Systems;
|
||||
|
||||
public sealed partial class CultSystem
|
||||
{
|
||||
public void InitializeVerb()
|
||||
{
|
||||
SubscribeLocalEvent<CultistComponent, GetVerbsEvent<Verb>>(OnGetVerbs);
|
||||
SubscribeLocalEvent<CultistComponent, CultEmpowerSelectedBuiMessage>(OnCultistEmpowerSelected);
|
||||
SubscribeLocalEvent<CultistComponent, CultEmpowerRemoveBuiMessage>(OnCultistEmpowerRemove);
|
||||
SubscribeLocalEvent<CultistComponent, SpellCreatedEvent>(OnSpellCreated);
|
||||
}
|
||||
|
||||
private void OnCultistEmpowerRemove(Entity<CultistComponent> ent, ref CultEmpowerRemoveBuiMessage args)
|
||||
{
|
||||
var entity = GetEntity(args.ActionType);
|
||||
ent.Comp.SelectedEmpowers.Remove(args.ActionType);
|
||||
_actionsSystem.RemoveAction(entity);
|
||||
Dirty(ent);
|
||||
}
|
||||
|
||||
private void OnSpellCreated(EntityUid ent, CultistComponent comp, SpellCreatedEvent args)
|
||||
{
|
||||
if (args.Cancelled || comp.SelectedEmpowers.Count >= 1)
|
||||
return;
|
||||
|
||||
var action = CultistComponent.CultistActions.FirstOrDefault(x => x.Equals(args.Spell));
|
||||
|
||||
if (action == null)
|
||||
return;
|
||||
|
||||
var howMuchBloodTake = HasComp<CultBuffComponent>(ent) ? -10f : -20f;
|
||||
|
||||
if (!TryComp<BloodstreamComponent>(ent, out var bloodstreamComponent))
|
||||
return;
|
||||
|
||||
_bloodstreamSystem.TryModifyBloodLevel(ent, howMuchBloodTake, bloodstreamComponent, createPuddle: false);
|
||||
|
||||
comp.SelectedEmpowers.Add(GetNetEntity(_actionsSystem.AddAction(ent, args.Spell)));
|
||||
|
||||
Dirty(ent, comp);
|
||||
}
|
||||
|
||||
private void OnCultistEmpowerSelected(EntityUid ent, CultistComponent comp, CultEmpowerSelectedBuiMessage args)
|
||||
{
|
||||
var action = CultistComponent.CultistActions.FirstOrDefault(x => x.Equals(args.ActionType));
|
||||
|
||||
if (action == null)
|
||||
return;
|
||||
|
||||
if (comp.SelectedEmpowers.Count >= 1)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("verb-spell-create-too-much"), ent);
|
||||
return;
|
||||
}
|
||||
|
||||
var creationTime = HasComp<CultBuffComponent>(ent) ? 2.5f : 5f;
|
||||
|
||||
_doAfterSystem.TryStartDoAfter(
|
||||
new DoAfterArgs(_entityManager, ent, creationTime, new SpellCreatedEvent {Spell = action}, ent)
|
||||
{
|
||||
BreakOnDamage = true,
|
||||
BreakOnUserMove = true
|
||||
});
|
||||
}
|
||||
|
||||
private void OnGetVerbs(Entity<CultistComponent> ent, ref GetVerbsEvent<Verb> args)
|
||||
{
|
||||
if (ent.Owner != args.User || !TryComp<ActorComponent>(args.User, out var actor))
|
||||
return;
|
||||
|
||||
var createSpellVerb = new Verb
|
||||
{
|
||||
Text = Loc.GetString("verb-spell-create-text"),
|
||||
Message = Loc.GetString("verb-spell-create-message"),
|
||||
Category = VerbCategory.Cult,
|
||||
Act = () =>
|
||||
{
|
||||
_ui.TryOpen(ent, CultEmpowerUiKey.Key, actor.PlayerSession);
|
||||
}
|
||||
};
|
||||
|
||||
var removeSpellVerb = new Verb
|
||||
{
|
||||
Text = Loc.GetString("verb-spell-remove-text"),
|
||||
Message = Loc.GetString("verb-spell-remove-message"),
|
||||
Category = VerbCategory.Cult,
|
||||
Act = () =>
|
||||
{
|
||||
RemoveSpell(ent, actor.PlayerSession);
|
||||
}
|
||||
};
|
||||
|
||||
args.Verbs.Add(createSpellVerb);
|
||||
args.Verbs.Add(removeSpellVerb);
|
||||
}
|
||||
|
||||
private void RemoveSpell(Entity<CultistComponent> ent, ICommonSession session)
|
||||
{
|
||||
if (ent.Comp.SelectedEmpowers.Count == 0)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("verb-spell-remove-no-spells"), ent);
|
||||
return;
|
||||
}
|
||||
|
||||
_ui.TryOpen(ent, CultEmpowerRemoveUiKey.Key, session);
|
||||
}
|
||||
}
|
||||
@@ -102,6 +102,13 @@ public sealed class RequestPerformActionEvent : EntityEventArgs
|
||||
}
|
||||
}
|
||||
|
||||
// WD START
|
||||
public sealed partial class ActionGettingRemovedEvent : EntityEventArgs
|
||||
{
|
||||
public EntityUid Action;
|
||||
}
|
||||
// WD END
|
||||
|
||||
/// <summary>
|
||||
/// This is the type of event that gets raised when an <see cref="InstantAction"/> is performed. The <see
|
||||
/// cref="Performer"/> field is automatically filled out by the <see cref="SharedActionsSystem"/>.
|
||||
|
||||
@@ -144,6 +144,11 @@ public abstract partial class BaseActionComponent : Component
|
||||
/// </summary>
|
||||
[DataField("autoPopulate")] public bool AutoPopulate = true;
|
||||
|
||||
// WD START
|
||||
[DataField]
|
||||
public bool RemoveOnNoCharges;
|
||||
// WD END
|
||||
|
||||
/// <summary>
|
||||
/// Temporary actions are deleted when they get removed a <see cref="ActionsComponent"/>.
|
||||
/// </summary>
|
||||
|
||||
@@ -15,6 +15,7 @@ using Robust.Shared.Map;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
using Content.Shared.Rejuvenate;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Shared.Actions;
|
||||
|
||||
@@ -29,6 +30,7 @@ public abstract class SharedActionsSystem : EntitySystem
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
|
||||
[Dependency] private readonly ActionContainerSystem _actionContainer = default!;
|
||||
[Dependency] private readonly INetManager _net = default!; // WD
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -537,6 +539,13 @@ public abstract class SharedActionsSystem : EntitySystem
|
||||
action.Charges--;
|
||||
if (action is { Charges: 0, RenewCharges: false })
|
||||
action.Enabled = false;
|
||||
// WD START
|
||||
if (action is {Charges: 0, RemoveOnNoCharges: true})
|
||||
{
|
||||
RaiseLocalEvent(performer, new ActionGettingRemovedEvent {Action = actionId});
|
||||
RemoveAction(performer, actionId, component, action);
|
||||
}
|
||||
// WD END
|
||||
}
|
||||
|
||||
action.Cooldown = null;
|
||||
@@ -816,7 +825,7 @@ public abstract class SharedActionsSystem : EntitySystem
|
||||
Dirty(actionId.Value, action);
|
||||
Dirty(performer, comp);
|
||||
ActionRemoved(performer, actionId.Value, comp, action);
|
||||
if (action.Temporary)
|
||||
if (action.Temporary && (!_net.IsClient || action.ClientExclusive)) // WD EDIT
|
||||
QueueDel(actionId.Value);
|
||||
}
|
||||
|
||||
|
||||
@@ -680,8 +680,13 @@ namespace Content.Shared.Cuffs
|
||||
if (cuff.BreakOnRemove)
|
||||
{
|
||||
QueueDel(cuffsToRemove);
|
||||
var trash = Spawn(cuff.BrokenPrototype, Transform(cuffsToRemove).Coordinates);
|
||||
_hands.PickupOrDrop(user, trash);
|
||||
// WD EDIT START
|
||||
if (cuff.BrokenPrototype != null)
|
||||
{
|
||||
var trash = Spawn(cuff.BrokenPrototype, Transform(cuffsToRemove).Coordinates);
|
||||
_hands.PickupOrDrop(user, trash);
|
||||
}
|
||||
// WD EDIT END
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -41,6 +41,9 @@ namespace Content.Shared.Verbs
|
||||
public static readonly VerbCategory MeatyOre =
|
||||
new("MeatyOre", null);
|
||||
|
||||
public static readonly VerbCategory Cult =
|
||||
new("verb-categories-cult", "/Textures/White/Cult/interface.rsi/icon.png");
|
||||
|
||||
public static readonly VerbCategory Antag =
|
||||
new("verb-categories-antag", "/Textures/Interface/VerbIcons/antag-e_sword-temp.192dpi.png", iconsOnly: true) { Columns = 5 };
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ public sealed partial class CultTeleportTargetActionEvent : EntityTargetActionEv
|
||||
{
|
||||
}
|
||||
|
||||
public sealed partial class CultElectromagneticPulseTargetActionEvent : EntityTargetActionEvent
|
||||
public sealed partial class CultElectromagneticPulseInstantActionEvent : InstantActionEvent
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
9
Content.Shared/_White/Cult/Actions/ShacklesEvent.cs
Normal file
9
Content.Shared/_White/Cult/Actions/ShacklesEvent.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using Content.Shared.DoAfter;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._White.Cult.Actions;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class ShacklesEvent : SimpleDoAfterEvent
|
||||
{
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace Content.Shared._White.Cult.Components;
|
||||
/// <summary>
|
||||
/// This is used for tagging a mob as a cultist.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class CultistComponent : Component
|
||||
{
|
||||
[DataField("greetSound", customTypeSerializer: typeof(SoundSpecifierTypeSerializer))]
|
||||
@@ -18,22 +18,28 @@ public sealed partial class CultistComponent : Component
|
||||
|
||||
public CancellationTokenSource? HolyConvertToken;
|
||||
|
||||
[NonSerialized]
|
||||
public List<EntityUid?> SelectedEmpowers = new();
|
||||
[AutoNetworkedField]
|
||||
public List<NetEntity?> SelectedEmpowers = new();
|
||||
|
||||
public static string SummonCultDaggerAction = "InstantActionSummonCultDagger";
|
||||
|
||||
public static string BloodRitesAction = "InstantActionBloodRites";
|
||||
|
||||
public static string EmpPulseAction = "InstantActionEmpPulse";
|
||||
|
||||
public static string CultTwistedConstructionAction = "ActionCultTwistedConstruction";
|
||||
|
||||
public static string CultTeleportAction = "ActionCultTeleport";
|
||||
|
||||
public static string CultSummonCombatEquipmentAction = "ActionCultSummonCombatEquipment";
|
||||
|
||||
public static string CultStunAction = "ActionCultStun";
|
||||
|
||||
public static string CultShadowShacklesAction = "ActionCultShadowShackles";
|
||||
|
||||
public static List<string> CultistActions = new()
|
||||
{
|
||||
SummonCultDaggerAction, BloodRitesAction, CultTwistedConstructionAction, CultTeleportAction,
|
||||
CultSummonCombatEquipmentAction
|
||||
CultSummonCombatEquipmentAction, CultStunAction, EmpPulseAction, CultShadowShacklesAction
|
||||
};
|
||||
}
|
||||
|
||||
27
Content.Shared/_White/Cult/SpellVerbEvents.cs
Normal file
27
Content.Shared/_White/Cult/SpellVerbEvents.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using Content.Shared.DoAfter;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._White.Cult;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class SpellCreatedEvent : SimpleDoAfterEvent
|
||||
{
|
||||
public string Spell = "";
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class CultEmpowerRemoveBuiMessage : BoundUserInterfaceMessage
|
||||
{
|
||||
public NetEntity ActionType;
|
||||
|
||||
public CultEmpowerRemoveBuiMessage(NetEntity actionType)
|
||||
{
|
||||
ActionType = actionType;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum CultEmpowerRemoveUiKey : byte
|
||||
{
|
||||
Key
|
||||
}
|
||||
@@ -10,3 +10,28 @@ wraith-phase-action-name = Фазовый Сдвиг
|
||||
wraith-phase-action-description = Это заклинание позволяет проходить сквозь стены, подобно бесплотному полету волшебника.
|
||||
juggernaut-create-wall-action-name = Щит
|
||||
juggernaut-create-wall-action-description = Это заклинание создает временное, невидимое, силовое поле для защиты себя и союзников от подавляющего огня.
|
||||
|
||||
|
||||
ent-ActionCultTwistedConstruction = Искажённое Воздействие
|
||||
.desc = Зловещее заклинание, которое используют для превращения металла в рунический металл.
|
||||
|
||||
ent-ActionCultTeleport = Телепорт
|
||||
.desc = Полезное заклинание, которое телепортирует культистов в выбранное место.
|
||||
|
||||
ent-ActionCultSummonCombatEquipment = Призыв Боевого Снаряжения
|
||||
.desc = Важное заклинание, которое позволяет вам вызвать полный набор боевого снаряжения.
|
||||
|
||||
ent-InstantActionSummonCultDagger = Призыв Ритуального Кинжала
|
||||
.desc = Призывает ритуальный кинжал.
|
||||
|
||||
ent-InstantActionBloodRites = Кровавые Обряды
|
||||
.desc = Высасывает кровь и исцеляет вас.
|
||||
|
||||
ent-ActionCultStun = Оглушение
|
||||
.desc = Сильное заклинание, которое оглушает и обезмолвливает жертв.
|
||||
|
||||
ent-ActionCultShadowShackles = Теневые Узы
|
||||
.desc = Бесшумное заклинание, которое наложит на человека теневые наручники и заставит вашу жертву замолчать на 10 секунд.
|
||||
|
||||
ent-InstantActionEmpPulse = Электромагнитный Импульс
|
||||
.desc = Большое заклинание, которое позволяет пользователю направлять темную энергию в ЭМИ.
|
||||
|
||||
9
Resources/Locale/ru-RU/cult/verb.ftl
Normal file
9
Resources/Locale/ru-RU/cult/verb.ftl
Normal file
@@ -0,0 +1,9 @@
|
||||
verb-categories-cult = Культ
|
||||
|
||||
verb-spell-create-text = Создать заклинание крови
|
||||
verb-spell-create-message = Вы можете создать одно заклинание крови без руны могущества.
|
||||
verb-spell-create-too-much = Начертите руну могущества, чтобы создать больше одного заклинания крови.
|
||||
|
||||
verb-spell-remove-text = Удалить заклинание крови
|
||||
verb-spell-remove-message = Убрать любое из созданных заклинаний крови.
|
||||
verb-spell-remove-no-spells = Заклинания крови отсутствуют.
|
||||
@@ -212,6 +212,10 @@
|
||||
type: TeleportRunesListWindowBUI
|
||||
- key: enum.SummonCultistUiKey.Key
|
||||
type: SummonCultistListWindowBUI
|
||||
- key: enum.CultEmpowerUiKey.Key
|
||||
type: SpellSelectorBUI
|
||||
- key: enum.CultEmpowerRemoveUiKey.Key
|
||||
type: SpellRemoverBUI
|
||||
# WD-EDIT END
|
||||
- type: Puller
|
||||
- type: Butcherable
|
||||
|
||||
@@ -41,6 +41,10 @@
|
||||
type: TeleportRunesListWindowBUI
|
||||
- key: enum.SummonCultistUiKey.Key
|
||||
type: SummonCultistListWindowBUI
|
||||
- key: enum.CultEmpowerUiKey.Key
|
||||
type: SpellSelectorBUI
|
||||
- key: enum.CultEmpowerRemoveUiKey.Key
|
||||
type: SpellRemoverBUI
|
||||
# WD-EDIT END
|
||||
- type: Sprite
|
||||
scale: 0.9, 0.9
|
||||
|
||||
@@ -5,13 +5,15 @@
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: EntityTargetAction
|
||||
useDelay: 50
|
||||
canTargetSelf: false
|
||||
icon:
|
||||
sprite: /Textures/Objects/Materials/Sheets/metal.rsi
|
||||
state: steel
|
||||
event: !type:CultTwistedConstructionActionEvent
|
||||
itemIconStyle: BigAction
|
||||
charges: 1
|
||||
temporary: true
|
||||
removeOnNoCharges: true
|
||||
|
||||
- type: entity
|
||||
id: ActionCultTeleport
|
||||
@@ -20,7 +22,6 @@
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: EntityTargetAction
|
||||
useDelay: 30
|
||||
whitelist:
|
||||
components:
|
||||
- HumanoidAppearance
|
||||
@@ -33,6 +34,9 @@
|
||||
state: teleport
|
||||
event: !type:CultTeleportTargetActionEvent
|
||||
itemIconStyle: BigAction
|
||||
charges: 1
|
||||
temporary: true
|
||||
removeOnNoCharges: true
|
||||
|
||||
- type: entity
|
||||
id: ActionCultSummonCombatEquipment
|
||||
@@ -41,7 +45,6 @@
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: EntityTargetAction
|
||||
useDelay: 300
|
||||
whitelist:
|
||||
components:
|
||||
- HumanoidAppearance
|
||||
@@ -54,6 +57,53 @@
|
||||
state: armor
|
||||
event: !type:CultSummonCombatEquipmentTargetActionEvent
|
||||
itemIconStyle: BigAction
|
||||
charges: 1
|
||||
temporary: true
|
||||
removeOnNoCharges: true
|
||||
|
||||
- type: entity
|
||||
id: ActionCultStun
|
||||
name: Stun
|
||||
description: A potent spell that will stun and mute victims.
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: EntityTargetAction
|
||||
whitelist:
|
||||
components:
|
||||
- HumanoidAppearance
|
||||
canTargetSelf: false
|
||||
deselectOnMiss: true
|
||||
repeat: false
|
||||
icon:
|
||||
sprite: /Textures/White/Cult/actions_cult.rsi
|
||||
state: stun
|
||||
event: !type:CultStunTargetActionEvent
|
||||
itemIconStyle: BigAction
|
||||
charges: 1
|
||||
temporary: true
|
||||
removeOnNoCharges: true
|
||||
|
||||
- type: entity
|
||||
id: ActionCultShadowShackles
|
||||
name: Shadow Shackles
|
||||
description: A stealthy spell that will summon shadowy handcuffs on a person, and temporarily silence your victim for 10 seconds.
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: EntityTargetAction
|
||||
whitelist:
|
||||
components:
|
||||
- HumanoidAppearance
|
||||
canTargetSelf: false
|
||||
deselectOnMiss: true
|
||||
repeat: false
|
||||
icon:
|
||||
sprite: /Textures/White/Cult/actions_cult.rsi
|
||||
state: shackles
|
||||
event: !type:CultShadowShacklesTargetActionEvent
|
||||
itemIconStyle: BigAction
|
||||
charges: 4
|
||||
temporary: true
|
||||
removeOnNoCharges: true
|
||||
|
||||
- type: entity
|
||||
id: InstantActionSummonCultDagger
|
||||
@@ -66,7 +116,9 @@
|
||||
sprite: /Textures/White/Cult/interface.rsi
|
||||
state: icon
|
||||
event: !type:CultSummonDaggerActionEvent
|
||||
useDelay: 200
|
||||
charges: 1
|
||||
temporary: true
|
||||
removeOnNoCharges: true
|
||||
|
||||
- type: entity
|
||||
id: InstantActionBloodRites
|
||||
@@ -79,4 +131,21 @@
|
||||
sprite: /Textures/White/Cult/actions_cult.rsi
|
||||
state: blood_rites
|
||||
event: !type:CultBloodRitesInstantActionEvent
|
||||
useDelay: 35
|
||||
charges: 4
|
||||
temporary: true
|
||||
removeOnNoCharges: true
|
||||
|
||||
- type: entity
|
||||
id: InstantActionEmpPulse
|
||||
name: Electromagnetic Pulse
|
||||
description: A large spell that allows a user to channel dark energy into an EMP.
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: InstantAction
|
||||
icon:
|
||||
sprite: /Textures/White/Cult/actions_cult.rsi
|
||||
state: emp
|
||||
event: !type:CultElectromagneticPulseInstantActionEvent
|
||||
charges: 1
|
||||
temporary: true
|
||||
removeOnNoCharges: true
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
- type: entity
|
||||
name: shadow shackles
|
||||
description: Shackles that bind the wrists with sinister magic.
|
||||
id: ShadowShackles
|
||||
parent: Handcuffs
|
||||
components:
|
||||
- type: Handcuff
|
||||
breakoutTime: 15
|
||||
color: black
|
||||
breakOnRemove: true
|
||||
- type: Sprite
|
||||
color: black
|
||||
Reference in New Issue
Block a user