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:
Aviu00
2024-03-01 17:44:27 +09:00
committed by GitHub
parent 9b5dd4481d
commit 71ca698a7c
20 changed files with 498 additions and 43 deletions

View File

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

View File

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

View File

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

View File

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

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

View File

@@ -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"/>.

View File

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

View File

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

View File

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

View File

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

View File

@@ -18,7 +18,7 @@ public sealed partial class CultTeleportTargetActionEvent : EntityTargetActionEv
{
}
public sealed partial class CultElectromagneticPulseTargetActionEvent : EntityTargetActionEvent
public sealed partial class CultElectromagneticPulseInstantActionEvent : InstantActionEvent
{
}

View 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
{
}

View File

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

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

View File

@@ -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 = Большое заклинание, которое позволяет пользователю направлять темную энергию в ЭМИ.

View 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 = Заклинания крови отсутствуют.

View File

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

View File

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

View File

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

View File

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