diff --git a/Content.Server/_Sunrise/Biocode/Systems/BiocodeDeactivationSystem.cs b/Content.Server/_Sunrise/Biocode/Systems/BiocodeDeactivationSystem.cs
new file mode 100644
index 0000000000..f6f8a701d7
--- /dev/null
+++ b/Content.Server/_Sunrise/Biocode/Systems/BiocodeDeactivationSystem.cs
@@ -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;
+
+///
+/// Server-side implementation of biocode deactivation system.
+///
+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(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(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(uid, out var otherComponent))
+ // {
+ // _someOtherSystem.Deactivate(uid, otherComponent);
+ // }
+ }
+}
diff --git a/Content.Server/_Sunrise/BloodCult/BloodCultTargetComponent.cs b/Content.Server/_Sunrise/BloodCult/BloodCultTargetComponent.cs
deleted file mode 100644
index 024df13779..0000000000
--- a/Content.Server/_Sunrise/BloodCult/BloodCultTargetComponent.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Content.Server._Sunrise.BloodCult;
-
-[RegisterComponent]
-public sealed partial class BloodCultTargetComponent : Component
-{
-}
diff --git a/Content.Server/_Sunrise/BloodCult/Commands/AddCultTargetCommand.cs b/Content.Server/_Sunrise/BloodCult/Commands/AddCultTargetCommand.cs
new file mode 100644
index 0000000000..82990b0acd
--- /dev/null
+++ b/Content.Server/_Sunrise/BloodCult/Commands/AddCultTargetCommand.cs
@@ -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(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(entityUid, out var meta)
+ ? meta.EntityName
+ : Loc.GetString("bloodcult-unknown-entity");
+ shell.WriteLine(Loc.GetString("bloodcult-addtarget-success", ("name", targetName)));
+ }
+}
diff --git a/Content.Server/_Sunrise/BloodCult/Commands/ListCultTargetsCommand.cs b/Content.Server/_Sunrise/BloodCult/Commands/ListCultTargetsCommand.cs
new file mode 100644
index 0000000000..388e910086
--- /dev/null
+++ b/Content.Server/_Sunrise/BloodCult/Commands/ListCultTargetsCommand.cs
@@ -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(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(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)));
+ }
+ }
+}
diff --git a/Content.Server/_Sunrise/BloodCult/Commands/RemoveCultTargetCommand.cs b/Content.Server/_Sunrise/BloodCult/Commands/RemoveCultTargetCommand.cs
new file mode 100644
index 0000000000..03ab1bdaf1
--- /dev/null
+++ b/Content.Server/_Sunrise/BloodCult/Commands/RemoveCultTargetCommand.cs
@@ -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(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(entityUid, out var meta)
+ ? meta.EntityName
+ : Loc.GetString("bloodcult-unknown-entity");
+ shell.WriteLine(Loc.GetString("bloodcult-removetarget-success", ("name", targetName)));
+ }
+}
diff --git a/Content.Server/_Sunrise/BloodCult/GameRule/BloodCultRuleSystem.cs b/Content.Server/_Sunrise/BloodCult/GameRule/BloodCultRuleSystem.cs
index fbd43e9aa3..835d1c9236 100644
--- a/Content.Server/_Sunrise/BloodCult/GameRule/BloodCultRuleSystem.cs
+++ b/Content.Server/_Sunrise/BloodCult/GameRule/BloodCultRuleSystem.cs
@@ -142,6 +142,45 @@ public sealed class BloodCultRuleSystem : GameRuleSystem
}
}
+ ///
+ /// Manually add a specific entity as a cult target.
+ ///
+ public bool AddSpecificCultTarget(EntityUid target, BloodCultRuleComponent rule)
+ {
+ if (!Exists(target) || rule.CultTargets.ContainsKey(target))
+ return false;
+
+ rule.CultTargets.Add(target, false);
+ EnsureComp(target);
+
+ var query = EntityQueryEnumerator();
+ while (query.MoveNext(out var uid, out var killCultistTargetsComponent))
+ {
+ _cultistTargetsConditionSystem.RefresTitle(uid, rule.CultTargets, killCultistTargetsComponent);
+ }
+ return true;
+ }
+
+ ///
+ /// Manually remove a specific entity as a cult target.
+ ///
+ public bool RemoveSpecificCultTarget(EntityUid target, BloodCultRuleComponent rule)
+ {
+ if (!rule.CultTargets.ContainsKey(target))
+ return false;
+
+ rule.CultTargets.Remove(target);
+ if (Exists(target))
+ RemComp(target);
+
+ var query = EntityQueryEnumerator();
+ 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,
diff --git a/Content.Server/_Sunrise/BloodCult/Runes/Systems/BloodCultSystem.Rune.cs b/Content.Server/_Sunrise/BloodCult/Runes/Systems/BloodCultSystem.Rune.cs
index b85682605d..4b255663fd 100644
--- a/Content.Server/_Sunrise/BloodCult/Runes/Systems/BloodCultSystem.Rune.cs
+++ b/Content.Server/_Sunrise/BloodCult/Runes/Systems/BloodCultSystem.Rune.cs
@@ -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;
diff --git a/Content.Server/_Sunrise/BloodCult/Runes/Systems/BloodCultSystem.cs b/Content.Server/_Sunrise/BloodCult/Runes/Systems/BloodCultSystem.cs
index 32536732ae..91db7f350a 100644
--- a/Content.Server/_Sunrise/BloodCult/Runes/Systems/BloodCultSystem.cs
+++ b/Content.Server/_Sunrise/BloodCult/Runes/Systems/BloodCultSystem.cs
@@ -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;
diff --git a/Content.Shared/Pinpointer/SharedPinpointerSystem.cs b/Content.Shared/Pinpointer/SharedPinpointerSystem.cs
index 4710960183..2f62c5d9fc 100644
--- a/Content.Shared/Pinpointer/SharedPinpointerSystem.cs
+++ b/Content.Shared/Pinpointer/SharedPinpointerSystem.cs
@@ -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)));
diff --git a/Content.Shared/_Sunrise/Biocode/Components/BiocodeDeactivationComponent.cs b/Content.Shared/_Sunrise/Biocode/Components/BiocodeDeactivationComponent.cs
new file mode 100644
index 0000000000..22dd415fef
--- /dev/null
+++ b/Content.Shared/_Sunrise/Biocode/Components/BiocodeDeactivationComponent.cs
@@ -0,0 +1,29 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared._Sunrise.Biocode.Components;
+
+///
+/// Component that automatically deactivates items when they're not in the possession of authorized users.
+///
+[RegisterComponent, NetworkedComponent]
+public sealed partial class BiocodeDeactivationComponent : Component
+{
+ ///
+ /// Whether the item should be deactivated when removed from authorized user's possession.
+ ///
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public bool DeactivateOnRemoval = true;
+
+ ///
+ /// Whether the item should be deactivated when placed in unauthorized user's possession.
+ ///
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public bool DeactivateOnUnauthorized = true;
+
+ ///
+ /// Alert text to show when unauthorized user tries to use the item.
+ /// If null, uses the BiocodeComponent's alert text.
+ ///
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public string? AlertText;
+}
diff --git a/Content.Shared/_Sunrise/Biocode/Systems/BiocodeDeactivationSystem.cs b/Content.Shared/_Sunrise/Biocode/Systems/BiocodeDeactivationSystem.cs
new file mode 100644
index 0000000000..c44d181637
--- /dev/null
+++ b/Content.Shared/_Sunrise/Biocode/Systems/BiocodeDeactivationSystem.cs
@@ -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;
+
+///
+/// System that handles automatic deactivation of biocoded items when they're not in authorized user's possession.
+///
+public abstract class BiocodeDeactivationSystem : EntitySystem
+{
+ [Dependency] private readonly BiocodeSystem _biocodeSystem = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+ SubscribeLocalEvent(OnActivate);
+ SubscribeLocalEvent(OnUseInHand);
+ SubscribeLocalEvent(OnItemDropped);
+ SubscribeLocalEvent(OnItemPickedUp);
+ }
+
+ private void OnItemDropped(EntityUid uid, BiocodeDeactivationComponent component, DroppedEvent args)
+ {
+ if (!component.DeactivateOnRemoval)
+ return;
+
+ // Check if this item has biocode
+ if (!TryComp(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(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(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(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;
+ }
+
+ ///
+ /// Shows an alert to the user. Override this method to implement specific alert display logic.
+ ///
+ protected abstract void ShowAlert(EntityUid user, string alertText);
+
+ ///
+ /// Deactivates the item. Override this method in the shared system to implement specific deactivation logic.
+ ///
+ protected abstract void DeactivateItem(EntityUid uid);
+
+ private EntityUid? GetContainerOwner(EntityUid container)
+ {
+ // Try to find the owner through various container types
+ if (TryComp(container, out _))
+ {
+ return container;
+ }
+
+ if (TryComp(container, out _))
+ {
+ return container;
+ }
+
+ if (TryComp(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;
+ }
+}
diff --git a/Content.Shared/_Sunrise/BloodCult/Components/BloodCultTargetComponent.cs b/Content.Shared/_Sunrise/BloodCult/Components/BloodCultTargetComponent.cs
new file mode 100644
index 0000000000..6ff7e43fc7
--- /dev/null
+++ b/Content.Shared/_Sunrise/BloodCult/Components/BloodCultTargetComponent.cs
@@ -0,0 +1,11 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared._Sunrise.BloodCult.Components;
+
+///
+/// Component that marks an entity as a target for the Blood cult.
+///
+[RegisterComponent, NetworkedComponent]
+public sealed partial class BloodCultTargetComponent : Component
+{
+}
diff --git a/Resources/Audio/_Sunrise/BloodCult/Tear-of-veil(bolgarich).ogg b/Resources/Audio/_Sunrise/BloodCult/Tear-of-veil(bolgarich).ogg
new file mode 100644
index 0000000000..3005c560f4
Binary files /dev/null and b/Resources/Audio/_Sunrise/BloodCult/Tear-of-veil(bolgarich).ogg differ
diff --git a/Resources/Locale/en-US/_prototypes/_sunrise/entities/objects/devices/blood_cult_pinpointer.ftl b/Resources/Locale/en-US/_prototypes/_sunrise/entities/objects/devices/blood_cult_pinpointer.ftl
new file mode 100644
index 0000000000..a34c2e3625
--- /dev/null
+++ b/Resources/Locale/en-US/_prototypes/_sunrise/entities/objects/devices/blood_cult_pinpointer.ftl
@@ -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.
diff --git a/Resources/Locale/en-US/_strings/_sunrise/bloodcult/commands.ftl b/Resources/Locale/en-US/_strings/_sunrise/bloodcult/commands.ftl
new file mode 100644
index 0000000000..f9608b089b
--- /dev/null
+++ b/Resources/Locale/en-US/_strings/_sunrise/bloodcult/commands.ftl
@@ -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
+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
+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.
diff --git a/Resources/Locale/en-US/_strings/_sunrise/bloodcult/pinpointer.ftl b/Resources/Locale/en-US/_strings/_sunrise/bloodcult/pinpointer.ftl
new file mode 100644
index 0000000000..6ec7defb6d
--- /dev/null
+++ b/Resources/Locale/en-US/_strings/_sunrise/bloodcult/pinpointer.ftl
@@ -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
diff --git a/Resources/Locale/ru-RU/_prototypes/_sunrise/entities/objects/devices/blood_cult_pinpointer.ftl b/Resources/Locale/ru-RU/_prototypes/_sunrise/entities/objects/devices/blood_cult_pinpointer.ftl
new file mode 100644
index 0000000000..afbdd54548
--- /dev/null
+++ b/Resources/Locale/ru-RU/_prototypes/_sunrise/entities/objects/devices/blood_cult_pinpointer.ftl
@@ -0,0 +1,2 @@
+ent-BloodCultPinpointer = Кровеуказатель
+ .desc = Зловещий указатель со странным кристаллом, встроенным в него. Он указывает на цели культа. Только культисты знают об этом устройстве и как его использовать, для остальных это странный хлам.
diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/blood-cult/cult.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/blood-cult/cult.ftl
index f9a924f4be..d63272e7da 100644
--- a/Resources/Locale/ru-RU/_strings/_sunrise/blood-cult/cult.ftl
+++ b/Resources/Locale/ru-RU/_strings/_sunrise/blood-cult/cult.ftl
@@ -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 = На этом тайле уже есть руна!
\ No newline at end of file
+tile-has-rune = На этом тайле уже есть руна!
diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/bloodcult/commands.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/bloodcult/commands.ftl
new file mode 100644
index 0000000000..c1cc1d6a0f
--- /dev/null
+++ b/Resources/Locale/ru-RU/_strings/_sunrise/bloodcult/commands.ftl
@@ -0,0 +1,40 @@
+# Blood Cult Console Commands
+
+# Add Target Command
+bloodcult-addtarget-description = Добавить цель для Культа Крови
+bloodcult-addtarget-help = Добавляет конкретного игрока как цель Культа Крови для отслеживания и потенциального жертвоприношения.
+bloodcult-addtarget-usage = Использование: bloodcult_addtarget
+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
+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 = Устройство пульсирует тёмной энергией, отвергая ваше прикосновение. Только те, кто связан кровью, могут владеть его силой.
diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/bloodcult/pinpointer.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/bloodcult/pinpointer.ftl
new file mode 100644
index 0000000000..53fb4ac537
--- /dev/null
+++ b/Resources/Locale/ru-RU/_strings/_sunrise/bloodcult/pinpointer.ftl
@@ -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 = Зловещий указатель со странным кристаллом, встроенным в него. Он указывает на цели культа. Только культисты знают об этом устройстве и как его использовать, для остальных это странный хлам.
diff --git a/Resources/Prototypes/_Sunrise/BloodCult/Entities/Altars/cult_altars.yml b/Resources/Prototypes/_Sunrise/BloodCult/Entities/Altars/cult_altars.yml
index e7eba73d1c..8c838bb8d0 100644
--- a/Resources/Prototypes/_Sunrise/BloodCult/Entities/Altars/cult_altars.yml
+++ b/Resources/Prototypes/_Sunrise/BloodCult/Entities/Altars/cult_altars.yml
@@ -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
diff --git a/Resources/Prototypes/_Sunrise/BloodCult/Entities/Effects/shield.yml b/Resources/Prototypes/_Sunrise/BloodCult/Entities/Effects/shield.yml
index 43030cdfe4..130541fbc6 100644
--- a/Resources/Prototypes/_Sunrise/BloodCult/Entities/Effects/shield.yml
+++ b/Resources/Prototypes/_Sunrise/BloodCult/Entities/Effects/shield.yml
@@ -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
diff --git a/Resources/Prototypes/_Sunrise/BloodCult/Entities/Items/weapon.yml b/Resources/Prototypes/_Sunrise/BloodCult/Entities/Items/weapon.yml
index 9f70379e22..dfd076b048 100644
--- a/Resources/Prototypes/_Sunrise/BloodCult/Entities/Items/weapon.yml
+++ b/Resources/Prototypes/_Sunrise/BloodCult/Entities/Items/weapon.yml
@@ -220,6 +220,8 @@
types:
Structural: 100
Blunt: 25
+ soundHit:
+ collection: MetalThud
- type: MultiHandedItem
- type: Clothing
quickEquip: false
diff --git a/Resources/Prototypes/_Sunrise/BloodCult/Entities/Objects/Devices/blood_cult_pinpointer.yml b/Resources/Prototypes/_Sunrise/BloodCult/Entities/Objects/Devices/blood_cult_pinpointer.yml
new file mode 100644
index 0000000000..0c5584b4fd
--- /dev/null
+++ b/Resources/Prototypes/_Sunrise/BloodCult/Entities/Objects/Devices/blood_cult_pinpointer.yml
@@ -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
diff --git a/Resources/Prototypes/_Sunrise/BloodCult/Entities/constructs.yml b/Resources/Prototypes/_Sunrise/BloodCult/Entities/constructs.yml
index e93844ab0b..9bcb30cfb6 100644
--- a/Resources/Prototypes/_Sunrise/BloodCult/Entities/constructs.yml
+++ b/Resources/Prototypes/_Sunrise/BloodCult/Entities/constructs.yml
@@ -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
diff --git a/Resources/Prototypes/_Sunrise/BloodCult/cult_types.yml b/Resources/Prototypes/_Sunrise/BloodCult/cult_types.yml
index 6b70ae4a73..c9da9524dc 100644
--- a/Resources/Prototypes/_Sunrise/BloodCult/cult_types.yml
+++ b/Resources/Prototypes/_Sunrise/BloodCult/cult_types.yml
@@ -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
diff --git a/Resources/Prototypes/_Sunrise/BloodCult/modifier_sets.yml b/Resources/Prototypes/_Sunrise/BloodCult/modifier_sets.yml
new file mode 100644
index 0000000000..3d3a822aef
--- /dev/null
+++ b/Resources/Prototypes/_Sunrise/BloodCult/modifier_sets.yml
@@ -0,0 +1,6 @@
+- type: damageModifierSet
+ id: BloodCultJuggernautModifierSet
+ coefficients:
+ Slash: 0.5
+ Piercing: 0.5
+ Heat: 2
diff --git a/Resources/Prototypes/_Sunrise/Entities/Objects/Tools/biocode.yml b/Resources/Prototypes/_Sunrise/Entities/Objects/Tools/biocode.yml
index b36ddcf5e7..67f0fa0754 100644
--- a/Resources/Prototypes/_Sunrise/Entities/Objects/Tools/biocode.yml
+++ b/Resources/Prototypes/_Sunrise/Entities/Objects/Tools/biocode.yml
@@ -31,4 +31,4 @@
factions:
- Syndicate
- type: StaticPrice
- price: 900
+ price: 1000
diff --git a/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/meta.json b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/meta.json
new file mode 100644
index 0000000000..e5c2f085a6
--- /dev/null
+++ b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/meta.json
@@ -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
+ ]
+ ]
+ }
+ ]
+}
diff --git a/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonalert.png b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonalert.png
new file mode 100644
index 0000000000..7ffa2f5fda
Binary files /dev/null and b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonalert.png differ
diff --git a/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonalertdirect.png b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonalertdirect.png
new file mode 100644
index 0000000000..8b529e41a6
Binary files /dev/null and b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonalertdirect.png differ
diff --git a/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonalertnull.png b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonalertnull.png
new file mode 100644
index 0000000000..1556d82c76
Binary files /dev/null and b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonalertnull.png differ
diff --git a/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonclose.png b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonclose.png
new file mode 100644
index 0000000000..d652e4cd02
Binary files /dev/null and b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonclose.png differ
diff --git a/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinondirect.png b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinondirect.png
new file mode 100644
index 0000000000..9888880ea1
Binary files /dev/null and b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinondirect.png differ
diff --git a/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinondirectlarge.png b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinondirectlarge.png
new file mode 100644
index 0000000000..c8b1fa4875
Binary files /dev/null and b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinondirectlarge.png differ
diff --git a/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinondirectsmall.png b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinondirectsmall.png
new file mode 100644
index 0000000000..77064e298d
Binary files /dev/null and b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinondirectsmall.png differ
diff --git a/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinondirectxtrlarge.png b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinondirectxtrlarge.png
new file mode 100644
index 0000000000..5db693402c
Binary files /dev/null and b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinondirectxtrlarge.png differ
diff --git a/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonfar.png b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonfar.png
new file mode 100644
index 0000000000..fd0fbf51ac
Binary files /dev/null and b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonfar.png differ
diff --git a/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonmedium.png b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonmedium.png
new file mode 100644
index 0000000000..5f8e89aec2
Binary files /dev/null and b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonmedium.png differ
diff --git a/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonnull.png b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonnull.png
new file mode 100644
index 0000000000..0b4a50f33a
Binary files /dev/null and b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonnull.png differ
diff --git a/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinpointer_bloodcult.png b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinpointer_bloodcult.png
new file mode 100644
index 0000000000..97b6330b5f
Binary files /dev/null and b/Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinpointer_bloodcult.png differ