Обнова культа крови (#128)

* stable

* sprite

* yes!

* LOCATOR TRANSLATION MISSING

* finally

* stable2

* stable

* stable?

* FIS

* Nerfs

* works

* Трек болгарыча и время призыва теперь 3 минуты

* f

* Update modifier_sets.yml

* Барьер больше не даёт 5 рун металла, ибо почему он должен?
This commit is contained in:
A-Mironov 2025-11-30 01:06:35 +03:00 committed by GitHub
parent 7a977ad62c
commit abf39617af
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
41 changed files with 727 additions and 27 deletions

View file

@ -0,0 +1,60 @@
using Content.Shared._Sunrise.Biocode.Systems;
using Content.Shared.Pinpointer;
using Content.Server.Popups;
using Content.Server.Pinpointer;
namespace Content.Server._Sunrise.Biocode.Systems;
/// <summary>
/// Server-side implementation of biocode deactivation system.
/// </summary>
public sealed class ServerBiocodeDeactivationSystem : BiocodeDeactivationSystem
{
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly PinpointerSystem _pinpointerSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
private static readonly ISawmill Sawmill = Logger.GetSawmill("biocode.deactivation");
protected override void ShowAlert(EntityUid user, string alertText)
{
Sawmill.Info($"Showing alert '{alertText}' to user {user}");
_popup.PopupEntity(Loc.GetString(alertText), user, user);
}
protected override void DeactivateItem(EntityUid uid)
{
Sawmill.Info($"Attempting to deactivate item {uid}");
// Handle pinpointer deactivation using the proper system method
if (TryComp<PinpointerComponent>(uid, out var pinpointer))
{
Sawmill.Info($"Pinpointer {uid} current state: IsActive={pinpointer.IsActive}");
// Always ensure the pinpointer is deactivated
_pinpointerSystem.SetActive(uid, false, pinpointer);
// Force update appearance to ensure visual state is correct
if (TryComp<AppearanceComponent>(uid, out var appearance))
{
Sawmill.Info($"Force updating appearance for pinpointer {uid}");
_appearance.SetData(uid, PinpointerVisuals.IsActive, false, appearance);
_appearance.SetData(uid, PinpointerVisuals.TargetDistance, Distance.Unknown, appearance);
}
else
{
Sawmill.Info($"No appearance component found for pinpointer {uid}");
}
}
else
{
Sawmill.Info($"Item {uid} is not a pinpointer");
}
// Add other item types here as needed
// Example: if (TryComp<SomeOtherComponent>(uid, out var otherComponent))
// {
// _someOtherSystem.Deactivate(uid, otherComponent);
// }
}
}

View file

@ -1,6 +0,0 @@
namespace Content.Server._Sunrise.BloodCult;
[RegisterComponent]
public sealed partial class BloodCultTargetComponent : Component
{
}

View file

@ -0,0 +1,61 @@
using Content.Server._Sunrise.BloodCult.GameRule;
using Content.Server.Administration;
using Content.Shared.Administration;
using Robust.Shared.Console;
using Robust.Server.Player;
namespace Content.Server._Sunrise.BloodCult.Commands;
[AdminCommand(AdminFlags.Admin)]
public sealed class AddCultTargetCommand : IConsoleCommand
{
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
public string Command => "bloodcult_addtarget";
public string Description => Loc.GetString("bloodcult-addtarget-description");
public string Help => Loc.GetString("bloodcult-addtarget-help");
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length != 1)
{
shell.WriteError(Loc.GetString("bloodcult-addtarget-usage"));
return;
}
var ckey = args[0];
if (!_playerManager.TryGetSessionByUsername(ckey, out var session) || session.AttachedEntity == null)
{
shell.WriteError(Loc.GetString("bloodcult-addtarget-player-not-found", ("ckey", ckey)));
return;
}
var entityUid = session.AttachedEntity.Value;
if (!_entManager.EntitySysManager.TryGetEntitySystem<BloodCultRuleSystem>(out var cultRuleSystem))
{
shell.WriteError(Loc.GetString("bloodcult-addtarget-system-not-found"));
return;
}
var rule = cultRuleSystem.GetRule();
if (rule == null)
{
shell.WriteError(Loc.GetString("bloodcult-addtarget-rule-not-found"));
return;
}
// Use the system method to add target properly
if (!cultRuleSystem.AddSpecificCultTarget(entityUid, rule))
{
shell.WriteError(Loc.GetString("bloodcult-addtarget-already-target"));
return;
}
var targetName = _entManager.TryGetComponent<MetaDataComponent>(entityUid, out var meta)
? meta.EntityName
: Loc.GetString("bloodcult-unknown-entity");
shell.WriteLine(Loc.GetString("bloodcult-addtarget-success", ("name", targetName)));
}
}

View file

@ -0,0 +1,42 @@
using Content.Server._Sunrise.BloodCult.GameRule;
using Content.Server.Administration;
using Content.Shared.Administration;
using Robust.Shared.Console;
namespace Content.Server._Sunrise.BloodCult.Commands;
[AdminCommand(AdminFlags.Admin)]
public sealed class ListCultTargetsCommand : IConsoleCommand
{
[Dependency] private readonly IEntityManager _entManager = default!;
public string Command => "bloodcult_listtargets";
public string Description => Loc.GetString("bloodcult-listtargets-description");
public string Help => Loc.GetString("bloodcult-listtargets-help");
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (!_entManager.EntitySysManager.TryGetEntitySystem<BloodCultRuleSystem>(out var cultRuleSystem))
{
shell.WriteError(Loc.GetString("bloodcult-listtargets-system-not-found"));
return;
}
var rule = cultRuleSystem.GetRule();
if (rule?.CultTargets == null || rule.CultTargets.Count == 0)
{
shell.WriteLine(Loc.GetString("bloodcult-listtargets-no-targets"));
return;
}
shell.WriteLine(Loc.GetString("bloodcult-listtargets-header", ("count", rule.CultTargets.Count)));
foreach (var (target, isSacrificed) in rule.CultTargets)
{
var targetName = _entManager.TryGetComponent<MetaDataComponent>(target, out var meta)
? meta.EntityName
: Loc.GetString("bloodcult-unknown-entity");
var status = isSacrificed ? Loc.GetString("bloodcult-listtargets-sacrificed") : Loc.GetString("bloodcult-listtargets-alive");
shell.WriteLine(Loc.GetString("bloodcult-listtargets-target", ("name", targetName), ("uid", target), ("status", status)));
}
}
}

View file

@ -0,0 +1,61 @@
using Content.Server._Sunrise.BloodCult.GameRule;
using Content.Server.Administration;
using Content.Shared.Administration;
using Robust.Shared.Console;
using Robust.Server.Player;
namespace Content.Server._Sunrise.BloodCult.Commands;
[AdminCommand(AdminFlags.Admin)]
public sealed class RemoveCultTargetCommand : IConsoleCommand
{
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
public string Command => "bloodcult_removetarget";
public string Description => Loc.GetString("bloodcult-removetarget-description");
public string Help => Loc.GetString("bloodcult-removetarget-help");
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length != 1)
{
shell.WriteError(Loc.GetString("bloodcult-removetarget-usage"));
return;
}
var ckey = args[0];
if (!_playerManager.TryGetSessionByUsername(ckey, out var session) || session.AttachedEntity == null)
{
shell.WriteError(Loc.GetString("bloodcult-removetarget-player-not-found", ("ckey", ckey)));
return;
}
var entityUid = session.AttachedEntity.Value;
if (!_entManager.EntitySysManager.TryGetEntitySystem<BloodCultRuleSystem>(out var cultRuleSystem))
{
shell.WriteError(Loc.GetString("bloodcult-removetarget-system-not-found"));
return;
}
var rule = cultRuleSystem.GetRule();
if (rule == null)
{
shell.WriteError(Loc.GetString("bloodcult-removetarget-rule-not-found"));
return;
}
// Use the system method to remove target properly
if (!cultRuleSystem.RemoveSpecificCultTarget(entityUid, rule))
{
shell.WriteError(Loc.GetString("bloodcult-removetarget-not-target"));
return;
}
var targetName = _entManager.TryGetComponent<MetaDataComponent>(entityUid, out var meta)
? meta.EntityName
: Loc.GetString("bloodcult-unknown-entity");
shell.WriteLine(Loc.GetString("bloodcult-removetarget-success", ("name", targetName)));
}
}

View file

@ -142,6 +142,45 @@ public sealed class BloodCultRuleSystem : GameRuleSystem<BloodCultRuleComponent>
}
}
/// <summary>
/// Manually add a specific entity as a cult target.
/// </summary>
public bool AddSpecificCultTarget(EntityUid target, BloodCultRuleComponent rule)
{
if (!Exists(target) || rule.CultTargets.ContainsKey(target))
return false;
rule.CultTargets.Add(target, false);
EnsureComp<BloodCultTargetComponent>(target);
var query = EntityQueryEnumerator<KillCultistTargetsConditionComponent>();
while (query.MoveNext(out var uid, out var killCultistTargetsComponent))
{
_cultistTargetsConditionSystem.RefresTitle(uid, rule.CultTargets, killCultistTargetsComponent);
}
return true;
}
/// <summary>
/// Manually remove a specific entity as a cult target.
/// </summary>
public bool RemoveSpecificCultTarget(EntityUid target, BloodCultRuleComponent rule)
{
if (!rule.CultTargets.ContainsKey(target))
return false;
rule.CultTargets.Remove(target);
if (Exists(target))
RemComp<BloodCultTargetComponent>(target);
var query = EntityQueryEnumerator<KillCultistTargetsConditionComponent>();
while (query.MoveNext(out var uid, out var killCultistTargetsComponent))
{
_cultistTargetsConditionSystem.RefresTitle(uid, rule.CultTargets, killCultistTargetsComponent);
}
return true;
}
protected override void Added(EntityUid uid,
BloodCultRuleComponent component,
GameRuleComponent gameRule,

View file

@ -778,7 +778,7 @@ namespace Content.Server._Sunrise.BloodCult.Runes.Systems
var ev = new SummonNarsieDoAfterEvent();
var argsDoAfterEvent = new DoAfterArgs(_entityManager, user, TimeSpan.FromSeconds(60), ev, user)
var argsDoAfterEvent = new DoAfterArgs(_entityManager, user, TimeSpan.FromSeconds(170), ev, user) //fish-edit
{
BreakOnMove = true
};
@ -798,7 +798,7 @@ namespace Content.Server._Sunrise.BloodCult.Runes.Systems
var stream = _audio.PlayGlobal(_narsie40Sec,
Filter.Broadcast(),
false,
AudioParams.Default.WithLoop(true).WithVolume(0.15f));
AudioParams.Default.WithLoop(false).WithVolume(0.1f)); //fish-edit
_playingStream = stream?.Entity;

View file

@ -119,7 +119,7 @@ namespace Content.Server._Sunrise.BloodCult.Runes.Systems
private readonly SoundPathSpecifier _teleportOutSound = new("/Audio/_Sunrise/BloodCult/veilout.ogg");
private readonly SoundPathSpecifier _apocRuneEndDrawing = new("/Audio/_Sunrise/BloodCult/finisheddraw.ogg");
private readonly SoundPathSpecifier _apocRuneStartDrawing = new("/Audio/_Sunrise/BloodCult/startdraw.ogg");
private readonly SoundPathSpecifier _narsie40Sec = new("/Audio/_Sunrise/BloodCult/40sec.ogg");
private readonly SoundPathSpecifier _narsie40Sec = new("/Audio/_Sunrise/BloodCult/Tear-of-veil(bolgarich).ogg"); //slava Bolgarich https://www.youtube.com/watch?v=NqNHKfTAvcw&list=LL&index=1
private readonly SoundPathSpecifier _magic = new("/Audio/_Sunrise/BloodCult/magic.ogg");
private bool _doAfterAlreadyStarted;

View file

@ -67,7 +67,7 @@ public abstract class SharedPinpointerSystem : EntitySystem
private void OnExamined(EntityUid uid, PinpointerComponent component, ExaminedEvent args)
{
if (!args.IsInDetailsRange || component.TargetName == null)
if (!args.IsInDetailsRange || component.TargetName == null || !component.IsActive)
return;
args.PushMarkup(Loc.GetString("examine-pinpointer-linked", ("target", component.TargetName)));

View file

@ -0,0 +1,29 @@
using Robust.Shared.GameStates;
namespace Content.Shared._Sunrise.Biocode.Components;
/// <summary>
/// Component that automatically deactivates items when they're not in the possession of authorized users.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class BiocodeDeactivationComponent : Component
{
/// <summary>
/// Whether the item should be deactivated when removed from authorized user's possession.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public bool DeactivateOnRemoval = true;
/// <summary>
/// Whether the item should be deactivated when placed in unauthorized user's possession.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public bool DeactivateOnUnauthorized = true;
/// <summary>
/// Alert text to show when unauthorized user tries to use the item.
/// If null, uses the BiocodeComponent's alert text.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public string? AlertText;
}

View file

@ -0,0 +1,136 @@
using Content.Shared._Sunrise.Biocode.Components;
using Content.Shared.Containers;
using Content.Shared.Hands.Components;
using Content.Shared.Inventory;
using Content.Shared.Storage.Components;
using Content.Shared.Interaction;
using Content.Shared.Interaction.Events;
using Content.Shared.Storage;
using Content.Shared.Hands;
using Content.Shared.Inventory.Events;
using Robust.Shared.Containers;
namespace Content.Shared._Sunrise.Biocode.Systems;
/// <summary>
/// System that handles automatic deactivation of biocoded items when they're not in authorized user's possession.
/// </summary>
public abstract class BiocodeDeactivationSystem : EntitySystem
{
[Dependency] private readonly BiocodeSystem _biocodeSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<BiocodeDeactivationComponent, ActivateInWorldEvent>(OnActivate);
SubscribeLocalEvent<BiocodeDeactivationComponent, UseInHandEvent>(OnUseInHand);
SubscribeLocalEvent<BiocodeDeactivationComponent, DroppedEvent>(OnItemDropped);
SubscribeLocalEvent<BiocodeDeactivationComponent, GotEquippedEvent>(OnItemPickedUp);
}
private void OnItemDropped(EntityUid uid, BiocodeDeactivationComponent component, DroppedEvent args)
{
if (!component.DeactivateOnRemoval)
return;
// Check if this item has biocode
if (!TryComp<BiocodeComponent>(uid, out var biocodeComponent))
return;
// Item was dropped, deactivate it
DeactivateItem(uid);
}
private void OnItemPickedUp(EntityUid uid, BiocodeDeactivationComponent component, GotEquippedEvent args)
{
if (!component.DeactivateOnUnauthorized)
return;
// Check if this item has biocode
if (!TryComp<BiocodeComponent>(uid, out var biocodeComponent))
return;
// Check if the picker is authorized
if (_biocodeSystem.CanUse(args.Equipee, biocodeComponent.Factions))
return;
// Picker is not authorized, deactivate the item
DeactivateItem(uid);
}
private void OnActivate(EntityUid uid, BiocodeDeactivationComponent component, ActivateInWorldEvent args)
{
if (args.Handled || !args.Complex)
return;
// Check if this item has biocode
if (!TryComp<BiocodeComponent>(uid, out var biocodeComponent))
return;
// Check if user is authorized
if (_biocodeSystem.CanUse(args.User, biocodeComponent.Factions))
return;
// User is not authorized, show alert and prevent activation
var alertText = component.AlertText ?? biocodeComponent.AlertText;
ShowAlert(args.User, alertText);
args.Handled = true;
}
private void OnUseInHand(EntityUid uid, BiocodeDeactivationComponent component, UseInHandEvent args)
{
if (args.Handled)
return;
// Check if this item has biocode
if (!TryComp<BiocodeComponent>(uid, out var biocodeComponent))
return;
// Check if user is authorized
if (_biocodeSystem.CanUse(args.User, biocodeComponent.Factions))
return;
// User is not authorized, show alert and prevent use
var alertText = component.AlertText ?? biocodeComponent.AlertText;
ShowAlert(args.User, alertText);
args.Handled = true;
}
/// <summary>
/// Shows an alert to the user. Override this method to implement specific alert display logic.
/// </summary>
protected abstract void ShowAlert(EntityUid user, string alertText);
/// <summary>
/// Deactivates the item. Override this method in the shared system to implement specific deactivation logic.
/// </summary>
protected abstract void DeactivateItem(EntityUid uid);
private EntityUid? GetContainerOwner(EntityUid container)
{
// Try to find the owner through various container types
if (TryComp<HandsComponent>(container, out _))
{
return container;
}
if (TryComp<InventoryComponent>(container, out _))
{
return container;
}
if (TryComp<StorageComponent>(container, out _))
{
return container;
}
// Check if this container is inside another entity
var parent = Transform(container).ParentUid;
if (parent != EntityUid.Invalid)
{
return GetContainerOwner(parent);
}
return null;
}
}

View file

@ -0,0 +1,11 @@
using Robust.Shared.GameStates;
namespace Content.Shared._Sunrise.BloodCult.Components;
/// <summary>
/// Component that marks an entity as a target for the Blood cult.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class BloodCultTargetComponent : Component
{
}

View file

@ -0,0 +1,2 @@
ent-BloodCultPinpointer = Blood Locator
.desc = A sinister looking pinpointer with a strange crystal lodged into it. It points towards cult targets. Only cultists know about this device and how to use it, for others it's a strange piece of junk.

View file

@ -0,0 +1,36 @@
# Blood Cult Console Commands
# Add Target Command
bloodcult-addtarget-description = Add target for Blood Cult
bloodcult-addtarget-help = Adds a specific player as a target for the Blood Cult. The player will be marked for tracking and potential sacrifice.
bloodcult-addtarget-usage = Usage: bloodcult_addtarget <ckey>
bloodcult-addtarget-player-not-found = Player with ckey '{ $ckey }' not found or not in game.
bloodcult-addtarget-system-not-found = Blood Cult system not found.
bloodcult-addtarget-rule-not-found = No active Blood Cult rule found.
bloodcult-addtarget-already-target = Entity is already a cult target.
bloodcult-addtarget-success = Successfully added { $name } as a cult target.
# Remove Target Command
bloodcult-removetarget-description = Remove target for Blood Cult
bloodcult-removetarget-help = Removes a specific player from the Blood Cult target list. The player will no longer be tracked or marked for sacrifice.
bloodcult-removetarget-usage = Usage: bloodcult_removetarget <ckey>
bloodcult-removetarget-player-not-found = Player with ckey '{ $ckey }' not found or not in game.
bloodcult-removetarget-system-not-found = Blood Cult system not found.
bloodcult-removetarget-rule-not-found = No active Blood Cult rule found.
bloodcult-removetarget-not-target = Entity is not a cult target.
bloodcult-removetarget-success = Successfully removed { $name } as a cult target.
# List Targets Command
bloodcult-listtargets-description = Show all current Blood Cult targets
bloodcult-listtargets-help = Displays all current Blood Cult targets with their status (alive or sacrificed) and entity information.
bloodcult-listtargets-usage = Usage: bloodcult_listtargets
bloodcult-listtargets-system-not-found = Blood Cult system not found.
bloodcult-listtargets-no-targets = No cult targets found.
bloodcult-listtargets-header = Current cult targets ({ $count }):
bloodcult-listtargets-sacrificed = Sacrificed
bloodcult-listtargets-alive = Alive
bloodcult-listtargets-target = { $name } ({ $uid }) - { $status }
bloodcult-unknown-entity = Unknown Entity
# Cult Device Alert
bloodcult-biocode-alert = The device pulses with dark energy, rejecting your touch. Only those bound by blood may wield its power.

View file

@ -0,0 +1,11 @@
#Sunrise-start
pinpointer-cult-target = cult target
pinpointer-cult-no-target = No cult targets found
pinpointer-cult-target-name = { $name } ({ $status })
pinpointer-cult-target-alive = Alive
pinpointer-cult-target-sacrificed = Sacrificed
# Blood Locator
blood-locator-name = Blood Locator
blood-locator-description = A sinister looking pinpointer with a strange crystal lodged into it. It points towards cult targets. Only cultists know about this device and how to use it, for others it's a strange piece of junk.
#Sunrise-End

View file

@ -0,0 +1,2 @@
ent-BloodCultPinpointer = Кровеуказатель
.desc = Зловещий указатель со странным кристаллом, встроенным в него. Он указывает на цели культа. Только культисты знают об этом устройстве и как его использовать, для остальных это странный хлам.

View file

@ -32,7 +32,7 @@ cult-narsie-summon-not-enough = Необходимо минимум { $count }
cult-narsie-already-summoning = Кто-то уже призывает бога.
cult-narsie-summon-do-after = Вы уже чем-то заняты.
cult-stay-still = Вам нужно стоять на месте!
cult-ritual-started = Культисты приступили к ритуалу! У вас меньше минуты, чтобы предотвратить вторжение.
cult-ritual-started = Культисты приступили к ритуалу! У вас меньше трёх минут, чтобы предотвратить вторжение.
cult-ritual-prevented = Ритуал был прерван.
cult-narsie-summoned = Понял, вычеркиваю...
cult-revive-rune-already-alive = Он уже живой.
@ -54,4 +54,4 @@ objective-condition-cult-kill-title =
summon-button-label = { $label } ({ $mobState }; { $distance } м)
teleport-button-label = { $label } ({ $distance } м)
revived-cultist-desc = Культист крови, душа которого сгинула в вечном мраке.
tile-has-rune = На этом тайле уже есть руна!
tile-has-rune = На этом тайле уже есть руна!

View file

@ -0,0 +1,40 @@
# Blood Cult Console Commands
# Add Target Command
bloodcult-addtarget-description = Добавить цель для Культа Крови
bloodcult-addtarget-help = Добавляет конкретного игрока как цель Культа Крови для отслеживания и потенциального жертвоприношения.
bloodcult-addtarget-usage = Использование: bloodcult_addtarget <ckey>
bloodcult-addtarget-player-not-found = Игрок с ckey '{ $ckey }' не найден или не в игре.
bloodcult-addtarget-system-not-found = Система Культа Крови не найдена.
bloodcult-addtarget-rule-not-found = Активное правило Культа Крови не найдено.
bloodcult-addtarget-already-target = Сущность уже является целью культа.
bloodcult-addtarget-success = Цель культа { $name } успешно добавлена.
# Remove Target Command
bloodcult-removetarget-description = Удалить цель для Культа Крови
bloodcult-removetarget-help = Удаляет конкретного игрока из списка целей Культа Крови, прекращая отслеживание и отметку для жертвоприношения.
bloodcult-removetarget-usage = Использование: bloodcult_removetarget <ckey>
bloodcult-removetarget-player-not-found = Игрок с ckey '{ $ckey }' не найден или не в игре.
bloodcult-removetarget-system-not-found = Система Культа Крови не найдена.
bloodcult-removetarget-rule-not-found = Активное правило Культа Крови не найдено.
bloodcult-removetarget-not-target = Сущность не является целью культа.
bloodcult-removetarget-success = Цель культа { $name } успешно удалена.
# List Targets Command
bloodcult-listtargets-description = Показать все текущие цели Культа Крови
bloodcult-listtargets-help = Отображает все текущие цели Культа Крови с их статусом (жив или принесен в жертву) и информацией о сущности.
bloodcult-listtargets-usage = Использование: bloodcult_listtargets
bloodcult-listtargets-system-not-found = Система Культа Крови не найдена.
bloodcult-listtargets-no-targets = Цели культа не найдены.
bloodcult-listtargets-header = { $count ->
[1] Текущая цель культа ({ $count }):
[few] Текущие цели культа ({ $count }):
*[other] Текущие цели культа ({ $count }):
}
bloodcult-listtargets-sacrificed = Принесен в жертву
bloodcult-listtargets-alive = Жив
bloodcult-listtargets-target = { $name } ({ $uid }) - { $status }
bloodcult-unknown-entity = Неизвестная сущность
# Cult Device Alert
bloodcult-biocode-alert = Устройство пульсирует тёмной энергией, отвергая ваше прикосновение. Только те, кто связан кровью, могут владеть его силой.

View file

@ -0,0 +1,9 @@
pinpointer-cult-target = цель культа
pinpointer-cult-no-target = Цели культа не найдены
pinpointer-cult-target-name = { $name } ({ $status })
pinpointer-cult-target-alive = Жив
pinpointer-cult-target-sacrificed = Принесен в жертву
# Blood Locator
blood-locator-name = Кровеуказатель
blood-locator-description = Зловещий указатель со странным кристаллом, встроенным в него. Он указывает на цели культа. Только культисты знают об этом устройстве и как его использовать, для остальных это странный хлам.

View file

@ -50,13 +50,13 @@
max: 2
- type: Appearance
- type: Pylon
healingAuraDamage:
healingAuraDamage: #Fish-edit, healing halved
groups:
Brute: -10
Burn: -10
Toxin: -6
Brute: -5
Burn: -5
Toxin: -3
Genetic: -5
Airloss: -20
Airloss: -10
burnDamageOnInteract:
groups:
Burn: 5

View file

@ -36,12 +36,12 @@
- trigger:
!type:DamageTrigger
damage: 300
behaviors:
- !type:SpawnEntitiesBehavior
spawn:
CultRunicMetal:
min: 5
max: 5
behaviors: # Fish-edit
#- !type:SpawnEntitiesBehavior
# spawn:
# CultRunicMetal:
# min: 5
# max: 5
- !type:PlaySoundBehavior
sound:
collection: MetalBreak

View file

@ -220,6 +220,8 @@
types:
Structural: 100
Blunt: 25
soundHit:
collection: MetalThud
- type: MultiHandedItem
- type: Clothing
quickEquip: false

View file

@ -0,0 +1,45 @@
- type: entity
name: ent-BloodCultPinpointer
description: ent-BloodCultPinpointer-desc
id: BloodCultPinpointer
parent: PinpointerBase
components:
- type: Sprite
sprite: _Sunrise/BloodCult/pinpointer.rsi
layers:
- state: pinpointer_bloodcult
map: ["enum.PinpointerLayers.Base"]
- state: pinonnull
map: ["enum.PinpointerLayers.Screen"]
shader: unshaded
visible: false
- type: Item
inhandVisuals:
left:
- state: inhand-left-base
color: "#8b0000"
- state: inhand-left-stripe
color: "#8b0000"
- state: inhand-left-top
right:
- state: inhand-right-base
color: "#8b0000"
- state: inhand-right-stripe
color: "#8b0000"
- state: inhand-right-top
- type: Icon
sprite: _Sunrise/BloodCult/pinpointer.rsi
state: pinpointer_bloodcult
- type: Pinpointer
component: BloodCultTarget
targetName: cult target
updateTargetName: true
canRetarget: false
- type: Biocode
factions:
- BloodCult
alertText: bloodcult-biocode-alert
- type: BiocodeDeactivation
deactivateOnRemoval: true
deactivateOnUnauthorized: true
alertText: bloodcult-biocode-alert

View file

@ -71,6 +71,9 @@
name: juggernaut
description: big and scary
components:
- type: Damageable
damageContainer: Biological
damageModifierSet: BloodCultJuggernautModifierSet
- type: Fixtures
fixtures:
fix1:
@ -89,7 +92,7 @@
300: Dead
- type: MovementSpeedModifier
baseWalkSpeed: 1
baseSprintSpeed: 2
baseSprintSpeed: 2.5 #Fish-edit
- type: Construct
actions: [JuggernautCreateWall]
- type: Hands
@ -141,7 +144,7 @@
components:
- type: MovementSpeedModifier
baseWalkSpeed: 3.0
baseSprintSpeed: 3.0
baseSprintSpeed: 4.0
- type: MobThresholds
thresholds:
0: Alive
@ -162,7 +165,7 @@
damage:
types:
Blunt: 10
Slash: 10
Slash: 20 #Fish-edit
- type: entity
id: ReaperConstruct

View file

@ -8,6 +8,7 @@
startingItems:
- NarsieRitualDagger
- CultRunicMetal10
- BloodCultPinpointer
- type: bloodCult
id: NarbeeCult
@ -19,6 +20,7 @@
startingItems:
- NarbeeRitualDagger
- CultRunicMetal10
- BloodCultPinpointer
- type: bloodCult
id: ReaperCult
@ -30,3 +32,4 @@
startingItems:
- ReaperRitualDagger
- CultRunicMetal10
- BloodCultPinpointer

View file

@ -0,0 +1,6 @@
- type: damageModifierSet
id: BloodCultJuggernautModifierSet
coefficients:
Slash: 0.5
Piercing: 0.5
Heat: 2

View file

@ -31,4 +31,4 @@
factions:
- Syndicate
- type: StaticPrice
price: 900
price: 1000

View file

@ -0,0 +1,108 @@
{
"version": 1,
"size": {
"x": 32,
"y": 32
},
"license": "CC-BY-SA-3.0",
"copyright": "© 2025 Alexnov33x",
"states": [
{
"name": "pinonalert",
"directions": 8
},
{
"name": "pinonalertdirect",
"delays": [
[
0.2,
0.2
]
]
},
{
"name": "pinonalertnull"
},
{
"name": "pinonclose",
"delays": [
[
0.2,
0.2
]
]
},
{
"name": "pinondirect",
"delays": [
[
0.2,
0.2
]
]
},
{
"name": "pinondirectlarge",
"delays": [
[
0.2,
0.2
]
]
},
{
"name": "pinondirectsmall",
"delays": [
[
0.2,
0.2
]
]
},
{
"name": "pinondirectxtrlarge",
"delays": [
[
0.2,
0.2
]
]
},
{
"name": "pinonfar",
"delays": [
[
0.6,
0.2
]
]
},
{
"name": "pinonmedium",
"delays": [
[
0.4,
0.2
]
]
},
{
"name": "pinonnull"
},
{
"name": "pinpointer_bloodcult",
"delays": [
[
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2
]
]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB