diff --git a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs
index 20655737259..b01d7dac8ac 100644
--- a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs
+++ b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs
@@ -156,7 +156,6 @@ public override void Update(float frameTime)
if (altDown == BoundKeyState.Up && attackTime >= TimeSpan.FromSeconds(charged.MinAttackTime) || attackTime >= TimeSpan.FromSeconds(charged.MaxAttackTime))
{
RaisePredictiveEvent(new ChargedAttackEnd(GetNetCoordinates(coordinates), GetNetEntity(weaponUid), attackTime));
- Log.Info("1");
return;
}
else if (altDown == BoundKeyState.Up && attackTime <= TimeSpan.FromSeconds(charged.MinAttackTime))
diff --git a/Content.Server/Imperial/Medieval/Cult/Bloodspells/CultCastSystem.cs b/Content.Server/Imperial/Medieval/Cult/Bloodspells/CultCastSystem.cs
index b7be87ea2e5..14ad17c0da1 100644
--- a/Content.Server/Imperial/Medieval/Cult/Bloodspells/CultCastSystem.cs
+++ b/Content.Server/Imperial/Medieval/Cult/Bloodspells/CultCastSystem.cs
@@ -1,27 +1,25 @@
+using System.Linq;
+using System.Numerics;
using System.Data;
using Content.Server.Chat.Systems;
using Content.Server.Cult.Components;
-using Content.Server.Imperial.Medieval.Cult.Bloodspells.mateials;
+using Content.Server.Imperial.Medieval.Cult.Bloodspells.Materials;
+using Content.Server.Imperial.Medieval.Cult.Bloodspells.Light;
+using Content.Server.Hands.Systems;
using Content.Shared.Body.Components;
using Content.Shared.Inventory;
using Content.Shared.Popups;
-using Robust.Shared.Timing;
-using System.Linq;
-using System.Numerics;
-using Content.Server.Hands.Systems;
-using Content.Server.Imperial.Medieval.Cult.Bloodspells.light;
+using Content.Shared.Stacks;
using Content.Shared.Alert;
using Content.Shared.Damage;
using Content.Shared.Imperial.Medieval.Cult;
using Content.Shared.Interaction.Events;
using Content.Shared.Weapons.Melee.Events;
-
+using Robust.Shared.Prototypes;
+using Robust.Shared.Timing;
namespace Content.Server.Imperial.Medieval.Cult.Bloodspells;
-///
-/// This handles...
-///
public sealed class CultCastSystem : EntitySystem
{
[Dependency] private readonly HandsSystem _handsSystem = default!;
@@ -32,352 +30,316 @@ public sealed class CultCastSystem : EntitySystem
[Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly AlertsSystem _alert = default!;
+ [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
+ [Dependency] private readonly SharedStackSystem _stack = default!;
+
+ private const int MaxStoredMessages = 3;
+ private const float MinTimeBetweenWords = 0.7f;
+ private const float MaxSpellCastTime = 5.0f;
+ private const float MaterialLookupRange = 1f;
+ private const float DeathCurseDamageMultiplier = 1.5f;
+ private const int DeathCurseCountDivisor = 2;
+
+ private List _bloodSpells = new();
- ///
public override void Initialize()
{
SubscribeLocalEvent(OnSpoke);
- SubscribeLocalEvent(OnGetDamage);
+ SubscribeLocalEvent(OnDamageReceived);
SubscribeLocalEvent(OnInit);
- SubscribeLocalEvent(OnAttack);
-
+ SubscribeLocalEvent(OnAttackAttempt);
}
private void OnInit(EntityUid uid, CultMemberComponent component, ComponentInit args)
{
- if (component.DeathCusre)
+ if (component.DeathCurse)
_alert.ShowAlert(uid, component.DeathCurseAlert);
}
- private void OnGetDamage(EntityUid uid, CultMemberComponent component, DamageChangedEvent args)
+ private void OnDamageReceived(EntityUid uid, CultMemberComponent component, DamageChangedEvent args)
{
- if (!component.DeathCusre)
+ if (!component.DeathCurse || !args.DamageIncreased || !args.Origin.HasValue)
+ return;
+
+ var attacker = args.Origin.Value;
+
+ if (HasComp(attacker))
return;
- if (!args.DamageIncreased)
+
+ if (TryComp(attacker, out var cursed) && cursed.CurseLevel != 0)
return;
- if (!args.Origin.HasValue)
+
+ ApplyOrIncreaseCurse(attacker);
+ RemoveDeathCurse(uid, component);
+ }
+
+ private void OnAttackAttempt(EntityUid uid, CultMemberComponent component, AttackAttemptEvent args)
+ {
+ if (!component.DeathCurse || args.Target == null)
return;
- if (HasComp(args.Origin.Value))
+
+ var target = args.Target.Value;
+
+ if (HasComp(target))
+ return;
+
+ if (TryComp(target, out var cursed) && cursed.CurseLevel != 0)
return;
- if (TryComp(args.Origin.Value, out var curs))
- {
- if (curs.CurseLevel != 0)
- return;
- }
- if (TryComp(args.Origin.Value, out var cursed))
+ RemoveDeathCurse(uid, component);
+ }
+
+ private void ApplyOrIncreaseCurse(EntityUid target)
+ {
+ if (TryComp(target, out var existingCurse))
{
- foreach (var key in cursed.CurseDamage.DamageDict.Keys.ToList())
+ foreach (var key in existingCurse.CurseDamage.DamageDict.Keys.ToList())
{
- cursed.CurseDamage.DamageDict[key] *= 1.5f;
- cursed.CurseCount /= 2;
+ existingCurse.CurseDamage.DamageDict[key] *= DeathCurseDamageMultiplier;
+ existingCurse.CurseCount /= DeathCurseCountDivisor;
}
}
else
{
- AddComp(args.Origin.Value);
+ EnsureComp(target);
}
- component.DeathCusre = false;
+ }
+
+ private void RemoveDeathCurse(EntityUid uid, CultMemberComponent component)
+ {
+ component.DeathCurse = false;
_alert.ClearAlert(uid, component.DeathCurseAlert);
}
- private void OnAttack(EntityUid uid, CultMemberComponent component, AttackAttemptEvent args)
+ private bool CheckSpellSequence(Queue<(string message, TimeSpan time)> queue, BloodSpellPrototype spell)
{
- if (!component.DeathCusre)
- return;
- if (args.Target == null)
- return;
- if (HasComp(args.Target.Value))
- return;
- if (TryComp(args.Target.Value, out var curs) && curs.CurseLevel != 0)
- return;
+ var sequenceLength = spell.Incantation.Count;
+ if (queue.Count < sequenceLength)
+ return false;
- component.DeathCusre = false;
- _alert.ClearAlert(uid, component.DeathCurseAlert);
+ var recentMessages = queue.Reverse().Take(sequenceLength).Reverse().Select(item => item.message).ToArray();
+
+ return recentMessages.Zip(spell.Incantation, (msg, spellWord) =>
+ msg.Equals(spellWord, StringComparison.OrdinalIgnoreCase)).All(match => match);
}
- private static bool CheckSequenceInQueueFromRow(Queue<(string message, TimeSpan time)> queue, string[,] array, int targetRow)
+ private bool ValidateSpellTiming(Queue<(string message, TimeSpan time)> messages, EntityUid caster)
{
- if (targetRow >= array.GetLength(0) || targetRow < 0) return false;
+ if (messages.Count == 0)
+ return false;
- int seqLength = array.GetLength(1);
- if (queue.Count < seqLength) return false;
+ var messageArray = messages.ToArray();
- var messages = queue.Reverse().Take(seqLength).Reverse().Select(item => item.message).ToArray();
+ for (int i = 1; i < messageArray.Length; i++)
+ {
+ var timeDiff = messageArray[i].time - messageArray[i - 1].time;
+ if (timeDiff.TotalSeconds < MinTimeBetweenWords)
+ {
+ _popupSystem.PopupEntity(Loc.GetString("cult-spell-too-fast"), caster, caster);
+ return false;
+ }
+ }
- // Получаем последовательность из ряда
- var rowSequence = new string[seqLength];
- for (int j = 0; j < seqLength; j++)
+ var oldestMessage = messages.MaxBy(item => item.time);
+ if (oldestMessage.time.TotalSeconds <= MaxSpellCastTime)
{
- rowSequence[j] = array[targetRow, j];
+ _popupSystem.PopupEntity(Loc.GetString("cult-spell-too-slow"), caster, caster);
+ return false;
}
- // Сравнение (case-insensitive)
- return messages.Zip(rowSequence, (msg, seq) => msg.Equals(seq, StringComparison.OrdinalIgnoreCase)).All(match => match);
+ return true;
}
- private bool CheckTime(Queue<(string message, TimeSpan time)> lastSpokenMessages , EntityUid uid)
+ private void OnSpoke(EntityUid uid, CultMemberComponent component, EntitySpokeEvent args)
{
- if (lastSpokenMessages.Count == 0)
- return false;
+ if (component.LastSpokenMessages.Count >= MaxStoredMessages)
+ component.LastSpokenMessages.Dequeue();
+
+ component.LastSpokenMessages.Enqueue((args.Message, _timing.CurTime));
+
+ if (!TryComp(uid, out var bloodstream) || bloodstream.BleedAmount == 0)
+ return;
+
+ var spells = _prototypeManager
+ .EnumeratePrototypes()
+ .OrderByDescending(s => s.Incantation.Count);
- var messages = lastSpokenMessages.ToArray();
- for (int i = 1; i < messages.Length; i++)
+ foreach (var spell in spells)
{
- var diff = messages[i].time - messages[i - 1].time;
- if (diff.TotalSeconds < 0.7)
- {
- _popupSystem.PopupEntity("Ты чуствуешь, что твои слова не успели наполнится магией", uid, uid);
- return true;
- }
+ if (spell.Incantation.Count == 0 || spell.Incantation.Last() != args.Message)
+ continue;
+
+ if (!CheckSpellSequence(component.LastSpokenMessages, spell))
+ continue;
+
+ if (!ValidateSpellTiming(component.LastSpokenMessages, uid))
+ return;
+ ExecuteSpell(uid, component, spell);
+ return;
}
+ }
- var oldest = lastSpokenMessages.MaxBy(item => item.time);
- if (oldest.time.TotalSeconds <= 5)
+ private void ExecuteSpell(EntityUid caster, CultMemberComponent component, BloodSpellPrototype spell)
+ {
+ switch (spell.SpellType)
{
- _popupSystem.PopupEntity("Ты чуствуешь, что твои слова успели обветшать", uid, uid);
- return true;
+ case BloodSpellType.ItemUpgrade:
+ CastItemUpgradeSpell(caster, spell);
+ break;
+
+ case BloodSpellType.CraftItem:
+ CastCraftingSpell(caster, spell);
+ break;
+
+ case BloodSpellType.CraftArmor:
+ CastCraftingSpell(caster, spell, isArmor: true);
+ break;
+
+ case BloodSpellType.DeathCurse:
+ CastDeathCurseSpell(caster, component, spell);
+ break;
+
+ default:
+ _popupSystem.PopupEntity(Loc.GetString("cult-spell-incorrect"), caster, caster);
+ break;
}
- return false;
}
- private void OnSpoke(EntityUid uid, CultMemberComponent component, EntitySpokeEvent args)
+ private void CastItemUpgradeSpell(EntityUid caster, BloodSpellPrototype spell)
{
- if (component.LastSpokenMessages.Count >= 3)
+ if (!_handsSystem.TryGetActiveItem(caster, out var heldItem))
{
- component.LastSpokenMessages.Dequeue(); // Удаляем первый (самый старый) элемент
+ var failMsg = spell.FailureMessage ?? "cult-spell-need-holy-scripture";
+ _popupSystem.PopupEntity(Loc.GetString(failMsg), caster, caster);
+ return;
}
- component.LastSpokenMessages.Enqueue((args.Message,
- _timing.CurTime)); // я бы мог бы сделать сразу что то с акцентами но блин, это всё таки магия и надо быть точным
- if (!TryComp(uid, out var bloodstream))
+ var itemPrototype = _entityManager.GetComponent(heldItem.Value).EntityPrototype?.ID;
+ if (spell.RequiredHeldItem == null || itemPrototype != spell.RequiredHeldItem.Value.Id)
+ {
+ var itemName = _entityManager.GetComponent(heldItem.Value).EntityPrototype?.Name ?? "unknown";
+ _popupSystem.PopupEntity(Loc.GetString("cult-spell-wrong-item", ("item", itemName)), caster, caster);
return;
- if (bloodstream.BleedAmount == 0)
+ }
+
+ if (spell.ReplacementItem == null)
return;
- string[,] bloodcasts =
+
+ EntityManager.DeleteEntity(heldItem.Value);
+ var newItem = Spawn(spell.ReplacementItem.Value, Transform(caster).Coordinates);
+ _handsSystem.TryPickup(caster, newItem, checkActionBlocker: false);
+
+ if (spell.SuccessMessage != null)
+ _popupSystem.PopupEntity(Loc.GetString(spell.SuccessMessage), caster, caster);
+ }
+
+ private void CastCraftingSpell(EntityUid caster, BloodSpellPrototype spell, bool isArmor = false)
+ {
+ if (spell.RequiredMaterial == null || spell.SpawnProto == null)
+ return;
+
+ var (availableCount, materials) = CollectNearbyMaterials(caster, spell.RequiredMaterial, spell.RequiredMaterialCount);
+ if (availableCount < spell.RequiredMaterialCount)
{
- {"Ave", "The", "Truth"},
- {"Ave", "The", "Bronus"},
- {"Ave", "The", "Vilkus"},
- {"Ave", "The", "Knatus"},
- {"Ave", "The", "Sekir"},
- {"Ave", "The", "Magical"},
- {"Katariemai", "Opoion", "Me chtypisei"},
- // {"Дебагус", "Магикус", "Призывус"}
- // {"Elderberry", "Fig", "Banana"}
- };
-
- for (int i = bloodcasts.GetLength(0)-1; i >= 0; i--)
+ var failMsg = spell.FailureMessage ?? "cult-spell-insufficient-materials";
+ _popupSystem.PopupEntity(Loc.GetString(failMsg), caster, caster);
+ return;
+ }
+
+ if (isArmor && spell.ReplaceEquipment)
{
- if (bloodcasts[i, 2] != args.Message) // Проверяем первое слово
- continue;
+ if (spell.EquipmentSlot == null ||
+ !TryComp(caster, out var inventory) ||
+ !_inventorySystem.TryGetSlotEntity(caster, spell.EquipmentSlot, out var existingOutfit))
+ {
+ var failMsg = spell.FailureMessage ?? "cult-spell-insufficient-materials";
+ _popupSystem.PopupEntity(Loc.GetString(failMsg), caster, caster);
+ return;
+ }
+
+ ConsumeMaterials(materials);
+ EntityManager.DeleteEntity(existingOutfit.Value);
+ var armor = Spawn(spell.SpawnProto.Value, Transform(caster).Coordinates);
+ _inventorySystem.TryEquip(caster, armor, spell.EquipmentSlot, silent: true, force: true, inventory: inventory);
+ }
+ else
+ {
+ ConsumeMaterials(materials);
+ Spawn(spell.SpawnProto.Value, Transform(caster).Coordinates);
+ }
+
+ if (spell.SuccessMessage != null)
+ _popupSystem.PopupEntity(Loc.GetString(spell.SuccessMessage), caster, caster);
+ }
+
+ private (int totalCount, List<(EntityUid entity, int takeCount)> materials) CollectNearbyMaterials(
+ EntityUid caster,
+ string materialType,
+ int requiredCount)
+ {
+ var result = new List<(EntityUid entity, int takeCount)>();
+ int foundTotal = 0;
+
+ var entities = _lookup.GetEntitiesInRange(caster, MaterialLookupRange)
+ .Where(e => TryComp(e, out var mat) && mat.MaterialType == materialType)
+ .ToList();
+
+ var sortedEntities = entities.OrderByDescending(e => {
+ int count = TryComp(e, out var stack) ? stack.Count : 1;
+ return count >= requiredCount ? int.MaxValue : count;
+ }).ThenByDescending(e => _stack.GetCount(e));
+
+ foreach (var entity in sortedEntities)
+ {
+ if (foundTotal >= requiredCount)
+ break;
+
+ int availableInStack = _stack.GetCount(entity);
+ int neededFromThisStack = Math.Min(availableInStack, requiredCount - foundTotal);
+
+ result.Add((entity, neededFromThisStack));
+ foundTotal += neededFromThisStack;
+ }
+
+ return (foundTotal, result);
+ }
- if (!CheckSequenceInQueueFromRow(component.LastSpokenMessages, bloodcasts, i))
+ private void ConsumeMaterials(List<(EntityUid entity, int takeCount)> materials)
+ {
+ foreach (var (entity, takeCount) in materials)
+ {
+ if (!TryComp(entity, out var stack))
{
+ EntityManager.DeleteEntity(entity);
continue;
}
- if (CheckTime(component.LastSpokenMessages, uid))
- return;
- switch (bloodcasts[i, 2])
+
+ if (stack.Count <= takeCount)
{
- case "Призывус":
- {
- var center = Transform(uid).Coordinates;
- for (int x = -4; x <= 5; x++)
- {
- for (int y = -4; y <= 5; y++)
- {
- var b = Spawn("MedievalCultBrushFine", center.Offset(new Vector2(x*0.5f, y*-0.5f)));
- if (!TryComp(b, out var bloodPaint))
- break;
- bloodPaint.PosX = x+5;
- bloodPaint.PosY = y+5;
- }
- }
- break;
- }
-
-
- case "Truth":
- {
- if (_handsSystem.TryGetActiveItem(uid, out var heldItem))
- {
- // Проверяем, что предмет в руке — это именно книга-прототип (MedievalBookCultGuide)
- if (!_entityManager.GetComponent(heldItem.Value).EntityPrototype?.ID.Equals("MedievalBookCultGuide") == true)
- {
- _popupSystem.PopupEntity("В руке должно быть святое писание! а не "+ heldItem+" "+_entityManager.GetComponent(heldItem.Value).EntityPrototype?.Name, uid, uid);
- break;
- }
-
- // Удаляем текущий предмет в руке
- _entityManager.DeleteEntity(heldItem.Value);
-
- // Спавним новую книгу и экипируем её
- var newBook = Spawn("MedievalBookCultGuide2", Transform(uid).Coordinates);
- _handsSystem.TryPickup(uid, newBook, checkActionBlocker: false);
- }
- else
- {
- _popupSystem.PopupEntity("В руке должно быть святое писание!", uid, uid);
- }
- break;
- }
-
-
- case "Bronus":
- {
- var needCount = 5;
- var myMaterials = new List{};
- foreach (var target in _lookup.GetEntitiesInRange(uid, 1f))
- {
- if (TryComp(target, out var bloodMaterial) && bloodMaterial.MaterialType == "BloodIron")
- {
- myMaterials.Add(target);
- needCount--;
- if (needCount == 0)
- {
- if (TryComp(uid, out var inventory) && _inventorySystem.TryGetSlotEntity(uid, "outerClothing", out var existingOutfit))
- {
- foreach (var material in myMaterials)
- {
- _entityManager.DeleteEntity(material);
- }
- _entityManager.DeleteEntity(existingOutfit.Value);
- var b = Spawn("MedievalClothingOuterArmorCultUp", Transform(uid).Coordinates);
- _inventorySystem.TryEquip(uid, b, "outerClothing", silent: true, force: true, inventory: inventory);
- return;
- }
-
- }
- }
- }
- _popupSystem.PopupEntity("Ресурсов не достаточно", uid, uid);
- break;
- }
- case "Vilkus":
- {
- var needCount = 5;
- var myMaterials = new List{};
- foreach (var target in _lookup.GetEntitiesInRange(uid, 1f))
- {
- if (TryComp(target, out var bloodMaterial) && bloodMaterial.MaterialType == "BloodIron")
- {
- myMaterials.Add(target);
- needCount--;
- if (needCount == 0)
- {
- foreach (var material in myMaterials)
- {
- _entityManager.DeleteEntity(material);
- }
- Spawn("MedievalSpearCult", Transform(uid).Coordinates);
- return;
- }
- }
- }
- _popupSystem.PopupEntity("Ресурсов не достаточно", uid, uid);
- break;
- }
- case "Knatus":
- {
- var needCount = 5;
- var myMaterials = new List{};
- foreach (var target in _lookup.GetEntitiesInRange(uid, 1f))
- {
- if (TryComp(target, out var bloodMaterial) && bloodMaterial.MaterialType == "BloodIron")
- {
- myMaterials.Add(target);
- needCount--;
- if (needCount == 0)
- {
- foreach (var material in myMaterials)
- {
- _entityManager.DeleteEntity(material);
- }
- Spawn("MedievalCultYatagan", Transform(uid).Coordinates);
- return;
- }
- }
- }
- _popupSystem.PopupEntity("Ресурсов не достаточно", uid, uid);
- break;
- }
- case "Sekir":
- {
- var needCount = 5;
- var myMaterials = new List{};
- foreach (var target in _lookup.GetEntitiesInRange(uid, 1f))
- {
- if (TryComp(target, out var bloodMaterial) && bloodMaterial.MaterialType == "BloodIron")
- {
- myMaterials.Add(target);
- needCount--;
- if (needCount == 0)
- {
- foreach (var material in myMaterials)
- {
- _entityManager.DeleteEntity(material);
- }
- Spawn("MedievalIronSekirCult", Transform(uid).Coordinates);
- return;
- }
- }
- }
- _popupSystem.PopupEntity("Ресурсов не достаточно", uid, uid);
- break;
- }
- case "Magical":
- {
- var needCount = 5;
- var myMaterials = new List{};
- foreach (var target in _lookup.GetEntitiesInRange(uid, 1f))
- {
- if (TryComp(target, out var bloodMaterial) && bloodMaterial.MaterialType == "BloodLeather")
- {
- myMaterials.Add(target);
- needCount--;
- if (needCount == 0)
- {
- if (TryComp(uid, out var inventory) && _inventorySystem.TryGetSlotEntity(uid, "outerClothing", out var existingOutfit))
- {
- foreach (var material in myMaterials)
- {
- _entityManager.DeleteEntity(material);
- }
- _entityManager.DeleteEntity(existingOutfit.Value);
- var b = Spawn("MedievalClothingOuterArmorCultMana", Transform(uid).Coordinates);
- _inventorySystem.TryEquip(uid, b, "outerClothing", silent: true, force: true, inventory: inventory);
- return;
- }
-
- }
- }
- }
- _popupSystem.PopupEntity("Ресурсов не достаточно", uid, uid);
- break;
- }
- case "Me chtypisei":
- {
- if (!component.DeathCusre)
- {
- component.DeathCusre = true;
- _popupSystem.PopupEntity("Да будет проклят тот, кто меня ударит", uid, uid);
- _alert.ShowAlert(uid, component.DeathCurseAlert);
- }
- else
- {
- _popupSystem.PopupEntity("Ты чуствуешь, что проклятье сильно", uid, uid);
- }
- break;
- }
- default:
- _popupSystem.PopupEntity("Ты чуствуешь неправильность в своих словах", uid, uid);
- break;
+ EntityManager.DeleteEntity(entity);
+ }
+ else
+ {
+ _stack.SetCount(entity, stack.Count - takeCount, stack);
}
}
+ }
+ private void CastDeathCurseSpell(EntityUid caster, CultMemberComponent component, BloodSpellPrototype spell)
+ {
+ if (!component.DeathCurse)
+ {
+ component.DeathCurse = true;
+ var successMsg = spell.SuccessMessage ?? "cult-spell-death-curse-activated";
+ _popupSystem.PopupEntity(Loc.GetString(successMsg), caster, caster);
+ _alert.ShowAlert(caster, component.DeathCurseAlert);
+ }
+ else
+ {
+ var failMsg = spell.FailureMessage ?? "cult-spell-death-curse-already-active";
+ _popupSystem.PopupEntity(Loc.GetString(failMsg), caster, caster);
+ }
}
}
-
diff --git a/Content.Server/Imperial/Medieval/Cult/Bloodspells/mateials/BloodMaterialComponent.cs b/Content.Server/Imperial/Medieval/Cult/Bloodspells/Materials/BloodMaterialComponent.cs
similarity index 59%
rename from Content.Server/Imperial/Medieval/Cult/Bloodspells/mateials/BloodMaterialComponent.cs
rename to Content.Server/Imperial/Medieval/Cult/Bloodspells/Materials/BloodMaterialComponent.cs
index f87468b9ecb..2f8a925a6f6 100644
--- a/Content.Server/Imperial/Medieval/Cult/Bloodspells/mateials/BloodMaterialComponent.cs
+++ b/Content.Server/Imperial/Medieval/Cult/Bloodspells/Materials/BloodMaterialComponent.cs
@@ -1,8 +1,5 @@
-namespace Content.Server.Imperial.Medieval.Cult.Bloodspells.mateials;
+namespace Content.Server.Imperial.Medieval.Cult.Bloodspells.Materials;
-///
-/// This is used for...
-///
[RegisterComponent]
public sealed partial class BloodMaterialComponent : Component
{
diff --git a/Content.Server/Imperial/Medieval/Cult/Bloodspells/MedievalBlodedComponent.cs b/Content.Server/Imperial/Medieval/Cult/Bloodspells/MedievalBlodedComponent.cs
deleted file mode 100644
index 94ba93c16dc..00000000000
--- a/Content.Server/Imperial/Medieval/Cult/Bloodspells/MedievalBlodedComponent.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace Content.Server.Imperial.Medieval.Cult.Bloodspells;
-
-///
-/// This is used for...
-///
-[RegisterComponent]
-public sealed partial class MedievalBlodedComponent : Component
-{
- [DataField("blood")]
- [ViewVariables(VVAccess.ReadWrite)]
- public int Blood;
-}
diff --git a/Content.Server/Imperial/Medieval/Cult/Bloodspells/MedievalBloodedComponent.cs b/Content.Server/Imperial/Medieval/Cult/Bloodspells/MedievalBloodedComponent.cs
new file mode 100644
index 00000000000..2418e38e192
--- /dev/null
+++ b/Content.Server/Imperial/Medieval/Cult/Bloodspells/MedievalBloodedComponent.cs
@@ -0,0 +1,8 @@
+namespace Content.Server.Imperial.Medieval.Cult.Bloodspells;
+
+[RegisterComponent]
+public sealed partial class MedievalBloodedComponent : Component
+{
+ [DataField("blood"), ViewVariables(VVAccess.ReadWrite)]
+ public int Blood;
+}
diff --git a/Content.Server/Imperial/Medieval/Cult/Bloodspells/light/DeathCurseSystem.cs b/Content.Server/Imperial/Medieval/Cult/Bloodspells/light/DeathCurseSystem.cs
index 0a0ae3d6894..86a05bd1b09 100644
--- a/Content.Server/Imperial/Medieval/Cult/Bloodspells/light/DeathCurseSystem.cs
+++ b/Content.Server/Imperial/Medieval/Cult/Bloodspells/light/DeathCurseSystem.cs
@@ -9,11 +9,8 @@
using Content.Shared.Popups;
using Robust.Shared.Timing;
-namespace Content.Server.Imperial.Medieval.Cult.Bloodspells.light;
+namespace Content.Server.Imperial.Medieval.Cult.Bloodspells.Light;
-///
-/// This handles...
-///
public sealed class DeathCurseSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
@@ -21,7 +18,6 @@ public sealed class DeathCurseSystem : EntitySystem
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly AlertsSystem _alertsSystem = default!;
- ///
private TimeSpan _nextCheckTime;
private TimeSpan _nextCheckTimePopup;
diff --git a/Content.Server/Imperial/Medieval/Cult/CultMemberComponent.cs b/Content.Server/Imperial/Medieval/Cult/CultMemberComponent.cs
index 393277822c5..6339840bb89 100644
--- a/Content.Server/Imperial/Medieval/Cult/CultMemberComponent.cs
+++ b/Content.Server/Imperial/Medieval/Cult/CultMemberComponent.cs
@@ -3,7 +3,6 @@
using Robust.Shared.Prototypes;
using System.Collections.Generic;
using System;
-using System.Linq;
using Content.Shared.Alert;
namespace Content.Server.Cult.Components;
@@ -12,17 +11,17 @@ namespace Content.Server.Cult.Components;
public sealed partial class CultMemberComponent : Component
{
[DataField]
- public EntityUid? parent;
+ public EntityUid? Parent;
[ViewVariables(VVAccess.ReadWrite)]
[DataField]
public DamageSpecifier Damage = new()
{
DamageDict = new()
- {
- { "Poison", 10 },
- { "Asphyxiation", 10}
- }
+ {
+ { "Poison", 10 },
+ { "Asphyxiation", 10 }
+ }
};
[ViewVariables(VVAccess.ReadWrite)]
@@ -30,7 +29,7 @@ public sealed partial class CultMemberComponent : Component
public Queue<(string message, TimeSpan time)> LastSpokenMessages = new();
[DataField]
- public bool DeathCusre = true;
+ public bool DeathCurse = true;
[DataField]
public ProtoId DeathCurseAlert = "CultDeathCurse";
diff --git a/Content.Server/Imperial/Medieval/Cult/CultSystem.cs b/Content.Server/Imperial/Medieval/Cult/CultSystem.cs
index 0699bf1137b..cb64414fb21 100644
--- a/Content.Server/Imperial/Medieval/Cult/CultSystem.cs
+++ b/Content.Server/Imperial/Medieval/Cult/CultSystem.cs
@@ -27,7 +27,7 @@
using Content.Server.Construction.Completions;
using Content.Server.Construction.Conditions;
using Content.Server.Imperial.Medieval.Cult.Bloodspells;
-using Content.Server.Imperial.Medieval.Cult.Bloodspells.mateials;
+using Content.Server.Imperial.Medieval.Cult.Bloodspells.Materials;
using Content.Shared.Alert;
using Content.Shared.Inventory;
using Content.Shared.Mobs.Components;
@@ -249,7 +249,7 @@ public override void Update(float frameTime)
if (picture.CollegiumUnlocked) continue;
foreach (var cultist in EntityManager.EntityQuery())
{
- if (TryComp(cultist.parent, out var blocker))
+ if (TryComp(cultist.Parent, out var blocker))
{
switch (blocker.Sector)
{
@@ -332,7 +332,7 @@ private void OnChangeParent(EntityUid uid, CultMemberComponent comp, ref MoveEve
if (!args.ParentChanged)
return;
- comp.parent = newParent;
+ comp.Parent = newParent;
}
public void OnActivated(EntityUid uid, CultCheckPictureComponent comp, ActivateInWorldEvent args)
{
@@ -931,7 +931,7 @@ private bool CheckCrystals(EntityUid uid, CultCheckPictureComponent comp, int bl
if (_itemSlotsSystem.TryGetSlot(slot.Item.Value, "Conductor" + i, out var container) &&
container.HasItem && container.Item != null)
{
- if (TryComp(container.Item.Value, out var bloodcomp))
+ if (TryComp(container.Item.Value, out var bloodcomp))
{
bloodcomp.Blood += bloodyCost * 3 + redCost;
if (bloodcomp.Blood >= 10)
@@ -945,13 +945,13 @@ private bool CheckCrystals(EntityUid uid, CultCheckPictureComponent comp, int bl
}
else
{
- AddComp(container.Item.Value);
+ EnsureComp(container.Item.Value);
}
}
}
- if (TryComp(slot.Item.Value, out var blodcomp))
+ if (TryComp(slot.Item.Value, out var blodcomp))
{
blodcomp.Blood += bloodyCost * 3 + redCost;
if (blodcomp.Blood >= 10)
@@ -967,7 +967,7 @@ private bool CheckCrystals(EntityUid uid, CultCheckPictureComponent comp, int bl
}
else
{
- AddComp(slot.Item.Value);
+ EnsureComp(slot.Item.Value);
}
comp.BloodyCrystall -= bloodyCost;
comp.RedCrystall -= redCost;
diff --git a/Content.Server/Imperial/Medieval/MedievalRevive/MedievalReviveSystem.cs b/Content.Server/Imperial/Medieval/MedievalRevive/MedievalReviveSystem.cs
index 94d2d660186..3523b867a88 100644
--- a/Content.Server/Imperial/Medieval/MedievalRevive/MedievalReviveSystem.cs
+++ b/Content.Server/Imperial/Medieval/MedievalRevive/MedievalReviveSystem.cs
@@ -1,167 +1,111 @@
using System.Linq;
-using System.Numerics;
using Content.Server.Administration.Logs;
-using Content.Server.Chat.Managers;
-using Content.Server.Chat.Systems;
-using Content.Server.GameTicking;
using Content.Server.Ghost.Components;
using Content.Server.MagicBarrier.Components;
using Content.Server.Mind;
-using Content.Server.Roles.Jobs;
-using Content.Shared.Actions;
-using Content.Shared.CCVar;
-using Content.Shared.Coordinates;
-using Content.Shared.Damage;
-using Content.Shared.Damage.Prototypes;
using Content.Shared.Database;
-using Content.Shared.Examine;
-using Content.Shared.Eye;
-using Content.Shared.FixedPoint;
-using Content.Shared.Follower;
using Content.Shared.Ghost;
using Content.Shared.Imperial.Medieval.CCVar;
using Content.Shared.Imperial.Medieval.MedievalReviveSpawner;
using Content.Shared.Imperial.Medieval.Revive;
using Content.Shared.Mind;
using Content.Shared.Mind.Components;
-using Content.Shared.Mobs;
-using Content.Shared.Mobs.Components;
-using Content.Shared.Mobs.Systems;
-using Content.Shared.Movement.Events;
-using Content.Shared.Movement.Systems;
-using Content.Shared.NameModifier.EntitySystems;
-using Content.Shared.Players;
-using Content.Shared.Popups;
-using Content.Shared.Storage.Components;
-using Content.Shared.Tag;
-using Content.Shared.Warps;
using Robust.Server.GameObjects;
using Robust.Shared.Configuration;
-using Robust.Shared.Map;
-using Robust.Shared.Network;
-using Robust.Shared.Physics.Components;
-using Robust.Shared.Physics.Systems;
using Robust.Shared.Player;
-using Robust.Shared.Prototypes;
using Robust.Shared.Random;
-using Robust.Shared.Timing;
using Robust.Shared.Utility;
-namespace Content.Server.Imperial.Medieval.Revive
+namespace Content.Server.Imperial.Medieval.Revive;
+
+public sealed class MedievalReviveSystem : EntitySystem
{
- public sealed class MedievalReviveSystem : EntitySystem
+ [Dependency] private readonly MindSystem _minds = default!;
+ [Dependency] private readonly TransformSystem _transform = default!;
+ [Dependency] private readonly IConfigurationManager _cfg = default!;
+ [Dependency] private readonly IRobustRandom _random = default!;
+ [Dependency] private readonly IAdminLogManager _adminLog = default!;
+
+ private const int MaxRevives = 3;
+
+ public override void Initialize()
{
- [Dependency] private readonly MindSystem _minds = default!;
- [Dependency] private readonly TransformSystem _transformSystem = default!;
- [Dependency] private readonly IRobustRandom _random = default!;
- [Dependency] private readonly IConfigurationManager _cfg = default!;
- [Dependency] private readonly SharedPopupSystem _popup = default!;
- [Dependency] private readonly IAdminLogManager _adminlog = default!;
+ SubscribeNetworkEvent(OnGhostReviveRequest);
+ SubscribeNetworkEvent(OnReviveCountRequest);
+ }
- private const int MaxRevives = 3;
+ private void OnGhostReviveRequest(GhostReviveRequestEvent ev, EntitySessionEventArgs args)
+ {
+ if (!_cfg.GetCVar(MedievalCCVars.GhostRevive))
+ return;
+ var session = args.SenderSession;
+ var userId = session.UserId;
- public override void Initialize()
+ if (!EntityQuery().TryFirstOrDefault(out var barrier))
{
- base.Initialize();
- SubscribeNetworkEvent(OnGhostReviveRequest);
- SubscribeNetworkEvent(OnReviveCountRequest);
+ _adminLog.Add(LogType.Action, LogImpact.Low, $"Игрок {session.Name} попытался возродиться, но барьер не найден");
+ return;
}
- private void OnGhostReviveRequest(GhostReviveRequestEvent msg, EntitySessionEventArgs args)
- {
- var revivesOn = _cfg.GetCVar(MedievalCCVars.GhostRevive);
- if (!revivesOn)
- return;
-
- var player = args.SenderSession;
- var playerUid = player.UserId;
- if (!EntityQuery().TryFirstOrDefault(out var barrier))
- {
- _adminlog.Add(LogType.Action, LogImpact.Low, $"Игрок {player.Name} попытался возродиться, но барьер не найден");
- return;
- }
-
- if (!barrier.ReviveCount.ContainsKey(playerUid))
- barrier.ReviveCount[playerUid] = 0;
-
- if (barrier.ReviveCount[playerUid] >= MaxRevives)
- {
- _adminlog.Add(LogType.Action, LogImpact.High, $"Игрок {player.Name} попытался возродиться, но у него уже {MaxRevives} возрождений");
- return;
- }
- if (!_minds.TryGetNetEntity(player.GetMind(), out var netEntity))
- {
- _adminlog.Add(LogType.Action, LogImpact.High, $"Разум {player.GetMind()} не имеет значения");
- return;
- }
- if (EntityManager.GetEntity(netEntity) == null)
- {
- _adminlog.Add(LogType.Action, LogImpact.High, $"Сущность {netEntity} не имеет значения");
- return;
- }
-
- var playerMind = EntityManager.GetEntity(netEntity);
-
- if (!playerMind.HasValue)
- {
- _adminlog.Add(LogType.Action, LogImpact.High, $"Разум {playerMind} не имеет значения");
- return;
- }
-
- var playerEntity = EntityManager.GetComponent(playerMind.Value).CurrentEntity;
+ if (!barrier.ReviveCount.TryGetValue(userId, out var reviveCount))
+ reviveCount = 0;
+ if (reviveCount >= MaxRevives)
+ {
+ _adminLog.Add(LogType.Action, LogImpact.High, $"Игрок {session.Name} превысил лимит возрождений ({MaxRevives})");
+ return;
+ }
- if (!HasComp(playerEntity))
- {
- _adminlog.Add(LogType.Action, LogImpact.High, $"Обнаружена подозрительная активность, разум {netEntity} в теле {playerEntity} пытался возродится, либо софт либо баг менюшки");
- return;
- }
+ if (!_minds.TryGetMind(userId, out _, out var oldMind))
+ {
+ _adminLog.Add(LogType.Action, LogImpact.High, $"Игрок {session.Name} не имеет разума");
+ return;
+ }
- var reviveQuery = EntityManager.EntityQuery();
+ var currentEntity = oldMind.CurrentEntity;
+ if (currentEntity == null || !HasComp(currentEntity))
+ {
+ _adminLog.Add(LogType.Action, LogImpact.High, $"Игрок {session.Name} попытался возродиться не находясь в состоянии призрака");
+ return;
+ }
- if (reviveQuery.Count() == 0)
- return;
+ var spawnerQuery = EntityQuery();
+ if (!spawnerQuery.Any())
+ return;
- var reviveList = reviveQuery.ToList();
+ var spawner = _random.Pick(spawnerQuery.ToList());
+ var spawnerCoords = _transform.GetMoverCoordinates(spawner.Owner);
+ var mob = Spawn(spawner.Prototype, spawnerCoords);
- _random.Shuffle(reviveList);
- var component = reviveList.ElementAt(0);
- var spawner = component.Owner;
+ _transform.AttachToGridOrMap(mob);
+ EnsureComp(mob);
- var mob = Spawn(component.Prototype, Transform(spawner).Coordinates);
- _transformSystem.AttachToGridOrMap(mob);
+ if (!oldMind.IsVisitingEntity)
+ _minds.WipeMind(session);
- EnsureComp(mob);
+ var newMind = _minds.CreateMind(userId, Comp(mob).EntityName);
- if (_minds.TryGetMind(player.UserId, out _, out var mind) && !mind.IsVisitingEntity)
- _minds.WipeMind(player);
+ _minds.SetUserId(newMind, userId);
+ _minds.TransferTo(newMind, mob);
- var newMind = _minds.CreateMind(player.UserId,
- Comp(mob).EntityName);
+ barrier.ReviveCount[userId] = reviveCount + 1;
+ }
- _minds.SetUserId(newMind, player.UserId);
- _minds.TransferTo(newMind, mob);
- barrier.ReviveCount[playerUid]++;
- }
+ private void OnReviveCountRequest(ReviveCountRequestEvent _, EntitySessionEventArgs args)
+ {
+ var session = args.SenderSession;
+ var userId = session.UserId;
- private void OnReviveCountRequest(ReviveCountRequestEvent msg, EntitySessionEventArgs args)
+ if (!EntityQuery().TryFirstOrDefault(out var barrier))
{
- var player = args.SenderSession;
- var playerUid = player.UserId;
- if (!EntityQuery().TryFirstOrDefault(out var barrier))
- {
- _adminlog.Add(LogType.Action,
- LogImpact.High,
- $"Player {player.Name} tried to revive but magic barrier was not found");
- return;
- }
-
- if (!barrier.ReviveCount.ContainsKey(playerUid))
- barrier.ReviveCount[playerUid] = 0;
-
- // Отправляем ответ
- RaiseNetworkEvent(new ReviveCountResponseEvent(barrier.ReviveCount[playerUid], MaxRevives), args.SenderSession);
+ _adminLog.Add(LogType.Action, LogImpact.High, $"Игрок {session.Name} запросил количество возрождений, но барьер не найден");
+ return;
}
+
+ if (!barrier.ReviveCount.TryGetValue(userId, out var reviveCount))
+ reviveCount = 0;
+
+ RaiseNetworkEvent(new ReviveCountResponseEvent(reviveCount, MaxRevives), session);
}
}
diff --git a/Content.Shared/Imperial/Medieval/ChargedAttack/ChargedAttackSystem.cs b/Content.Shared/Imperial/Medieval/ChargedAttack/ChargedAttackSystem.cs
index 524f2e5faf3..1111046ea09 100644
--- a/Content.Shared/Imperial/Medieval/ChargedAttack/ChargedAttackSystem.cs
+++ b/Content.Shared/Imperial/Medieval/ChargedAttack/ChargedAttackSystem.cs
@@ -4,11 +4,14 @@
using Content.Shared.Damage.Systems;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Humanoid;
+using Content.Shared.Hands;
+using Content.Shared.Hands.Components;
using Content.Shared.Interaction.Events;
using Content.Shared.Mobs.Systems;
using Content.Shared.Movement.Systems;
using Content.Shared.Weapons.Melee;
using Content.Shared.Weapons.Melee.Events;
+using Robust.Shared.Containers;
using Robust.Shared.Map;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Systems;
@@ -40,6 +43,41 @@ public override void Initialize()
SubscribeLocalEvent(OnHit);
SubscribeLocalEvent(OnStaminaHit);
+ SubscribeLocalEvent(OnDropped);
+ SubscribeLocalEvent(OnUnequipped);
+ SubscribeLocalEvent(OnInsertedIntoContainer);
+ }
+
+ private void OnDropped(EntityUid weapon, ChargedAttackComponent charged, DroppedEvent args)
+ {
+ if (!charged.CurrentAttacking)
+ return;
+
+ StopAttacking(weapon, charged, args.User);
+ }
+
+ private void OnUnequipped(EntityUid weapon, ChargedAttackComponent charged, GotUnequippedHandEvent args)
+ {
+ if (!charged.CurrentAttacking)
+ return;
+
+ StopAttacking(weapon, charged, args.User);
+ }
+
+ private void OnInsertedIntoContainer(EntityUid weapon, ChargedAttackComponent charged, EntInsertedIntoContainerMessage args)
+ {
+ if (!charged.CurrentAttacking)
+ return;
+
+ var user = args.Container.Owner;
+
+ if (TryComp(user, out var xform) && xform.ParentUid.IsValid())
+ {
+ if (HasComp(xform.ParentUid))
+ user = xform.ParentUid;
+ }
+
+ StopAttacking(weapon, charged, user);
}
private void OnHit(EntityUid weapon, ChargedAttackComponent charged, MeleeHitEvent args)
@@ -113,7 +151,9 @@ private void OnStart(ChargedAttackStart msg, EntitySessionEventArgs args)
return;
var weaponUid = GetEntity(msg.Weapon);
- if (!TryComp(weaponUid, out var charged)) return;
+ if (!TryComp(weaponUid, out var charged))
+ return;
+
charged.AttackStart = _timing.CurTime;
charged.CurrentAttacking = true;
Dirty(weaponUid, charged);
@@ -130,8 +170,12 @@ private void OnEnd(ChargedAttackEnd msg, EntitySessionEventArgs args)
var weaponUid = GetEntity(msg.Weapon);
var attackTime = msg.AttackTime;
- if (!TryComp(weaponUid, out var charged)) return;
- if (!TryComp(weaponUid, out var weapon)) return;
+ if (!TryComp(weaponUid, out var charged))
+ return;
+
+ if (!TryComp(weaponUid, out var weapon))
+ return;
+
ChargedAttack(user, coordinates, (weaponUid, weapon), charged, attackTime, args.SenderSession);
StopAttacking(weaponUid, charged, user);
}
diff --git a/Content.Shared/Imperial/Medieval/Cult/BloodSpellPrototype.cs b/Content.Shared/Imperial/Medieval/Cult/BloodSpellPrototype.cs
new file mode 100644
index 00000000000..12c6e781469
--- /dev/null
+++ b/Content.Shared/Imperial/Medieval/Cult/BloodSpellPrototype.cs
@@ -0,0 +1,51 @@
+using Robust.Shared.Prototypes;
+
+namespace Content.Shared.Imperial.Medieval.Cult;
+
+[Prototype]
+public sealed partial class BloodSpellPrototype : IPrototype
+{
+ [IdDataField]
+ public string ID { get; private set; } = default!;
+
+ [DataField(required: true)]
+ public List Incantation = new();
+
+ [DataField(required: true)]
+ public BloodSpellType SpellType = BloodSpellType.ItemUpgrade;
+
+ [DataField]
+ public string? RequiredMaterial;
+
+ [DataField]
+ public int RequiredMaterialCount = 5;
+
+ [DataField]
+ public EntProtoId? SpawnProto;
+
+ [DataField]
+ public EntProtoId? RequiredHeldItem;
+
+ [DataField]
+ public EntProtoId? ReplacementItem;
+
+ [DataField]
+ public string? EquipmentSlot;
+
+ [DataField]
+ public bool ReplaceEquipment;
+
+ [DataField("successMessage")]
+ public string? SuccessMessage;
+
+ [DataField]
+ public string? FailureMessage;
+}
+
+public enum BloodSpellType
+{
+ ItemUpgrade,
+ CraftItem,
+ CraftArmor,
+ DeathCurse,
+}
diff --git a/Resources/Locale/ru-RU/Imperial/Medieval/Cult/cult.ftl b/Resources/Locale/ru-RU/Imperial/Medieval/Cult/cult.ftl
new file mode 100644
index 00000000000..06c4fb1d87e
--- /dev/null
+++ b/Resources/Locale/ru-RU/Imperial/Medieval/Cult/cult.ftl
@@ -0,0 +1,12 @@
+cult-spell-too-fast = Ты ощущаешь, что слова были произнесены слишком поспешно и не напитались магией
+cult-spell-too-slow = Ты ощущаешь, что слова утратили силу, прежде чем завершилось заклинание
+cult-spell-incorrect = Ты ощущаешь искажение в произнесённых словах
+
+cult-spell-insufficient-materials = Недостаточно ресурсов для ритуала
+
+cult-spell-need-holy-scripture = Ты должен держать в руке святое писание
+cult-spell-wrong-item = В твоей руке должно быть святое писание, а не { $item }
+cult-spell-book-upgraded = Книга пропитывается силой крови
+
+cult-spell-death-curse-activated = Да падёт проклятие на того, кто поднимет на меня руку
+cult-spell-death-curse-already-active = Ты ощущаешь, что проклятие уже действует
diff --git a/Resources/Prototypes/Imperial/Medieval/Cult/blood_spells.yml b/Resources/Prototypes/Imperial/Medieval/Cult/blood_spells.yml
new file mode 100644
index 00000000000..a68ededc495
--- /dev/null
+++ b/Resources/Prototypes/Imperial/Medieval/Cult/blood_spells.yml
@@ -0,0 +1,85 @@
+- type: bloodSpell
+ id: SpellBookUpgrade
+ incantation:
+ - Ave
+ - The
+ - Truth
+ spellType: ItemUpgrade
+ requiredHeldItem: MedievalBookCultGuide
+ replacementItem: MedievalBookCultGuideUnlocked
+ successMessage: cult-spell-book-upgraded
+ failureMessage: cult-spell-need-holy-scripture
+
+- type: bloodSpell
+ id: SpellCraftArmorIron
+ incantation:
+ - Ave
+ - The
+ - Bronus
+ spellType: CraftArmor
+ requiredMaterial: BloodIron
+ requiredMaterialCount: 5
+ spawnProto: MedievalClothingOuterArmorCultUp
+ equipmentSlot: outerClothing
+ replaceEquipment: true
+ failureMessage: cult-spell-insufficient-materials
+
+- type: bloodSpell
+ id: SpellCraftSpear
+ incantation:
+ - Ave
+ - The
+ - Vilkus
+ spellType: CraftItem
+ requiredMaterial: BloodIron
+ requiredMaterialCount: 5
+ spawnProto: MedievalSpearCult
+ failureMessage: cult-spell-insufficient-materials
+
+- type: bloodSpell
+ id: SpellCraftYatagan
+ incantation:
+ - Ave
+ - The
+ - Knatus
+ spellType: CraftItem
+ requiredMaterial: BloodIron
+ requiredMaterialCount: 5
+ spawnProto: MedievalCultYatagan
+ failureMessage: cult-spell-insufficient-materials
+
+- type: bloodSpell
+ id: SpellCraftSekir
+ incantation:
+ - Ave
+ - The
+ - Sekir
+ spellType: CraftItem
+ requiredMaterial: BloodIron
+ requiredMaterialCount: 5
+ spawnProto: MedievalIronSekirCult
+ failureMessage: cult-spell-insufficient-materials
+
+- type: bloodSpell
+ id: SpellCraftArmorMana
+ incantation:
+ - Ave
+ - The
+ - Magical
+ spellType: CraftArmor
+ requiredMaterial: BloodLeather
+ requiredMaterialCount: 5
+ spawnProto: MedievalClothingOuterArmorCultMana
+ equipmentSlot: outerClothing
+ replaceEquipment: true
+ failureMessage: cult-spell-insufficient-materials
+
+- type: bloodSpell
+ id: SpellDeathCurse
+ incantation:
+ - Katariemai
+ - Opoion
+ - Me chtypisei
+ spellType: DeathCurse
+ successMessage: cult-spell-death-curse-activated
+ failureMessage: cult-spell-death-curse-already-active
diff --git a/Resources/Prototypes/Imperial/Medieval/cult.yml b/Resources/Prototypes/Imperial/Medieval/Cult/cult.yml
similarity index 99%
rename from Resources/Prototypes/Imperial/Medieval/cult.yml
rename to Resources/Prototypes/Imperial/Medieval/Cult/cult.yml
index ff1154fd092..1fdc082d939 100644
--- a/Resources/Prototypes/Imperial/Medieval/cult.yml
+++ b/Resources/Prototypes/Imperial/Medieval/Cult/cult.yml
@@ -423,7 +423,7 @@
- type: entity
parent: BaseItem
name: книга ритуалов культа истины
- id: MedievalBookCultGuide2
+ id: MedievalBookCultGuideUnlocked
components:
- type: Sprite
sprite: Imperial/Medieval/Misc/cult.rsi
diff --git a/Resources/Prototypes/Imperial/Medieval/decor.yml b/Resources/Prototypes/Imperial/Medieval/decor.yml
index 9dab0528e5e..468d104fce3 100644
--- a/Resources/Prototypes/Imperial/Medieval/decor.yml
+++ b/Resources/Prototypes/Imperial/Medieval/decor.yml
@@ -3889,7 +3889,6 @@
color: red
castShadows: false
-
- type: entity
id: MedievalFlagCaptureBlueGold
parent: BaseStructure
@@ -3897,7 +3896,7 @@
description: A banner displaying the Nanotrasen logo. It looks rather cheap.
components:
- type: Sprite
- drawdepth: Overdoors
+ drawdepth: 3
sprite: Imperial/Medieval/Decor/medieval_banner.rsi
state: banner_blul_gold
- type: MedievalFactionFlagChecker
@@ -3918,20 +3917,6 @@
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- - type: Fixtures
- fixtures:
- fix1:
- shape:
- !type:PhysShapeCircle
- radius: 0.45
- density: 190
- mask:
- - MachineMask
- layer:
- - Opaque
- - MidImpassable
- - HighImpassable
- - BulletImpassable
- type: entity
id: MedievalFlagCaptureRedGold
@@ -3940,7 +3925,7 @@
description: A banner displaying the Nanotrasen logo. It looks rather cheap.
components:
- type: Sprite
- drawdepth: Overdoors
+ drawdepth: 3
sprite: Imperial/Medieval/Decor/medieval_banner.rsi
state: banner_red_gold
- type: MedievalFactionFlagChecker
@@ -3968,13 +3953,6 @@
!type:PhysShapeCircle
radius: 0.45
density: 190
- mask:
- - MachineMask
- layer:
- - Opaque
- - MidImpassable
- - HighImpassable
- - BulletImpassable
- type: entity
id: MedievalDecorPerekatiPole