Merge branch 'master' into ed-14-04-2025-content

This commit is contained in:
Ed
2025-04-25 13:12:46 +03:00
committed by GitHub
78 changed files with 949 additions and 358 deletions

View File

@@ -165,14 +165,14 @@ public sealed partial class CP14SkillTreeGraphControl : BoxContainer
// Base skill icon
var baseTexture = skill.Icon.Frame0();
var baseSize = new Vector2(baseTexture.Width, baseTexture.Height) * 2;
var baseSize = new Vector2(baseTexture.Width, baseTexture.Height) * 1.5f * UIScale;
var baseQuad = new UIBox2(pos - baseSize / 2, pos + baseSize / 2);
var hovered = (cursor - pos).LengthSquared() <= (baseSize.X / 2) * (baseSize.X / 2);
// Frame
var frameTexture = Tree.FrameIcon.Frame0();
var frameSize = new Vector2(frameTexture.Width, frameTexture.Height) * 2;
var frameSize = new Vector2(frameTexture.Width, frameTexture.Height) * 1.5f * UIScale;
var frameQuad = new UIBox2(pos - frameSize / 2, pos + frameSize / 2);
handle.DrawTextureRect(frameTexture, frameQuad, canBeLearned ? Color.White : Color.FromSrgb(new Color(0.7f, 0.7f, 0.7f)));
@@ -180,7 +180,7 @@ public sealed partial class CP14SkillTreeGraphControl : BoxContainer
if (_selectedNode == skill)
{
var selectedTexture = Tree.SelectedIcon.Frame0();
var selectedSize = new Vector2(selectedTexture.Width, selectedTexture.Height) * 2;
var selectedSize = new Vector2(selectedTexture.Width, selectedTexture.Height) * 1.5f * UIScale;
var selectedQuad = new UIBox2(pos - selectedSize / 2, pos + selectedSize / 2);
handle.DrawTextureRect(selectedTexture, selectedQuad, Color.White);
}
@@ -190,7 +190,7 @@ public sealed partial class CP14SkillTreeGraphControl : BoxContainer
{
_hoveredNode = skill;
var hoveredTexture = Tree.HoveredIcon.Frame0();
var hoveredSize = new Vector2(hoveredTexture.Width, hoveredTexture.Height) * 2;
var hoveredSize = new Vector2(hoveredTexture.Width, hoveredTexture.Height) * 1.5f * UIScale;
var hoveredQuad = new UIBox2(pos - hoveredSize / 2, pos + hoveredSize / 2);
handle.DrawTextureRect(hoveredTexture, hoveredQuad, Color.White);
}
@@ -202,14 +202,14 @@ public sealed partial class CP14SkillTreeGraphControl : BoxContainer
if (learned)
{
var learnedTexture = Tree.LearnedIcon.Frame0();
var learnedSize = new Vector2(learnedTexture.Width, learnedTexture.Height) * 2;
var learnedSize = new Vector2(learnedTexture.Width, learnedTexture.Height) * 1.5f * UIScale;
var learnedQuad = new UIBox2(pos - learnedSize / 2, pos + learnedSize / 2);
handle.DrawTextureRect(learnedTexture, learnedQuad, Color.White);
}
else if (canBeLearned)
{
var availableTexture = Tree.AvailableIcon.Frame0();
var availableSize = new Vector2(availableTexture.Width, availableTexture.Height) * 2;
var availableSize = new Vector2(availableTexture.Width, availableTexture.Height) * 1.5f * UIScale;
var availableQuad = new UIBox2(pos - availableSize / 2, pos + availableSize / 2);
handle.DrawTextureRect(availableTexture, availableQuad, Color.White);
}

View File

@@ -2,7 +2,6 @@ using System.Linq;
using Content.Server.Labels;
using Content.Shared._CP14.LockKey;
using Content.Shared._CP14.LockKey.Components;
using Content.Shared.Examine;
using Content.Shared.GameTicking;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
@@ -15,7 +14,7 @@ public sealed partial class CP14KeyholeGenerationSystem : EntitySystem
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly LabelSystem _label = default!;
private Dictionary<ProtoId<CP14LockTypePrototype>, List<int>> _roundKeyData = new();
private Dictionary<ProtoId<CP14LockTypePrototype>, List<int>> _roundKeyData = new(); //TODO: it won't survive saving and loading. This data must be stored in some component.
public override void Initialize()
{
@@ -25,8 +24,6 @@ public sealed partial class CP14KeyholeGenerationSystem : EntitySystem
SubscribeLocalEvent<CP14LockComponent, MapInitEvent>(OnLockInit);
SubscribeLocalEvent<CP14KeyComponent, MapInitEvent>(OnKeyInit);
SubscribeLocalEvent<CP14KeyComponent, ExaminedEvent>(OnKeyExamine);
}
#region Init
@@ -49,28 +46,13 @@ public sealed partial class CP14KeyholeGenerationSystem : EntitySystem
{
SetShape(lockEnt, lockEnt.Comp.AutoGenerateShape.Value);
}
else if (lockEnt.Comp.AutoGenerateRandomShape != null)
{
SetRandomShape(lockEnt, lockEnt.Comp.AutoGenerateRandomShape.Value);
}
}
#endregion
private void OnKeyExamine(Entity<CP14KeyComponent> key, ref ExaminedEvent args)
{
var parent = Transform(key).ParentUid;
if (parent != args.Examiner)
return;
if (key.Comp.LockShape == null)
return;
var markup = Loc.GetString("cp14-lock-examine-key", ("item", MetaData(key).EntityName));
markup += " (";
foreach (var item in key.Comp.LockShape)
{
markup += $"{item} ";
}
markup += ")";
args.PushMarkup(markup);
}
private List<int> GetKeyLockData(ProtoId<CP14LockTypePrototype> category)
{
if (_roundKeyData.ContainsKey(category))
@@ -84,6 +66,7 @@ public sealed partial class CP14KeyholeGenerationSystem : EntitySystem
public void SetShape(Entity<CP14KeyComponent> keyEnt, ProtoId<CP14LockTypePrototype> type)
{
keyEnt.Comp.LockShape = GetKeyLockData(type);
DirtyField(keyEnt, keyEnt.Comp, nameof(CP14KeyComponent.LockShape));
var indexedType = _proto.Index(type);
if (indexedType.Name is not null)
@@ -97,6 +80,19 @@ public sealed partial class CP14KeyholeGenerationSystem : EntitySystem
var indexedType = _proto.Index(type);
if (indexedType.Name is not null)
_label.Label(lockEnt, Loc.GetString(indexedType.Name.Value));
DirtyField(lockEnt, lockEnt.Comp, nameof(CP14LockComponent.LockShape));
}
public void SetRandomShape(Entity<CP14LockComponent> lockEnt, int complexity)
{
lockEnt.Comp.LockShape = new List<int>();
for (var i = 0; i < complexity; i++)
{
lockEnt.Comp.LockShape.Add(_random.Next(-SharedCP14LockKeySystem.DepthComplexity, SharedCP14LockKeySystem.DepthComplexity));
}
DirtyField(lockEnt, lockEnt.Comp, nameof(CP14LockComponent.LockShape));
}
private List<int> GenerateNewUniqueLockData(ProtoId<CP14LockTypePrototype> category)

View File

@@ -35,6 +35,28 @@ namespace Content.Shared.Verbs
IconsOnly = iconsOnly;
}
//CP14 verbs
public static readonly VerbCategory CP14LockPick =
new("verb-categories-lock-pick", "/Textures/Interface/VerbIcons/lock.svg.192dpi.png");
public static readonly VerbCategory CP14KeyFile =
new("verb-categories-key-file", "/Textures/Interface/VerbIcons/lock.svg.192dpi.png");
public static readonly VerbCategory CP14EditLock =
new("verb-categories-edit-lock", "/Textures/Interface/VerbIcons/lock.svg.192dpi.png");
public static readonly VerbCategory CP14ModularCraft =
new("verb-categories-modular-craft", "/Textures/Interface/AdminActions/unbolt.png");
public static readonly VerbCategory CP14RitualBook = new("cp14-verb-categories-ritual-book", null);
public static readonly VerbCategory CP14CurrencyConvert = new("cp14-verb-categories-currency-converter", null); //CP14
public static readonly VerbCategory CP14AdminSkillAdd =
new ("cp14-verb-categories-admin-skill-add", null, iconsOnly: true) { Columns = 6 };
public static readonly VerbCategory CP14AdminSkillRemove =
new ("cp14-verb-categories-admin-skill-remove", null, iconsOnly: true) { Columns = 6 };
//CP14 verbs
public static readonly VerbCategory Admin =
new("verb-categories-admin", "/Textures/Interface/character.svg.192dpi.png");
@@ -76,12 +98,6 @@ namespace Content.Shared.Verbs
public static readonly VerbCategory InstrumentStyle =
new("verb-categories-instrument-style", null);
public static readonly VerbCategory CP14LockPick =
new("verb-categories-lock-pick", "/Textures/Interface/VerbIcons/lock.svg.192dpi.png");
public static readonly VerbCategory CP14ModularCraft =
new("verb-categories-modular-craft", "/Textures/Interface/AdminActions/unbolt.png");
public static readonly VerbCategory ChannelSelect = new("verb-categories-channel-select", null);
public static readonly VerbCategory SetSensor = new("verb-categories-set-sensor", null);
@@ -91,15 +107,5 @@ namespace Content.Shared.Verbs
public static readonly VerbCategory SelectType = new("verb-categories-select-type", null);
public static readonly VerbCategory PowerLevel = new("verb-categories-power-level", null);
public static readonly VerbCategory CP14RitualBook = new("cp14-verb-categories-ritual-book", null); //CP14
public static readonly VerbCategory CP14CurrencyConvert = new("cp14-verb-categories-currency-converter", null); //CP14
public static readonly VerbCategory CP14AdminSkillAdd =
new ("cp14-verb-categories-admin-skill-add", null, iconsOnly: true) { Columns = 6 }; //CP14
public static readonly VerbCategory CP14AdminSkillRemove =
new ("cp14-verb-categories-admin-skill-remove", null, iconsOnly: true) { Columns = 6 }; //CP14
}
}

View File

@@ -1,3 +1,4 @@
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.LockKey.Components;
@@ -5,10 +6,10 @@ namespace Content.Shared._CP14.LockKey.Components;
/// <summary>
/// a key component that can be used to unlock and lock locks from CPLockComponent
/// </summary>
[RegisterComponent]
[RegisterComponent, AutoGenerateComponentState(fieldDeltas: true), NetworkedComponent]
public sealed partial class CP14KeyComponent : Component
{
[DataField]
[DataField, AutoNetworkedField]
public List<int>? LockShape = null;
/// <summary>

View File

@@ -0,0 +1,20 @@
using Robust.Shared.Audio;
namespace Content.Shared._CP14.LockKey.Components;
/// <summary>
/// Allows, when interacting with keys, to mill different teeth, changing the shape of the key
/// </summary>
[RegisterComponent]
public sealed partial class CP14KeyFileComponent : Component
{
/// <summary>
/// sound when used
/// </summary>
[DataField]
public SoundSpecifier UseSound =
new SoundPathSpecifier("/Audio/_CP14/Items/sharpening_stone.ogg")
{
Params = AudioParams.Default.WithVariation(0.02f),
};
}

View File

@@ -1,3 +1,5 @@
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.LockKey.Components;
@@ -5,30 +7,43 @@ namespace Content.Shared._CP14.LockKey.Components;
/// <summary>
/// A component of a lock that stores its keyhole shape, complexity, and current state.
/// </summary>
[RegisterComponent, AutoGenerateComponentState]
[RegisterComponent, AutoGenerateComponentState(fieldDeltas: true), NetworkedComponent]
public sealed partial class CP14LockComponent : Component
{
[DataField, AutoNetworkedField]
public List<int>? LockShape = null;
[DataField]
public float LockPickDamageChance = 0.2f;
/// <summary>
/// On which element of the shape sequence the lock is now located. It's necessary for the mechanics of breaking and entering.
/// </summary>
[DataField]
[DataField, AutoNetworkedField]
public int LockPickStatus = 0;
/// <summary>
/// after a lock is broken into, it leaves a description on it that it's been tampered with.
/// </summary>
[DataField]
public bool LockPickedFailMarkup = false;
/// <summary>
/// If not null, automatically generates a lock for the specified category on initialization. This ensures that the lock will be opened with a key of the same category.
/// </summary>
[DataField]
public ProtoId<CP14LockTypePrototype>? AutoGenerateShape = null;
/// <summary>
/// If not null, the lock will automatically generate a random shape on initialization with selected numbers of elements. Useful for random dungeons doors or chests for example.
/// </summary>
[DataField]
public int? AutoGenerateRandomShape = null;
/// <summary>
/// This component is used for two types of items: Entities themselves that are locked (doors, chests),
/// and a portable lock item that can be built into other entities. This variable determines whether
/// using this entity on another entity can overwrite the lock properties of the target entity.
/// </summary>
[DataField]
public bool CanEmbedded = false;
[DataField]
public SoundSpecifier EmbedSound = new SoundPathSpecifier("/Audio/_CP14/Items/lockpick_use.ogg")
{
Params = AudioParams.Default
.WithVariation(0.05f)
.WithVolume(0.5f),
};
}

View File

@@ -0,0 +1,28 @@
using Robust.Shared.Audio;
namespace Content.Shared._CP14.LockKey.Components;
/// <summary>
/// Allows, when interacting with keys, to mill different teeth, changing the shape of the key
/// </summary>
[RegisterComponent]
public sealed partial class CP14LockEditerComponent : Component
{
/// <summary>
/// sound when used
/// </summary>
[DataField]
public SoundSpecifier UseSound =
new SoundCollectionSpecifier("Screwdriver")
{
Params = AudioParams.Default.WithVariation(0.02f),
};
}
//Ed: maybe this component should be removed, and logic be attached to "Screwing" tool?
//CP14KeyFileComponent too, but with different tool prototype
// l、 meow
// (゚、 。
// l ~ヽ
// じしf_,)

View File

@@ -9,10 +9,10 @@ namespace Content.Shared._CP14.LockKey.Components;
public sealed partial class CP14LockpickComponent : Component
{
[DataField]
public int Health = 3;
public int Health = 10;
[DataField]
public TimeSpan HackTime = TimeSpan.FromSeconds(1.5f);
public TimeSpan HackTime = TimeSpan.FromSeconds(1.0f);
[DataField]
public SoundSpecifier SuccessSound = new SoundPathSpecifier("/Audio/_CP14/Items/lockpick_use.ogg")

View File

@@ -1,3 +1,5 @@
using System.Linq;
using System.Text;
using Content.Shared._CP14.LockKey.Components;
using Content.Shared.DoAfter;
using Content.Shared.Interaction;
@@ -6,9 +8,14 @@ using Content.Shared.Popups;
using Content.Shared.Storage;
using Content.Shared.Verbs;
using Content.Shared.Doors.Components;
using Content.Shared.Examine;
using Content.Shared.IdentityManagement;
using Content.Shared.Timing;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Network;
using Robust.Shared.Random;
using Robust.Shared.Serialization;
using Robust.Shared.Timing;
namespace Content.Shared._CP14.LockKey;
@@ -19,6 +26,9 @@ public sealed class SharedCP14LockKeySystem : EntitySystem
[Dependency] private readonly LockSystem _lock = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly UseDelaySystem _useDelay = default!;
private EntityQuery<LockComponent> _lockQuery;
private EntityQuery<CP14LockComponent> _cp14LockQuery;
@@ -36,12 +46,22 @@ public sealed class SharedCP14LockKeySystem : EntitySystem
_keyQuery = GetEntityQuery<CP14KeyComponent>();
_doorQuery = GetEntityQuery<DoorComponent>();
//Interact
SubscribeLocalEvent<CP14KeyComponent, AfterInteractEvent>(OnKeyInteract);
SubscribeLocalEvent<CP14KeyRingComponent, AfterInteractEvent>(OnKeyRingInteract);
SubscribeLocalEvent<CP14KeyComponent, GetVerbsEvent<UtilityVerb>>(OnKeyToLockVerb);
SubscribeLocalEvent<CP14LockComponent, AfterInteractEvent>(OnLockInteract);
//Verbs
SubscribeLocalEvent<CP14KeyComponent, GetVerbsEvent<UtilityVerb>>(GetKeysVerbs);
SubscribeLocalEvent<CP14KeyFileComponent, GetVerbsEvent<UtilityVerb>>(GetKeyFileVerbs);
SubscribeLocalEvent<CP14LockpickComponent, GetVerbsEvent<UtilityVerb>>(GetLockpickVerbs);
SubscribeLocalEvent<CP14LockEditerComponent, GetVerbsEvent<UtilityVerb>>(GetLockEditerVerbs);
SubscribeLocalEvent<CP14LockpickComponent, GetVerbsEvent<UtilityVerb>>(OnLockPickToLockVerb);
SubscribeLocalEvent<CP14LockComponent, LockPickHackDoAfterEvent>(OnLockHacked);
SubscribeLocalEvent<CP14LockComponent, LockInsertDoAfterEvent>(OnLockInserted);
SubscribeLocalEvent<CP14KeyComponent, ExaminedEvent>(OnKeyExamine);
SubscribeLocalEvent<CP14LockComponent, ExaminedEvent>(OnLockExamine);
}
private void OnKeyRingInteract(Entity<CP14KeyRingComponent> keyring, ref AfterInteractEvent args)
@@ -61,6 +81,11 @@ public sealed class SharedCP14LockKeySystem : EntitySystem
if (!_cp14LockQuery.TryComp(args.Target, out var cp14LockComp))
return;
if (!_timing.IsFirstTimePredicted)
return;
args.Handled = true;
foreach (var (key, _) in storageComp.StoredItems)
{
if (!_keyQuery.TryComp(key, out var keyComp))
@@ -69,12 +94,15 @@ public sealed class SharedCP14LockKeySystem : EntitySystem
if (keyComp.LockShape != cp14LockComp.LockShape)
continue;
TryUseKeyOnLock(args.User, new Entity<CP14LockComponent>(args.Target.Value, cp14LockComp), new Entity<CP14KeyComponent>(key, keyComp));
TryUseKeyOnLock(args.User,
new Entity<CP14LockComponent>(args.Target.Value, cp14LockComp),
new Entity<CP14KeyComponent>(key, keyComp));
args.Handled = true;
return;
}
_popup.PopupEntity(Loc.GetString("cp14-lock-key-no-fit"), args.Target.Value, args.User);
if (_timing.IsFirstTimePredicted)
_popup.PopupPredicted(Loc.GetString("cp14-lock-key-no-fit"), args.Target.Value, args.User);
}
private void OnKeyInteract(Entity<CP14KeyComponent> key, ref AfterInteractEvent args)
@@ -91,48 +119,85 @@ public sealed class SharedCP14LockKeySystem : EntitySystem
if (!_cp14LockQuery.TryComp(args.Target, out var cp14LockComp))
return;
if (!_timing.IsFirstTimePredicted)
return;
args.Handled = true;
TryUseKeyOnLock(args.User, new Entity<CP14LockComponent>(args.Target.Value, cp14LockComp), key);
args.Handled = true;
}
private void OnLockPickToLockVerb(Entity<CP14LockpickComponent> lockPick, ref GetVerbsEvent<UtilityVerb> args)
private void OnLockInteract(Entity<CP14LockComponent> ent, ref AfterInteractEvent args)
{
if (!args.CanInteract || !args.CanAccess)
if (args.Handled)
return;
if (!_lockQuery.TryComp(args.Target, out var lockComp) || !lockComp.Locked)
if (!_timing.IsFirstTimePredicted)
return;
if (!_cp14LockQuery.TryComp(args.Target, out _))
if (!ent.Comp.CanEmbedded)
return;
var target = args.Target;
var user = args.User;
if (!_lockQuery.TryComp(args.Target, out _))
return;
for (var i = DepthComplexity; i >= -DepthComplexity; i--)
if (!_cp14LockQuery.TryComp(args.Target, out var targetCp14LockComp))
return;
args.Handled = true;
if (targetCp14LockComp.LockShape is not null)
{
var height = i;
var verb = new UtilityVerb()
{
Act = () =>
{
_doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, user, lockPick.Comp.HackTime, new LockPickHackDoAfterEvent(height), target, target, lockPick)
{
BreakOnDamage = true,
BreakOnMove = true,
BreakOnDropItem = true,
BreakOnHandChange = true,
});
},
Text = Loc.GetString("cp14-lock-verb-lock-pick-use-text") + $" {height}",
Message = Loc.GetString("cp14-lock-verb-lock-pick-use-message"),
Category = VerbCategory.CP14LockPick,
Priority = height,
CloseMenu = false,
};
args.Verbs.Add(verb);
_popup.PopupPredicted(Loc.GetString("cp14-lock-insert-fail-have-lock",
("name", MetaData(args.Target.Value).EntityName)),
ent,
args.User);
return;
}
//Ok, all checks passed, we ready to install lock into entity
args.Handled = true;
_popup.PopupPredicted(Loc.GetString("cp14-lock-insert-start", ("name", MetaData(args.Target.Value).EntityName), ("player", Identity.Name(args.User, EntityManager))),
ent,
args.User);
_doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager,
args.User,
TimeSpan.FromSeconds(2f), //Boo, hardcoding
new LockInsertDoAfterEvent(),
args.Target,
args.Target,
ent)
{
BreakOnDamage = true,
BreakOnMove = true,
BreakOnDropItem = true,
BreakOnHandChange = true,
});
}
private void OnLockInserted(Entity<CP14LockComponent> ent, ref LockInsertDoAfterEvent args)
{
if (args.Cancelled || args.Handled)
return;
if (!_cp14LockQuery.TryComp(args.Used, out var usedLock))
return;
ent.Comp.LockShape = usedLock.LockShape;
DirtyField(ent, ent.Comp, nameof(CP14LockComponent.LockShape));
_popup.PopupPredicted(Loc.GetString("cp14-lock-insert-success", ("name", MetaData(ent).EntityName)),
ent,
args.User);
_audio.PlayPredicted(usedLock.EmbedSound, ent, args.User);
if (_net.IsServer)
QueueDel(args.Used);
}
private void OnLockHacked(Entity<CP14LockComponent> ent, ref LockPickHackDoAfterEvent args)
@@ -149,53 +214,72 @@ public sealed class SharedCP14LockKeySystem : EntitySystem
if (!TryComp<CP14LockpickComponent>(args.Used, out var lockPick))
return;
if (!_timing.IsFirstTimePredicted)
return;
if (args.Height == ent.Comp.LockShape[ent.Comp.LockPickStatus]) //Success
{
_audio.PlayPvs(lockPick.SuccessSound, ent);
_audio.PlayPredicted(lockPick.SuccessSound, ent, args.User);
ent.Comp.LockPickStatus++;
DirtyField(ent, ent.Comp, nameof(CP14LockComponent.LockPickStatus));
if (ent.Comp.LockPickStatus >= ent.Comp.LockShape.Count) // Final success
{
if (lockComp.Locked)
{
_lock.TryUnlock(ent, args.User, lockComp);
_popup.PopupEntity(Loc.GetString("cp14-lock-unlock", ("lock", MetaData(ent).EntityName)), ent, args.User);
_popup.PopupPredicted(Loc.GetString("cp14-lock-unlock", ("lock", MetaData(ent).EntityName)),
ent,
args.User);
ent.Comp.LockPickStatus = 0;
DirtyField(ent, ent.Comp, nameof(CP14LockComponent.LockPickStatus));
return;
}
_lock.TryLock(ent, args.User, lockComp);
_popup.PopupEntity(Loc.GetString("cp14-lock-lock", ("lock", MetaData(ent).EntityName)), ent, args.User);
_popup.PopupPredicted(Loc.GetString("cp14-lock-lock", ("lock", MetaData(ent).EntityName)),
ent,
args.User);
ent.Comp.LockPickStatus = 0;
DirtyField(ent, ent.Comp, nameof(CP14LockComponent.LockPickStatus));
return;
}
_popup.PopupEntity(Loc.GetString("cp14-lock-lock-pick-success"), ent, args.User);
_popup.PopupClient(Loc.GetString("cp14-lock-lock-pick-success") +
$" ({ent.Comp.LockPickStatus}/{ent.Comp.LockShape.Count})",
ent,
args.User);
}
else //Fail
{
_audio.PlayPvs(lockPick.FailSound, ent);
if (_random.Prob(ent.Comp.LockPickDamageChance)) // Damage lock pick
_audio.PlayPredicted(lockPick.FailSound, ent, args.User);
if (_net.IsServer)
{
lockPick.Health--;
if (lockPick.Health > 0)
{
_popup.PopupEntity(Loc.GetString("cp14-lock-lock-pick-failed-damage", ("lock", MetaData(ent).EntityName)), ent, args.User);
_popup.PopupEntity(Loc.GetString("cp14-lock-lock-pick-failed", ("lock", MetaData(ent).EntityName)),
ent,
args.User);
}
else
{
_popup.PopupEntity(Loc.GetString("cp14-lock-lock-pick-failed-break", ("lock", MetaData(ent).EntityName)), ent, args.User);
_popup.PopupEntity(
Loc.GetString("cp14-lock-lock-pick-failed-break", ("lock", MetaData(ent).EntityName)),
ent,
args.User);
QueueDel(args.Used);
}
}
else
{
_popup.PopupEntity(Loc.GetString("cp14-lock-lock-pick-failed", ("lock", MetaData(ent).EntityName)), ent, args.User);
}
ent.Comp.LockPickedFailMarkup = true;
ent.Comp.LockPickStatus = 0;
DirtyField(ent, ent.Comp, nameof(CP14LockComponent.LockPickStatus));
}
}
private void OnKeyToLockVerb(Entity<CP14KeyComponent> key, ref GetVerbsEvent<UtilityVerb> args)
private void GetKeysVerbs(Entity<CP14KeyComponent> key, ref GetVerbsEvent<UtilityVerb> args)
{
if (!args.CanInteract || !args.CanAccess)
return;
@@ -216,13 +300,167 @@ public sealed class SharedCP14LockKeySystem : EntitySystem
TryUseKeyOnLock(user, new Entity<CP14LockComponent>(target, cp14LockComponent), key);
},
IconEntity = GetNetEntity(key),
Text = Loc.GetString(lockComp.Locked ? "cp14-lock-verb-use-key-text-open" : "cp14-lock-verb-use-key-text-close", ("item", MetaData(args.Target).EntityName)),
Text = Loc.GetString(
lockComp.Locked ? "cp14-lock-verb-use-key-text-open" : "cp14-lock-verb-use-key-text-close",
("item", MetaData(args.Target).EntityName)),
Message = Loc.GetString("cp14-lock-verb-use-key-message", ("item", MetaData(args.Target).EntityName)),
};
args.Verbs.Add(verb);
}
private void GetKeyFileVerbs(Entity<CP14KeyFileComponent> ent, ref GetVerbsEvent<UtilityVerb> args)
{
if (!args.CanInteract || !args.CanAccess)
return;
if (!_keyQuery.TryComp(args.Target, out var keyComp))
return;
if (keyComp.LockShape == null)
return;
var target = args.Target;
var user = args.User;
var lockShapeCount = keyComp.LockShape.Count;
for (var i = 0; i <= lockShapeCount - 1; i++)
{
var i1 = i;
var verb = new UtilityVerb
{
Act = () =>
{
if (keyComp.LockShape[i1] <= -DepthComplexity)
return;
if (!_timing.IsFirstTimePredicted)
return;
if (TryComp<UseDelayComponent>(ent, out var useDelayComp) &&
_useDelay.IsDelayed((ent, useDelayComp)))
return;
if (!_net.IsServer)
return;
keyComp.LockShape[i1]--;
DirtyField(target, keyComp, nameof(CP14KeyComponent.LockShape));
_audio.PlayPvs(ent.Comp.UseSound, Transform(target).Coordinates);
Spawn("EffectSparks", Transform(target).Coordinates);
var shapeString = "[" + string.Join(", ", keyComp.LockShape) + "]";
_popup.PopupEntity(Loc.GetString("cp14-lock-key-file-updated") + shapeString, target, user);
_useDelay.TryResetDelay(ent);
},
IconEntity = GetNetEntity(ent),
Category = VerbCategory.CP14KeyFile,
Priority = -i,
Disabled = keyComp.LockShape[i] <= -DepthComplexity,
Text = Loc.GetString("cp14-lock-key-file-use-hint", ("num", i)),
CloseMenu = false,
};
args.Verbs.Add(verb);
}
}
private void GetLockpickVerbs(Entity<CP14LockpickComponent> lockPick, ref GetVerbsEvent<UtilityVerb> args)
{
if (!args.CanInteract || !args.CanAccess)
return;
if (!_lockQuery.TryComp(args.Target, out var lockComp) || !lockComp.Locked)
return;
if (!_cp14LockQuery.HasComp(args.Target))
return;
var target = args.Target;
var user = args.User;
for (var i = DepthComplexity; i >= -DepthComplexity; i--)
{
var height = i;
var verb = new UtilityVerb()
{
Act = () =>
{
_doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager,
user,
lockPick.Comp.HackTime,
new LockPickHackDoAfterEvent(height),
target,
target,
lockPick)
{
BreakOnDamage = true,
BreakOnMove = true,
BreakOnDropItem = true,
BreakOnHandChange = true,
});
},
Text = Loc.GetString("cp14-lock-verb-lock-pick-use-text") + $" {height}",
Message = Loc.GetString("cp14-lock-verb-lock-pick-use-message"),
Category = VerbCategory.CP14LockPick,
Priority = height,
CloseMenu = false,
};
args.Verbs.Add(verb);
}
}
private void GetLockEditerVerbs(Entity<CP14LockEditerComponent> ent, ref GetVerbsEvent<UtilityVerb> args)
{
if (!args.CanInteract || !args.CanAccess)
return;
if (!_cp14LockQuery.TryComp(args.Target, out var lockComp) || !lockComp.CanEmbedded)
return;
if (lockComp.LockShape is null)
return;
var target = args.Target;
var user = args.User;
var lockShapeCount = lockComp.LockShape.Count;
for (var i = 0; i <= lockShapeCount - 1; i++)
{
var i1 = i;
var verb = new UtilityVerb
{
Act = () =>
{
if (!_timing.IsFirstTimePredicted)
return;
if (TryComp<UseDelayComponent>(ent, out var useDelayComp) &&
_useDelay.IsDelayed((ent, useDelayComp)))
return;
if (!_net.IsServer)
return;
lockComp.LockShape[i1]--;
if (lockComp.LockShape[i1] < -DepthComplexity)
lockComp.LockShape[i1] = DepthComplexity; //Cycle back to max
DirtyField(target, lockComp, nameof(CP14LockComponent.LockShape));
_audio.PlayPvs(ent.Comp.UseSound, Transform(target).Coordinates);
var shapeString = "[" + string.Join(", ", lockComp.LockShape) + "]";
_popup.PopupEntity(Loc.GetString("cp14-lock-editor-updated") + shapeString, target, user);
_useDelay.TryResetDelay(ent);
},
IconEntity = GetNetEntity(ent),
Category = VerbCategory.CP14EditLock,
Priority = -i,
Text = Loc.GetString("cp14-lock-editor-use-hint", ("num", i)),
CloseMenu = false,
};
args.Verbs.Add(verb);
}
}
private void TryUseKeyOnLock(EntityUid user, Entity<CP14LockComponent> target, Entity<CP14KeyComponent> key)
{
if (!TryComp<LockComponent>(target, out var lockComp))
@@ -237,24 +475,65 @@ public sealed class SharedCP14LockKeySystem : EntitySystem
if (keyShape == null || lockShape == null)
return;
if (keyShape == lockShape)
if (keyShape.SequenceEqual(lockShape))
{
if (lockComp.Locked)
{
if(_lock.TryUnlock(target, user))
_popup.PopupEntity(Loc.GetString("cp14-lock-unlock", ("lock", MetaData(target).EntityName)), target, user);
_lock.TryUnlock(target, user);
}
else
{
if (_lock.TryLock(target, user))
_popup.PopupEntity(Loc.GetString("cp14-lock-lock", ("lock", MetaData(target).EntityName)), target, user);
_lock.TryLock(target, user);
}
}
else
{
_popup.PopupEntity(Loc.GetString("cp14-lock-key-no-fit"), target, user);
_popup.PopupClient(Loc.GetString("cp14-lock-key-no-fit"), target, user);
}
}
private void OnKeyExamine(Entity<CP14KeyComponent> ent, ref ExaminedEvent args)
{
var parent = Transform(ent).ParentUid;
if (parent != args.Examiner)
return;
if (ent.Comp.LockShape == null)
return;
var sb = new StringBuilder(Loc.GetString("cp14-lock-examine-key", ("item", MetaData(ent).EntityName)));
sb.Append(" (");
foreach (var item in ent.Comp.LockShape)
{
sb.Append($"{item} ");
}
sb.Append(")");
args.PushMarkup(sb.ToString());
}
private void OnLockExamine(Entity<CP14LockComponent> ent, ref ExaminedEvent args)
{
if (!ent.Comp.CanEmbedded)
return;
var parent = Transform(ent).ParentUid;
if (parent != args.Examiner)
return;
if (ent.Comp.LockShape == null)
return;
var sb = new StringBuilder(Loc.GetString("cp14-lock-examine-key", ("item", MetaData(ent).EntityName)));
sb.Append(" (");
foreach (var item in ent.Comp.LockShape)
{
sb.Append($"{item} ");
}
sb.Append(")");
args.PushMarkup(sb.ToString());
}
}
[Serializable, NetSerializable]
@@ -270,3 +549,6 @@ public sealed partial class LockPickHackDoAfterEvent : DoAfterEvent
public override DoAfterEvent Clone() => this;
}
[Serializable, NetSerializable]
public sealed partial class LockInsertDoAfterEvent : SimpleDoAfterEvent;

View File

@@ -1,16 +1,14 @@
verb-categories-lock-pick = Pick the lock
verb-categories-key-file = Modify key
verb-categories-edit-lock = Edit lock
cp14-lock-verb-lock-pick-use-text = Push:
cp14-lock-verb-lock-pick-use-message = If you engage the lock prongs in the correct sequence, you can unlock the lock.
cp14-lock-key-no-fit = The key does not fit!
cp14-lock-unlock = You have opened {$lock}
cp14-lock-lock = You closed {$lock}
cp14-lock-lock-pick-success = One of the lock elements clicks quietly.
cp14-lock-lock-pick-failed = {$lock} is reset to its original position.
cp14-lock-lock-pick-failed-damage = {$lock} is reset to its original position, damaging your lockpick.
cp14-lock-lock-pick-failed-break = {$lock} resets to its original position, breaking your lockpick.
cp14-lock-verb-use-key-text-open = Open the lock with {$item}.
@@ -20,4 +18,14 @@ cp14-lock-verb-use-key-message = Use {$item} to lock or unlock the lock.
cp14-lock-examine-lock-slot = {$lock} is hanging here.
cp14-lock-examine-lock-lockpicked = {$lock} looks shabby.
cp14-lock-examine-key = The {$item} has prongs of the following shape:
cp14-lock-examine-key = The {$item} has prongs of the following shape:
cp14-lock-key-file-use-hint = Grind tooth: {$num}
cp14-lock-key-file-updated = New key shape:
cp14-lock-editor-use-hint = Edit tooth: {$num}
cp14-lock-editor-updated = New lock shape:
cp14-lock-insert-start = {$player} starts installing a lock on {$name}.
cp14-lock-insert-fail-have-lock = {$name} already has a lock installed!
cp14-lock-insert-success = The new lock has been successfully installed in {$name}!

View File

@@ -1,16 +1,14 @@
verb-categories-lock-pick = Взломать замок
verb-categories-key-file = Подточить ключ
verb-categories-edit-lock = Настроить замок
cp14-lock-verb-lock-pick-use-text = Надавить:
cp14-lock-verb-lock-pick-use-message = Если вы в правильной последовательности заденете зубчики замка, вы сможете разблокировать его.
cp14-lock-key-no-fit = Ключ не подходит!
cp14-lock-unlock = Вы открыли {$lock}
cp14-lock-lock = Вы закрыли {$lock}
cp14-lock-lock-pick-success = Один из элементов замка тихо щелкает.
cp14-lock-lock-pick-failed = {$lock} сбрасывается в исходное положение.
cp14-lock-lock-pick-failed-damage = {$lock} сбрасывается в исходное положение, повреждая вашу отмычку.
cp14-lock-lock-pick-failed-break = {$lock} сбрасывается в исходное положение, ломая вашу отмычку.
cp14-lock-verb-use-key-text-open = Открыть замок при помощи {$item}
@@ -20,4 +18,14 @@ cp14-lock-verb-use-key-message = Использовать {$item} чтобы з
cp14-lock-examine-lock-slot = Здесь висит {$lock}
cp14-lock-examine-lock-lockpicked = {$lock} выглядит потрепанным.
cp14-lock-examine-key = {$item} имеет зубцы следующей формы:
cp14-lock-examine-key = {$item} имеет зубцы следующей формы:
cp14-lock-key-file-use-hint = Сточить зубец: {$num}
cp14-lock-key-file-updated = Новая форма ключа:
cp14-lock-editor-use-hint = Настроить зубец: {$num}
cp14-lock-editor-updated = Новая форма замка:
cp14-lock-insert-start = {$player} начинает устанавливать замок в {$name}.
cp14-lock-insert-fail-have-lock = В {$name} уже установлен замок!
cp14-lock-insert-success = Новый замок успешно установлен в {$name}!

View File

@@ -44,7 +44,7 @@
children:
- !type:GroupSelector
children:
- id: CP14BaseCrowbar
- id: CP14Screwdriver
weight: 2
- id: CP14BaseWrench
weight: 2

View File

@@ -1,5 +1,5 @@
- type: entity
parent: CP14BaseKey
parent: CP14KeyIronBlank
id: CP14KeyTavernAlchemistAbstract
suffix: Abstract Alchemist
components:
@@ -7,7 +7,7 @@
group: Alchemist
- type: entity
parent: CP14BaseKey
parent: CP14KeyIronBlank
id: CP14KeyAlchemy1
suffix: Alchemy 1
components:
@@ -15,7 +15,7 @@
autoGenerateShape: Alchemy1
- type: entity
parent: CP14BaseKey
parent: CP14KeyIronBlank
id: CP14KeyAlchemy2
suffix: Alchemy 2
components:

View File

@@ -1,5 +1,5 @@
- type: entity
parent: CP14BaseKey
parent: CP14KeyIronBlank
id: CP14KeyTavernBlacksmithAbstract
suffix: Abstract Blacksmith
components:
@@ -7,7 +7,7 @@
group: Blacksmith
- type: entity
parent: CP14BaseKey
parent: CP14KeyIronBlank
id: CP14KeyBlacksmith
suffix: Blacksmith 1
components:
@@ -15,7 +15,7 @@
autoGenerateShape: Blacksmith1
- type: entity
parent: CP14BaseKey
parent: CP14KeyIronBlank
id: CP14KeyBlacksmith2
suffix: Blacksmith 2
components:

View File

@@ -1,5 +1,5 @@
- type: entity
parent: CP14BaseKey
parent: CP14KeyIronBlank
id: CP14KeyGuardEntrance
suffix: Guard Entrance
components:
@@ -7,7 +7,7 @@
autoGenerateShape: GuardEntrance
- type: entity
parent: CP14BaseKey
parent: CP14KeyIronBlank
id: CP14KeyGuard
suffix: Guard
components:
@@ -15,7 +15,7 @@
autoGenerateShape: Guard
- type: entity
parent: CP14BaseKey
parent: CP14KeyMithrilBlank
id: CP14KeyGuardCommander
suffix: Guard Commander
components:
@@ -23,7 +23,7 @@
autoGenerateShape: GuardCommander
- type: entity
parent: CP14BaseKey
parent: CP14KeyMithrilBlank
id: CP14KeyGuardWeaponStorage
suffix: Guard Weapon Storage
components:

View File

@@ -1,5 +1,5 @@
- type: entity
parent: CP14BaseKey
parent: CP14KeyGoldBlank
id: CP14KeyGuildmaster
suffix: Guildmaster
components:
@@ -7,7 +7,7 @@
autoGenerateShape: Guildmaster
- type: entity
parent: CP14BaseKey
parent: CP14KeyGoldBlank
id: CP14KeyDemiplaneCrystal
suffix: Demiplane Crystal
components:

View File

@@ -1,5 +1,5 @@
- type: entity
parent: CP14BaseKey
parent: CP14KeyIronBlank
id: CP14KeyTavernMerchantShopAbstract
suffix: Abstract Merchant shop
components:
@@ -7,7 +7,7 @@
group: Merchant
- type: entity
parent: CP14BaseKey
parent: CP14KeyIronBlank
id: CP14KeyMercantShop1
suffix: Merchant shop 1
components:
@@ -15,7 +15,7 @@
autoGenerateShape: Shop1
- type: entity
parent: CP14BaseKey
parent: CP14KeyIronBlank
id: CP14KeyMercantShop2
suffix: Merchant shop 2
components:
@@ -23,7 +23,7 @@
autoGenerateShape: Shop2
- type: entity
parent: CP14BaseKey
parent: CP14KeyIronBlank
id: CP14KeyMercantShop3
suffix: Merchant shop 3
components:

View File

@@ -1,5 +1,5 @@
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyPersonalHouseAbstract
suffix: Abstract Personal house
components:
@@ -7,12 +7,12 @@
group: PersonalHouse
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyPersonalHouseAbstractLoadoutDummy
name: a key to a random personal home (limited per map)
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyPersonalHouse1
suffix: PersonalHouse1
components:
@@ -20,7 +20,7 @@
autoGenerateShape: PersonalHouse1
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyPersonalHouse2
suffix: PersonalHouse2
components:
@@ -28,7 +28,7 @@
autoGenerateShape: PersonalHouse2
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyPersonalHouse3
suffix: PersonalHouse3
components:
@@ -36,7 +36,7 @@
autoGenerateShape: PersonalHouse3
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyPersonalHouse4
suffix: PersonalHouse4
components:
@@ -44,7 +44,7 @@
autoGenerateShape: PersonalHouse4
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyPersonalHouse5
suffix: PersonalHouse5
components:
@@ -52,7 +52,7 @@
autoGenerateShape: PersonalHouse5
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyPersonalHouse6
suffix: PersonalHouse6
components:
@@ -60,7 +60,7 @@
autoGenerateShape: PersonalHouse6
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyPersonalHouse7
suffix: PersonalHouse7
components:
@@ -68,7 +68,7 @@
autoGenerateShape: PersonalHouse7
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyPersonalHouse8
suffix: PersonalHouse8
components:
@@ -76,7 +76,7 @@
autoGenerateShape: PersonalHouse8
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyPersonalHouse9
suffix: PersonalHouse9
components:
@@ -84,7 +84,7 @@
autoGenerateShape: PersonalHouse9
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyPersonalHouse10
suffix: PersonalHouse10
components:
@@ -92,7 +92,7 @@
autoGenerateShape: PersonalHouse10
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyPersonalHouse11
suffix: PersonalHouse11
components:
@@ -100,7 +100,7 @@
autoGenerateShape: PersonalHouse11
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyPersonalHouse12
suffix: PersonalHouse12
components:
@@ -108,7 +108,7 @@
autoGenerateShape: PersonalHouse12
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyPersonalHouse13
suffix: PersonalHouse13
components:
@@ -116,7 +116,7 @@
autoGenerateShape: PersonalHouse13
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyPersonalHouse14
suffix: PersonalHouse14
components:
@@ -124,7 +124,7 @@
autoGenerateShape: PersonalHouse14
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyPersonalHouse15
suffix: PersonalHouse15
components:
@@ -132,7 +132,7 @@
autoGenerateShape: PersonalHouse15
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyPersonalHouse16
suffix: PersonalHouse16
components:

View File

@@ -1,5 +1,5 @@
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyTavernHall
suffix: Tavern Hall
components:
@@ -7,7 +7,7 @@
autoGenerateShape: TavernHall
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyTavernStaff
suffix: Tavern Staff
components:
@@ -15,7 +15,7 @@
autoGenerateShape: TavernStaff
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyTavernDormsAbstract
suffix: Abstract Tavern Dorms
components:
@@ -23,7 +23,7 @@
group: TavernDorms
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyTavernDorms1
suffix: Tavern Dorms 1
components:
@@ -31,7 +31,7 @@
autoGenerateShape: TavernDorms1
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyTavernDorms2
suffix: Tavern Dorms 2
components:
@@ -39,7 +39,7 @@
autoGenerateShape: TavernDorms2
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyTavernDorms3
suffix: Tavern Dorms 3
components:
@@ -47,7 +47,7 @@
autoGenerateShape: TavernDorms3
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyTavernDorms4
suffix: Tavern Dorms 4
components:
@@ -55,7 +55,7 @@
autoGenerateShape: TavernDorms4
- type: entity
parent: CP14BaseKey
parent: CP14KeyCopperBlank
id: CP14KeyTavernDorms5
suffix: Tavern Dorms 5
components:

View File

@@ -1,62 +0,0 @@
- type: entity
parent: BaseItem
id: CP14BaseKey
abstract: true
categories: [ ForkFiltered ]
name: key
description: A small, intricate piece of metal that opens some locks. Don't give it to anyone!
components:
- type: Tag
tags:
- CP14Key
- type: Item
size: Tiny
- type: Sprite
sprite: _CP14/Objects/keys.rsi
layers:
- state: key1
map: [ "random" ]
- type: RandomSprite
available:
- random:
key1: ""
key2: ""
key3: ""
key4: ""
key5: ""
key6: ""
key7: ""
key8: ""
key9: ""
key10: ""
key11: ""
key12: ""
key13: ""
key14: ""
key15: ""
key16: ""
key17: ""
key18: ""
- type: CP14Key
- type: EmitSoundOnLand
sound:
path: /Audio/_CP14/Items/key_drop.ogg
params:
variation: 0.05
- type: entity
parent: BaseItem
id: CP14BaseLockpick
name: lockpick
description: A thief's tool that, with proper skill and skill, allows you to pick any lock.
categories: [ ForkFiltered ]
components:
- type: Item
storedRotation: -90
- type: Sprite
sprite: _CP14/Objects/keys.rsi
state: lockpick
- type: CP14Lockpick
- type: Tag
tags:
- CP14Lockpick

View File

@@ -0,0 +1,78 @@
- type: entity
parent: BaseItem
id: CP14BaseKey
abstract: true
categories: [ ForkFiltered ]
name: key
description: A small, intricate piece of metal that opens some locks. Don't give it to anyone!
components:
- type: Tag
tags:
- CP14Key
- type: Item
size: Tiny
- type: Sprite
sprite: _CP14/Objects/keys.rsi
- type: CP14Key
- type: EmitSoundOnLand
sound:
path: /Audio/_CP14/Items/key_drop.ogg
params:
variation: 0.05
- type: entity
parent: CP14BaseKey
id: CP14KeyCopperBlank
components:
- type: Sprite
state: key_copper
- type: CP14Key
lockShape:
- 2
- 2
- 2
- type: entity
parent: CP14BaseKey
id: CP14KeyIronBlank
components:
- type: Sprite
state: key_iron
- type: CP14Key
lockShape:
- 2
- 2
- 2
- 2
- 2
- type: entity
parent: CP14BaseKey
id: CP14KeyGoldBlank
components:
- type: Sprite
state: key_gold
- type: CP14Key
lockShape:
- 2
- 2
- 2
- 2
- 2
- 2
- type: entity
parent: CP14BaseKey
id: CP14KeyMithrilBlank
components:
- type: Sprite
state: key_mithril
- type: CP14Key
lockShape:
- 2
- 2
- 2
- 2
- 2
- 2
- 2

View File

@@ -0,0 +1,76 @@
- type: entity
parent: BaseItem
id: CP14BaseLock
abstract: true
categories: [ ForkFiltered ]
name: lock
description: A small device customized only for a specific key shape. Attach it to doors or chests that have no lock and feel the spirit of security.
components:
- type: Item
size: Tiny
- type: Sprite
sprite: _CP14/Objects/keys.rsi
- type: EmitSoundOnLand
sound:
path: /Audio/Items/welder_drop.ogg
params:
variation: 0.05
- type: CP14Lock
canEmbedded: true
- type: entity
parent: CP14BaseLock
id: CP14LockCopper
components:
- type: Sprite
state: lock_copper
- type: CP14Lock
lockShape:
- 2
- 2
- 2
- type: entity
parent: CP14BaseLock
id: CP14LockIron
components:
- type: Sprite
state: lock_iron
- type: CP14Lock
lockShape:
- 2
- 2
- 2
- 2
- 2
- type: entity
parent: CP14BaseLock
id: CP14LockGold
components:
- type: Sprite
state: lock_gold
- type: CP14Lock
lockShape:
- 2
- 2
- 2
- 2
- 2
- 2
- type: entity
parent: CP14BaseLock
id: CP14LockMithril
components:
- type: Sprite
state: lock_mithril
- type: CP14Lock
lockShape:
- 2
- 2
- 2
- 2
- 2
- 2
- 2

View File

@@ -0,0 +1,43 @@
- type: entity
parent: BaseItem
id: CP14BaseLockpick
name: iron lockpick
description: A thief's tool that, with proper skill and skill, allows you to pick any lock.
categories: [ ForkFiltered ]
components:
- type: Item
storedRotation: -90
- type: Sprite
sprite: _CP14/Objects/keys.rsi
state: lockpick_iron
- type: CP14Lockpick
health: 10
- type: Tag
tags:
- CP14Lockpick
- type: entity
parent: CP14BaseLockpick
id: CP14LockpickMithril
name: mithril lockpick
components:
- type: CP14Lockpick
health: 50
- type: Sprite
state: lockpick_mithril
- type: entity
parent: BaseItem
id: CP14KeyFile
name: key file
description: A file, ideal for sharpening keys, and reshaping them.
categories: [ ForkFiltered ]
components:
- type: Item
storedRotation: -45
- type: Sprite
sprite: _CP14/Objects/keys.rsi
state: file
- type: CP14KeyFile
- type: UseDelay
delay: 1.0

View File

@@ -0,0 +1,13 @@
- type: entity
parent: Screwdriver
id: CP14Screwdriver
categories: [ ForkFiltered ]
components:
- type: CP14LockEditer
- type: UseDelay
delay: 1.0
- type: MeleeWeapon
attackRate: 1
damage:
types:
Piercing: 4

View File

@@ -1,38 +0,0 @@
- type: entity
id: CP14BaseCrowbar
parent:
- BaseItem
- CP14BaseWeaponDestructible
- CP14BaseWeaponChemical
name: crowbar
description: A versatile and useful iron, for taking apart floors or other objects.
components:
- type: EmitSoundOnLand
sound:
path: /Audio/Items/crowbar_drop.ogg
- type: Tag
tags:
- Crowbar
- type: MeleeWeapon
wideAnimationRotation: -135
damage:
types:
Blunt: 7
soundHit:
collection: MetalThud
- type: Tool
qualities:
- Prying
useSound:
path: /Audio/Items/crowbar.ogg
- type: ToolTileCompatible
- type: Prying
- type: Sprite
sprite: _CP14/Objects/Tools/crowbar.rsi
layers:
- state: icon
- type: Item
sprite: _CP14/Objects/Tools/crowbar.rsi
size: Normal
shape:
- 0,0,0,1

View File

@@ -0,0 +1,50 @@
- type: entity
parent: CP14WoodenDoor
id: CP14WoodenDoorRandomLocked
suffix: Random Locked (Complex 3)
components:
- type: CP14Lock
autoGenerateRandomShape: 3
- type: Lock
locked: true
- type: entity
parent: CP14WoodenDoorWindowed
id: CP14WoodenDoorWindowedRandomLocked
suffix: Random Locked (Complex 3)
components:
- type: CP14Lock
autoGenerateRandomShape: 3
- type: Lock
locked: true
- type: entity
parent: CP14IronDoor
id: CP14IronDoorRandomLocked
suffix: Random Locked (Complex 5)
components:
- type: CP14Lock
autoGenerateRandomShape: 5
- type: Lock
locked: true
- type: entity
parent: CP14IronDoorWindowed
id: CP14IronDoorWindowedRandomLocked
suffix: Random Locked (Complex 5)
components:
- type: CP14Lock
autoGenerateRandomShape: 5
- type: Lock
locked: true
- type: entity
parent: CP14FenceGateBigIron
id: CP14FenceGateBigIronRandomLocked
suffix: Random Locked (Complex 5)
components:
- type: CP14Lock
autoGenerateRandomShape: 5
- type: Lock
locked: true

View File

@@ -17,6 +17,7 @@
openDrawDepth: Mobs
- type: Lock
locked: false
- type: CP14Lock #Empty, for installing new locks
- type: PlacementReplacement
key: walls
- type: CP14DoorInteractionPopup

View File

@@ -99,6 +99,7 @@
sprite: _CP14/Structures/Specific/Alchemy/alchemy_furnace.rsi
normalState: burning
- type: Climbable
- type: Anchorable
- type: Fixtures
fixtures:
fix1:

View File

@@ -67,4 +67,6 @@
- type: ItemSlots
- type: StaticPrice
price: 50
- type: CP14Lock #Empty, for installing new locks
- type: Lock
locked: false

View File

@@ -45,67 +45,67 @@
- type: CP14LockType
id: Alchemy1
group: Alchemist
complexity: 4
complexity: 5
name: cp14-lock-shape-alchemist1
- type: CP14LockType
id: Alchemy2
group: Alchemist
complexity: 4
complexity: 5
name: cp14-lock-shape-alchemist2
- type: CP14LockType
id: Alchemy3
group: Alchemist
complexity: 4
complexity: 5
name: cp14-lock-shape-alchemist3
- type: CP14LockType
id: Blacksmith1
group: Blacksmith
complexity: 4
complexity: 5
name: cp14-lock-shape-blacksmith1
- type: CP14LockType
id: Blacksmith2
group: Blacksmith
complexity: 4
complexity: 5
name: cp14-lock-shape-blacksmith2
- type: CP14LockType
id: Blacksmith3
group: Blacksmith
complexity: 4
complexity: 5
name: cp14-lock-shape-blacksmith3
- type: CP14LockType
id: Shop1
group: Merchant
complexity: 6
complexity: 5
name: cp14-lock-shape-merchant1
- type: CP14LockType
id: Shop2
group: Merchant
complexity: 6
complexity: 5
name: cp14-lock-shape-merchant2
- type: CP14LockType
id: Shop3
group: Merchant
complexity: 6
complexity: 5
name: cp14-lock-shape-merchant3
# Mercenary
- type: CP14LockType
id: Guildmaster
complexity: 5
complexity: 6
name: cp14-lock-shape-guildmaster
- type: CP14LockType
id: DemiplaneCrystal
complexity: 5
complexity: 6
name: cp14-lock-shape-demiplane-crystal
# Personal house
@@ -210,20 +210,20 @@
- type: CP14LockType
id: GuardEntrance
complexity: 3
complexity: 5
name: cp14-lock-shaper-guard-entrance
- type: CP14LockType
id: Guard
complexity: 4
complexity: 5
name: cp14-lock-shaper-guard-staff
- type: CP14LockType
id: GuardCommander
complexity: 5
complexity: 7
name: cp14-lock-shaper-guard-commander
- type: CP14LockType
id: GuardWeaponStorage
complexity: 5
complexity: 7
name: cp14-lock-shaper-guard-weapon-storage

View File

@@ -1,17 +1,30 @@
- type: modularPart
id: BaseBladePickaxe
modifiers:
- !type:AddComponents
override: true
components:
- type: Tool
qualities:
- Prying
useSound:
path: /Audio/Items/crowbar.ogg
- type: ToolTileCompatible
- type: Prying
- type: EmitSoundOnLand
sound:
path: /Audio/Items/crowbar_drop.ogg #Add to all modular weapons?
- !type:EditMeleeWeapon
attackRateMultiplier: 0.55
angleMultiplier: 1.2
bonusDamage:
types:
Piercing: 10
Structural: 6
Structural: 4
- !type:EditIncreaseDamageOnWield
bonusDamage:
types:
Piercing: 8
Piercing: 6
Structural: 17
- !type:EditItem
newSize: Normal

View File

@@ -10,7 +10,7 @@
southRotation: true
steps:
- material: CP14Dirt
amount: 3
amount: 5
doAfter: 2
- node: WallDirt
entity: CP14WallDirt

View File

@@ -11,16 +11,6 @@
count: 2
result: CP14BaseShield
- type: CP14Recipe
id: CP14BaseCrowbar
tag: CP14RecipeAnvil
craftTime: 4
requirements:
- !type:StackResource
stack: CP14IronBar
count: 2
result: CP14BaseCrowbar
- type: CP14Recipe
id: CP14BaseWrench
tag: CP14RecipeAnvil
@@ -31,6 +21,16 @@
count: 2
result: CP14BaseWrench
- type: CP14Recipe
id: CP14Screwdriver
tag: CP14RecipeAnvil
craftTime: 4
requirements:
- !type:StackResource
stack: CP14IronBar
count: 1
result: CP14Screwdriver
- type: CP14Recipe
id: CP14PlatePie
tag: CP14RecipeAnvil
@@ -148,6 +148,16 @@
count: 1
result: CP14BaseLockpick
- type: CP14Recipe
id: CP14LockpickMithril
tag: CP14RecipeAnvil
craftTime: 4
requirements:
- !type:StackResource
stack: CP14MithrilBar
count: 1
result: CP14LockpickMithril
- type: CP14Recipe
id: CP14BaseLightCrossbow
tag: CP14RecipeAnvil
@@ -173,3 +183,94 @@
stack: CP14IronBar
count: 2
result: CP14ClothingMaskSteelMask
- type: CP14Recipe
id: CP14KeyCopperBlank
tag: CP14RecipeAnvil
craftTime: 3
requirements:
- !type:StackResource
stack: CP14CopperBar
count: 1
result: CP14KeyCopperBlank
- type: CP14Recipe
id: CP14KeyIronBlank
tag: CP14RecipeAnvil
craftTime: 3
requirements:
- !type:StackResource
stack: CP14IronBar
count: 1
result: CP14KeyIronBlank
- type: CP14Recipe
id: CP14KeyGoldBlank
tag: CP14RecipeAnvil
craftTime: 3
requirements:
- !type:StackResource
stack: CP14GoldBar
count: 1
result: CP14KeyGoldBlank
- type: CP14Recipe
id: CP14KeyMithrilBlank
tag: CP14RecipeAnvil
craftTime: 3
requirements:
- !type:StackResource
stack: CP14MithrilBar
count: 1
result: CP14KeyMithrilBlank
- type: CP14Recipe
id: CP14KeyFile
tag: CP14RecipeAnvil
craftTime: 2
requirements:
- !type:StackResource
stack: CP14IronBar
count: 1
result: CP14KeyFile
- type: CP14Recipe
id: CP14LockCopper
tag: CP14RecipeAnvil
craftTime: 2
requirements:
- !type:StackResource
stack: CP14CopperBar
count: 1
result: CP14LockCopper
- type: CP14Recipe
id: CP14LockIron
tag: CP14RecipeAnvil
craftTime: 2
requirements:
- !type:StackResource
stack: CP14IronBar
count: 1
result: CP14LockIron
- type: CP14Recipe
id: CP14LockGold
tag: CP14RecipeAnvil
craftTime: 2
requirements:
- !type:StackResource
stack: CP14GoldBar
count: 1
result: CP14LockGold
- type: CP14Recipe
id: CP14LockMithril
tag: CP14RecipeAnvil
craftTime: 2
requirements:
- !type:StackResource
stack: CP14MithrilBar
count: 1
result: CP14LockMithril

Binary file not shown.

Before

Width:  |  Height:  |  Size: 255 B

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 B

After

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 B

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 B

After

Width:  |  Height:  |  Size: 270 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 463 B

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 479 B

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 451 B

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 451 B

After

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 415 B

View File

@@ -1,22 +0,0 @@
{
"version": 1,
"license": "All right reserved",
"copyright": "Created by Jaraten (Github)",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "icon"
},
{
"name": "inhand-left",
"directions": 4
},
{
"name": "inhand-right",
"directions": 4
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 248 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

View File

Before

Width:  |  Height:  |  Size: 272 B

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

View File

@@ -8,64 +8,37 @@
"copyright": "Created by TheShuEd (Github) ",
"states": [
{
"name": "key1"
"name": "file"
},
{
"name": "key2"
"name": "key_iron"
},
{
"name": "key3"
"name": "key_gold"
},
{
"name": "key4"
"name": "key_copper"
},
{
"name": "key5"
"name": "key_mithril"
},
{
"name": "key6"
"name": "lock_iron"
},
{
"name": "key7"
"name": "lock_copper"
},
{
"name": "key8"
"name": "lock_gold"
},
{
"name": "key9"
"name": "lock_mithril"
},
{
"name": "key10"
"name": "lockpick_iron"
},
{
"name": "key11"
},
{
"name": "key12"
},
{
"name": "key13"
},
{
"name": "key14"
},
{
"name": "key15"
},
{
"name": "key16"
},
{
"name": "key17"
},
{
"name": "key18"
},
{
"name": "lock"
},
{
"name": "lockpick"
"name": "lockpick_mithril"
},
{
"name": "keyring"
@@ -81,9 +54,6 @@
},
{
"name": "ring-3"
},
{
"name": "vault_key"
}
]
}

View File

@@ -329,6 +329,7 @@ CP14WallStonebrickCrushedMedium: CP14WallFrameStonebrick
CP14WallStonebrickCrushedLow: CP14WallFrameStonebrick
CP14WallCyan: CP14WallStonebrick
CP14FrameWooden: CP14WallFrameWooden
CP14BaseCrowbar: CP14ModularIronPickaxe
# <---> CrystallEdge migration zone end