QOL для культа крови (#3261)

This commit is contained in:
A-Mironov 2025-09-27 00:59:57 +03:00 committed by GitHub
parent 3d15e784d0
commit 599f047fc9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 716 additions and 7 deletions

View file

@ -0,0 +1,46 @@
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)
{
_popup.PopupEntity(Loc.GetString(alertText), user, user);
}
protected override void DeactivateItem(EntityUid uid)
{
// Handle pinpointer deactivation using the proper system method
if (TryComp<PinpointerComponent>(uid, out var pinpointer))
{
// 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))
{
_appearance.SetData(uid, PinpointerVisuals.IsActive, false, appearance);
_appearance.SetData(uid, PinpointerVisuals.TargetDistance, Distance.Unknown, appearance);
}
}
// 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

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

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

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

@ -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,142 @@
{
"version": 1,
"size": {
"x": 32,
"y": 32
},
"license": "CC-BY-SA-3.0",
"copyright": "© 2025 Alexnov33x",
"states": [
{
"name": "pinonalert",
"directions": 8,
"delays": [
[
0.2,
0.2
],
[
0.2,
0.2
],
[
0.2,
0.2
],
[
0.2,
0.2
],
[
0.2,
0.2
],
[
0.2,
0.2
],
[
0.2,
0.2
],
[
0.2,
0.2
]
]
},
{
"name": "pinonalertdirect",
"delays": [
[
0.2,
0.2
]
]
},
{
"name": "pinonalertnull",
"delays": [
[
0.2,
0.2
]
]
},
{
"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",
"delays": [
[
0.2,
0.2
]
]
},
{
"name": "pinpointer_bloodcult"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 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: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 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: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 857 B