Merge remote-tracking branch 'WD-core/master' into upstream-5

This commit is contained in:
BIGZi0348
2024-11-23 18:44:29 +03:00
34 changed files with 499 additions and 199 deletions

View File

@@ -1,5 +1,6 @@
using Content.Shared._White.Mood;
using Content.Shared.Dataset;
using Content.Shared.FixedPoint;
using Content.Shared.NPC.Prototypes;
using Content.Shared.Random;
using Content.Shared.Roles;
@@ -34,7 +35,25 @@ public sealed partial class TraitorRuleComponent : Component
[DataField]
public ProtoId<DatasetPrototype> ObjectiveIssuers = "TraitorCorporations";
// WD EDIT START AHEAD OF WIZDEN UPSTREAM
/// <summary>
/// Give this traitor an Uplink on spawn.
/// </summary>
[DataField]
public bool GiveUplink = true;
/// <summary>
/// Give this traitor the codewords.
/// </summary>
[DataField]
public bool GiveCodewords = true;
/// <summary>
/// Give this traitor a briefing in chat.
/// </summary>
[DataField]
public bool GiveBriefing = true;
// WD EDIT END AHEAD OF WIZDEN UPSTREAM
// WD edit start
[DataField]
public ProtoId<MoodEffectPrototype> MoodBuffEffect = "TraitorFocused";
@@ -77,7 +96,7 @@ public sealed partial class TraitorRuleComponent : Component
/// The amount of TC traitors start with.
/// </summary>
[DataField]
public int StartingBalance = 20;
public FixedPoint2 StartingBalance = 20; // WD EDIT AHEAD OF WIZDEN UPSTREAM
[DataField]
public int MaxDifficulty = 5;

View File

@@ -5,6 +5,7 @@ using Content.Server.Objectives;
using Content.Server.PDA.Ringer;
using Content.Server.Roles;
using Content.Server.Traitor.Uplink;
using Content.Shared.FixedPoint;
using Content.Shared.Mind;
using Content.Shared.NPC.Systems;
using Content.Shared.Objectives.Components;
@@ -74,7 +75,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
}
}
public bool MakeTraitor(EntityUid traitor, TraitorRuleComponent component, bool giveUplink = true, bool giveObjectives = true)
public bool MakeTraitor(EntityUid traitor, TraitorRuleComponent component, bool giveObjectives = true) // WD EDIT AHEAD OF WIZDEN UPSTREAM
{
//Grab the mind if it wasnt provided
if (!_mindSystem.TryGetMind(traitor, out var mindId, out var mind))
@@ -83,39 +84,46 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
// WD START
var richAspect = _gameTicker.GetActiveGameRules().Where(HasComp<TraitorRichAspectComponent>).Any();
// WD END
// WD EDIT START AHEAD OF WIZDEN UPSTREAM
var briefing = "";
var briefing = Loc.GetString("traitor-role-codewords-short", ("codewords", string.Join(", ", component.Codewords)));
if (component.GiveCodewords)
briefing = Loc.GetString("traitor-role-codewords-short", ("codewords", string.Join(", ", component.Codewords)));
// WD EDIT END AHEAD OF WIZDEN UPSTREAM
var issuer = _random.Pick(_prototypeManager.Index(component.ObjectiveIssuers).Values);
Note[]? code = null;
if (giveUplink)
if (component.GiveUplink) // WD EDIT AHEAD OF WIZDEN UPSTREAM
{
// Calculate the amount of currency on the uplink.
var startingBalance = component.StartingBalance;
if (_jobs.MindTryGetJob(mindId, out _, out var prototype))
startingBalance = Math.Max(startingBalance - prototype.AntagAdvantage, 0);
// WD EDIT START START AHEAD OF WIZDEN UPSTREAM
{
if (startingBalance < prototype.AntagAdvantage) // Can't use Math functions on FixedPoint2
startingBalance = 0;
else
startingBalance = startingBalance - prototype.AntagAdvantage;
}
if (richAspect)
{
startingBalance += 10;
}
// creadth: we need to create uplink for the antag.
// PDA should be in place already
var pda = _uplink.FindUplinkTarget(traitor);
if (pda == null || !_uplink.AddUplink(traitor, startingBalance))
return false;
// Give traitors their codewords and uplink code to keep in their character info menu
code = EnsureComp<RingerUplinkComponent>(pda.Value).Code;
// If giveUplink is false the uplink code part is omitted
briefing = string.Format("{0}\n{1}", briefing,
Loc.GetString("traitor-role-uplink-code-short", ("code", string.Join("-", code).Replace("sharp", "#"))));
// Choose and generate an Uplink, and return the uplink code if applicable
var uplinkParams = RequestUplink(traitor, startingBalance, briefing);
code = uplinkParams.Item1;
briefing = uplinkParams.Item2;
}
_antag.SendBriefing(traitor, GenerateBriefing(component.Codewords, code, issuer), null, component.GreetSoundNotification);
string[]? codewords = null;
if (component.GiveCodewords)
codewords = component.Codewords;
if (component.GiveBriefing)
_antag.SendBriefing(traitor, GenerateBriefing(codewords, code, issuer), null, component.GreetSoundNotification);
// WD EDIT END AHEAD OF WIZDEN UPSTREAM
component.TraitorMinds.Add(mindId);
// Assign briefing
@@ -146,7 +154,33 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
return true;
}
// WD EDIT START AHEAD OF WIZDEN UPSTREAM
private (Note[]?, string) RequestUplink(EntityUid traitor, FixedPoint2 startingBalance, string briefing)
{
var pda = _uplink.FindUplinkTarget(traitor);
Note[]? code = null;
var uplinked = _uplink.AddUplink(traitor, startingBalance, pda, true);
if (pda is not null && uplinked)
{
// Codes are only generated if the uplink is a PDA
code = EnsureComp<RingerUplinkComponent>(pda.Value).Code;
// If giveUplink is false the uplink code part is omitted
briefing = string.Format("{0}\n{1}",
briefing,
Loc.GetString("traitor-role-uplink-code-short", ("code", string.Join("-", code).Replace("sharp", "#"))));
return (code, briefing);
}
else if (pda is null && uplinked)
{
briefing += "\n" + Loc.GetString("traitor-role-uplink-implant-short");
}
return (null, briefing);
}
// WD EDIT END AHEAD OF WIZDEN UPSTREAM
private void OnObjectivesTextGetInfo(EntityUid uid, TraitorRuleComponent comp, ref ObjectivesTextGetInfoEvent args)
{
args.Minds = _antag.GetAntagMindEntityUids(uid);
@@ -158,13 +192,16 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
args.Text += "\n" + Loc.GetString("traitor-round-end-codewords", ("codewords", string.Join(", ", comp.Codewords)));
}
private string GenerateBriefing(string[] codewords, Note[]? uplinkCode, string? objectiveIssuer = null)
private string GenerateBriefing(string[]? codewords, Note[]? uplinkCode, string? objectiveIssuer = null)
{
var sb = new StringBuilder();
sb.AppendLine(Loc.GetString("traitor-role-greeting", ("corporation", objectiveIssuer ?? Loc.GetString("objective-issuer-unknown"))));
sb.AppendLine(Loc.GetString("traitor-role-codewords-short", ("codewords", string.Join(", ", codewords))));
if (codewords != null) // WD EDIT AHEAD OF WIZDEN UPSTREAM
sb.AppendLine(Loc.GetString("traitor-role-codewords", ("codewords", string.Join(", ", codewords))));
if (uplinkCode != null)
sb.AppendLine(Loc.GetString("traitor-role-uplink-code-short", ("code", string.Join("-", uplinkCode).Replace("sharp", "#"))));
else // WD EDIT AHEAD OF WIZDEN UPSTREAM
sb.AppendLine(Loc.GetString("traitor-role-uplink-implant"));
return sb.ToString();
}

View File

@@ -1,4 +1,5 @@
using Content.Server.Traitor.Systems;
using Robust.Shared.Prototypes;
namespace Content.Server.Traitor.Components;
@@ -9,14 +10,8 @@ namespace Content.Server.Traitor.Components;
public sealed partial class AutoTraitorComponent : Component
{
/// <summary>
/// Whether to give the traitor an uplink or not.
/// The traitor profile to use
/// </summary>
[DataField("giveUplink"), ViewVariables(VVAccess.ReadWrite)]
public bool GiveUplink = true;
/// <summary>
/// Whether to give the traitor objectives or not.
/// </summary>
[DataField("giveObjectives"), ViewVariables(VVAccess.ReadWrite)]
public bool GiveObjectives = true;
[DataField]
public EntProtoId Profile = "Traitor"; // WD EDIT AHEAD OF WIZDEN UPSTREAM
}

View File

@@ -12,9 +12,6 @@ public sealed class AutoTraitorSystem : EntitySystem
{
[Dependency] private readonly AntagSelectionSystem _antag = default!;
[ValidatePrototypeId<EntityPrototype>]
private const string DefaultTraitorRule = "Traitor";
public override void Initialize()
{
base.Initialize();
@@ -24,6 +21,6 @@ public sealed class AutoTraitorSystem : EntitySystem
private void OnMindAdded(EntityUid uid, AutoTraitorComponent comp, MindAddedMessage args)
{
_antag.ForceMakeAntag<AutoTraitorComponent>(args.Mind.Comp.Session, DefaultTraitorRule);
_antag.ForceMakeAntag<AutoTraitorComponent>(args.Mind.Comp.Session, comp.Profile); // WD EDIT AHEAD OF WIZDEN UPSTREAM
}
}

View File

@@ -0,0 +1,7 @@
namespace Content.Server.Traitor.Uplink;
/// <summary>
/// This is used for identifying something as a hidden uplink and showing the UI.
/// </summary>
[RegisterComponent]
public sealed partial class UplinkComponent : Component;

View File

@@ -1,94 +1,130 @@
using Content.Server.Store.Systems;
using Content.Shared.FixedPoint;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Implants;
using Content.Shared.Inventory;
using Content.Shared.PDA;
using Content.Server.Store.Components;
using Content.Shared.FixedPoint;
using Content.Shared.Store;
using Content.Server.Store.Components;
using Robust.Shared.Prototypes;
namespace Content.Server.Traitor.Uplink
namespace Content.Server.Traitor.Uplink;
public sealed class UplinkSystem : EntitySystem // WD EDIT AHEAD OF WIZDEN UPSTREAM
{
public sealed class UplinkSystem : EntitySystem
[Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly StoreSystem _store = default!;
[Dependency] private readonly SharedSubdermalImplantSystem _subdermalImplant = default!;
[ValidatePrototypeId<CurrencyPrototype>]
public const string TelecrystalCurrencyPrototype = "Telecrystal";
private const string FallbackUplinkImplant = "UplinkImplant";
private const string FallbackUplinkCatalog = "UplinkUplinkImplanter";
/// <summary>
/// Adds an uplink to the target
/// </summary>
/// <param name="user">The person who is getting the uplink</param>
/// <param name="balance">The amount of currency on the uplink. If null, will just use the amount specified in the preset.</param>
/// <param name="uplinkEntity">The entity that will actually have the uplink functionality. Defaults to the PDA if null.</param>
/// <param name="giveDiscounts">Marker that enables discounts for uplink items.</param>
/// <returns>Whether or not the uplink was added successfully</returns>
public bool AddUplink(
EntityUid user,
FixedPoint2 balance,
EntityUid? uplinkEntity = null,
bool giveDiscounts = false)
{
[Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
[Dependency] private readonly StoreSystem _store = default!;
// Try to find target item if none passed
uplinkEntity ??= FindUplinkTarget(user);
if (uplinkEntity == null)
return ImplantUplink(user, balance, giveDiscounts);
[ValidatePrototypeId<CurrencyPrototype>]
public const string TelecrystalCurrencyPrototype = "Telecrystal";
EnsureComp<UplinkComponent>(uplinkEntity.Value);
/// <summary>
/// Gets the amount of TC on an "uplink"
/// Mostly just here for legacy systems based on uplink.
/// </summary>
/// <param name="component"></param>
/// <returns>the amount of TC</returns>
public int GetTCBalance(StoreComponent component)
SetUplink(user, uplinkEntity.Value, balance, giveDiscounts);
// TODO add BUI. Currently can't be done outside of yaml -_-
// ^ What does this even mean?
return true;
}
/// <summary>
/// Configure TC for the uplink
/// </summary>
private void SetUplink(EntityUid user, EntityUid uplink, FixedPoint2 balance, bool giveDiscounts)
{
var store = EnsureComp<StoreComponent>(uplink);
store.AccountOwner = user;
_store.InitializeFromPreset("StorePresetUplink", uplink, store); // WD
store.Balance.Clear();
_store.TryAddCurrency(new Dictionary<string, FixedPoint2> { { TelecrystalCurrencyPrototype, balance } },
uplink,
store);
// WD REMOVED UNTIL PROPER UPSTREAM
// var uplinkInitializedEvent = new StoreInitializedEvent(
// TargetUser: user,
// Store: uplink,
// UseDiscounts: giveDiscounts,
// Listings: _store.GetAvailableListings(user, uplink, store)
// .ToArray());
// RaiseLocalEvent(ref uplinkInitializedEvent);
}
/// <summary>
/// Implant an uplink as a fallback measure if the traitor had no PDA
/// </summary>
private bool ImplantUplink(EntityUid user, FixedPoint2 balance, bool giveDiscounts)
{
var implantProto = new string(FallbackUplinkImplant);
if (!_proto.TryIndex<ListingPrototype>(FallbackUplinkCatalog, out var catalog))
return false;
if (!catalog.Cost.TryGetValue(TelecrystalCurrencyPrototype, out var cost))
return false;
if (balance < cost) // Can't use Math functions on FixedPoint2
balance = 0;
else
balance = balance - cost;
var implant = _subdermalImplant.AddImplant(user, implantProto);
if (!HasComp<StoreComponent>(implant))
return false;
SetUplink(user, implant.Value, balance, giveDiscounts);
return true;
}
/// <summary>
/// Finds the entity that can hold an uplink for a user.
/// Usually this is a pda in their pda slot, but can also be in their hands. (but not pockets or inside bag, etc.)
/// </summary>
public EntityUid? FindUplinkTarget(EntityUid user)
{
// Try to find PDA in inventory
if (_inventorySystem.TryGetContainerSlotEnumerator(user, out var containerSlotEnumerator))
{
FixedPoint2? tcBalance = component.Balance.GetValueOrDefault(TelecrystalCurrencyPrototype);
return tcBalance?.Int() ?? 0;
while (containerSlotEnumerator.MoveNext(out var pdaUid))
{
if (!pdaUid.ContainedEntity.HasValue)
continue;
if (HasComp<PdaComponent>(pdaUid.ContainedEntity.Value) || HasComp<StoreComponent>(pdaUid.ContainedEntity.Value))
return pdaUid.ContainedEntity.Value;
}
}
// Also check hands
foreach (var item in _handsSystem.EnumerateHeld(user))
{
if (HasComp<PdaComponent>(item) || HasComp<StoreComponent>(item))
return item;
}
/// <summary>
/// Adds an uplink to the target
/// </summary>
/// <param name="user">The person who is getting the uplink</param>
/// <param name="balance">The amount of currency on the uplink. If null, will just use the amount specified in the preset.</param>
/// <param name="uplinkPresetId">The id of the storepreset</param>
/// <param name="uplinkEntity">The entity that will actually have the uplink functionality. Defaults to the PDA if null.</param>
/// <returns>Whether or not the uplink was added successfully</returns>
public bool AddUplink(EntityUid user, FixedPoint2? balance, string uplinkPresetId = "StorePresetUplink", EntityUid? uplinkEntity = null)
{
// Try to find target item
if (uplinkEntity == null)
{
uplinkEntity = FindUplinkTarget(user);
if (uplinkEntity == null)
return false;
}
var store = EnsureComp<StoreComponent>(uplinkEntity.Value);
_store.InitializeFromPreset(uplinkPresetId, uplinkEntity.Value, store);
store.AccountOwner = user;
store.Balance.Clear();
if (balance != null)
{
store.Balance.Clear();
_store.TryAddCurrency(new Dictionary<string, FixedPoint2> { { TelecrystalCurrencyPrototype, balance.Value } }, uplinkEntity.Value, store);
}
// TODO add BUI. Currently can't be done outside of yaml -_-
return true;
}
/// <summary>
/// Finds the entity that can hold an uplink for a user.
/// Usually this is a pda in their pda slot, but can also be in their hands. (but not pockets or inside bag, etc.)
/// </summary>
public EntityUid? FindUplinkTarget(EntityUid user)
{
// Try to find PDA in inventory
if (_inventorySystem.TryGetContainerSlotEnumerator(user, out var containerSlotEnumerator))
{
while (containerSlotEnumerator.MoveNext(out var pdaUid))
{
if (!pdaUid.ContainedEntity.HasValue) continue;
if (HasComp<PdaComponent>(pdaUid.ContainedEntity.Value) || HasComp<StoreComponent>(pdaUid.ContainedEntity.Value))
return pdaUid.ContainedEntity.Value;
}
}
// Also check hands
foreach (var item in _handsSystem.EnumerateHeld(user))
{
if (HasComp<PdaComponent>(item) || HasComp<StoreComponent>(item))
return item;
}
return null;
}
return null;
}
}

View File

@@ -108,22 +108,38 @@ public abstract class SharedSubdermalImplantSystem : EntitySystem
/// </summary>
public void AddImplants(EntityUid uid, IEnumerable<String> implants)
{
var coords = Transform(uid).Coordinates;
foreach (var id in implants)
{
var ent = Spawn(id, coords);
if (TryComp<SubdermalImplantComponent>(ent, out var implant))
{
ForceImplant(uid, ent, implant);
}
else
{
Log.Warning($"Found invalid starting implant '{id}' on {uid} {ToPrettyString(uid):implanted}");
Del(ent);
}
AddImplant(uid, id);
}
}
/// <summary>
/// Adds a single implant to a person, and returns the implant.
/// Logs any implant ids that don't have <see cref="SubdermalImplantComponent"/>.
/// </summary>
/// <returns>
/// The implant, if it was successfully created. Otherwise, null.
/// </returns>>
public EntityUid? AddImplant(EntityUid uid, String implantId) // WD EDIT AHEAD OF WIZDEN UPSTREAM
{
var coords = Transform(uid).Coordinates;
var ent = Spawn(implantId, coords);
if (TryComp<SubdermalImplantComponent>(ent, out var implant))
{
ForceImplant(uid, ent, implant);
}
else
{
Log.Warning($"Found invalid starting implant '{implantId}' on {uid} {ToPrettyString(uid):implanted}");
Del(ent);
return null;
}
return ent;
}
/// <summary>
/// Forces an implant into a person
/// Good for on spawn related code or admin additions
@@ -184,7 +200,7 @@ public abstract class SharedSubdermalImplantSystem : EntitySystem
var relayEv = new ImplantRelayEvent<T>(args);
foreach (var implant in implantContainer.ContainedEntities)
{
if (args is HandledEntityEventArgs { Handled : true })
if (args is HandledEntityEventArgs { Handled: true })
return;
RaiseLocalEvent(implant, relayEv);
@@ -223,7 +239,7 @@ public abstract class SharedSubdermalImplantSystem : EntitySystem
// Remove the implant from the donor's implant container
_container.Remove(donorImplant, donorImplantContainer, force: true);
if(!TryComp<SubdermalImplantComponent>(donorImplant, out var subdermal))
if (!TryComp<SubdermalImplantComponent>(donorImplant, out var subdermal))
return;
// Insert the implant into the recipient's implant container

View File

@@ -1,50 +1,4 @@
Entries:
- author: KettlebellOfCreation
changes:
- message: "\u0414\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u0430 \u0430\u043D\u0442\
\u0438\u0441\u043F\u0430\u043C \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430\
, \u0438 \u043A\u0443\u043B\u0434\u0430\u0443\u043D \u043D\u0430 \u043B\u044E\
\u0431\u044B\u0435 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u044F"
type: Add
id: 108
time: '2023-03-06T20:39:24.0000000+00:00'
- author: rhailrake
changes:
- message: "\u0424\u0438\u043A\u0441 \u043F\u043E\u0447\u0438\u043D\u043A\u0438\
\ \u0431\u043E\u0440\u0433\u043E\u0432! \u0410\u0411\u0423\u0417 \u041F\u0420\
\u0418\u041D\u042F\u041B \u0418\u0421\u041B\u0410\u041C"
type: Fix
id: 109
time: '2023-03-09T15:17:32.0000000+00:00'
- author: Valtos
changes:
- message: "\u0420\u0430\u0437\u0434\u0435\u043B\u044C\u043D\u044B\u0435 \u0431\u0430\
\u043D\u044B \u0434\u043B\u044F \u043A\u0430\u0436\u0434\u043E\u0433\u043E \u0438\
\u0437 \u0441\u0435\u0440\u0432\u0435\u0440\u043E\u0432. \u0421\u0442\u0430\u0440\
\u044B\u0435 \u0431\u0430\u043D\u044B \u0432\u0441\u0451 \u0435\u0449\u0451\
\ \u0440\u0430\u0431\u043E\u0442\u0430\u044E\u0442 \u043D\u0430 \u0432\u0441\
\u0435\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u0445."
type: Add
- message: "\u0420\u0430\u0437\u0434\u0435\u043B\u044C\u043D\u044B\u0435 \u043F\u0435\
\u0434\u0430\u043B\u0438 \u0434\u043B\u044F \u043A\u0430\u0436\u0434\u043E\u0433\
\u043E \u0438\u0437 \u0441\u0435\u0440\u0432\u0435\u0440\u043E\u0432. \u0421\
\u0442\u0430\u0440\u044B\u0435 \u043F\u0435\u0434\u0430\u043B\u0438 \u0432\u0441\
\u0451 \u0435\u0449\u0451 \u0440\u0430\u0431\u043E\u0442\u0430\u044E\u0442 \u043D\
\u0430 \u0432\u0441\u0435\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u0445\
."
type: Add
id: 110
time: '2023-03-28T18:48:59.0000000+00:00'
- author: NCast-Hops
changes:
- message: "\u0414\u043E\u0431\u0430\u0432\u043B\u0435\u043D \u0425\u0410\u0419\u0417\
\u0415\u041D\u0411\u0423\u0420\u0413\u0415\u0420. \u0420\u0435\u0446\u0435\u043F\
\u0442: 1 \u0431\u0443\u043B\u043E\u0447\u043A\u0430, 1 \u0441\u044B\u0440\u043E\
\u0435 \u043C\u044F\u0441\u043E, 5 \u043C\u0435\u0442\u044B (\u0432 \u0440\u0435\
\u0430\u0433\u0435\u043D\u0442\u0430\u0445)"
type: Add
id: 111
time: '2023-04-02T20:18:54.0000000+00:00'
- author: Gersoon
changes:
- message: "\u0414\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u044B \u0441\u0435\u0440\
@@ -8874,3 +8828,50 @@
id: 607
time: '2024-11-18T04:54:23.0000000+00:00'
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/784
- author: BIG_Zi_348
changes:
- message: "\u0414\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u044B \u043D\u0435\u0434\
\u043E\u0441\u0442\u0430\u044E\u0449\u0438\u0435 \u043F\u0435\u0440\u0435\u0432\
\u043E\u0434\u044B \u043C\u0435\u043B\u043E\u0447\u0435\u0439."
type: Add
- message: "\u0418\u0441\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u044B \u043F\u0435\
\u0440\u0435\u0432\u043E\u0434\u044B \u043C\u0435\u043B\u043E\u0447\u0435\u0439\
."
type: Fix
- message: "\u0418\u0441\u043F\u0440\u0430\u0432\u043B\u0435\u043D \u0441\u043F\u0440\
\u0430\u0439\u0442 \u043A\u043E\u0431\u0440\u044B \u0432 \u0440\u0443\u043A\u0430\
\u0445."
type: Fix
id: 608
time: '2024-11-19T13:00:22.0000000+00:00'
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/785
- author: BIG_Zi_348
changes:
- message: "\u0414\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u044B \u043D\u0435\u0434\
\u043E\u0441\u0442\u0430\u044E\u0449\u0438\u0435 \u043F\u0435\u0440\u0435\u0432\
\u043E\u0434\u044B \u043C\u0435\u043B\u043E\u0447\u0435\u0439."
type: Add
id: 609
time: '2024-11-21T19:55:51.0000000+00:00'
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/786
- author: BIG_Zi_348
changes:
- message: "\u0414\u043E\u0431\u0430\u0432\u043B\u0435\u043D \u0442\u0440\u0430\u0432\
\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438\u0439 \u0434\u0440\u043E\
\u0431\u043E\u0432\u0438\u043A \u0434\u043B\u044F \u043F\u043E\u043A\u0443\u043F\
\u043A\u0438 \u0432 \u043A\u0430\u0440\u0433\u043E."
type: Add
id: 610
time: '2024-11-21T19:56:31.0000000+00:00'
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/787
- author: BIG_Zi_348
changes:
- message: "\u0422\u0435\u043F\u0435\u0440\u044C \u043F\u0440\u0435\u0434\u0430\u0442\
\u0435\u043B\u0438 \u0431\u0435\u0437 \u041F\u0414\u0410 \u043F\u043E\u043B\u0443\
\u0447\u0430\u044E\u0442 \u0438\u043C\u043F\u043B\u0430\u043D\u0442\u0438\u0440\
\u043E\u0432\u0430\u043D\u043D\u044B\u0439 \u0430\u043F\u043B\u0438\u043D\u043A\
."
type: Tweak
id: 611
time: '2024-11-22T19:21:34.0000000+00:00'
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/788

View File

@@ -26,7 +26,7 @@ traitor-death-match-end-round-description-entry = {$originalName}'s PDA, with {$
traitor-role-greeting =
You are an agent sent by {$corporation} on behalf of The Syndicate.
Your objectives and codewords are listed in the character menu.
Use the uplink loaded into your PDA to buy the tools you'll need for this mission.
Use your uplink to buy the tools you'll need for this mission.
Death to Nanotrasen!
traitor-role-codewords =
The codewords are:
@@ -36,9 +36,13 @@ traitor-role-codewords =
traitor-role-uplink-code =
Set your ringtone to the notes {$code} to lock or unlock your uplink.
Remember to lock it after, or the stations crew will easily open it too!
traitor-role-uplink-implant =
Your uplink implant has been activated, access it from your hotbar.
The uplink is secure unless someone removes it from your body.
# don't need all the flavour text for character menu
traitor-role-codewords-short =
The codewords are:
{$codewords}.
traitor-role-uplink-code-short = Your uplink code is {$code}. Set it as your PDA ringtone to access uplink.
traitor-role-uplink-implant-short = Your uplink was implanted. Access it from your hotbar.

View File

@@ -38,6 +38,8 @@ ent-Stairs = лестница
.suffix = Steel
ent-Cobweb1 = паутина
.desc = Кто-нибудь должен убрать это.
ent-Cobweb2 = паутина
.desc = Кто-нибудь должен убрать это.
ent-CryogenicSleepUnitSpawner = { ent-CryogenicSleepUnit }
.desc = { ent-CryogenicSleepUnit.desc }
ent-CryogenicSleepUnitSpawnerLateJoin = { ent-CryogenicSleepUnit }

View File

@@ -2,6 +2,12 @@ ent-PsychBed = кушетка психолога
.desc = Мягкая кровать для психологической помощи пациентам.
ent-BenchComfy = удобная скамья
.desc = Скамья с очень удобной спинкой.
ent-BenchRedComfy = { ent-BenchComfy }
.desc = { ent-BenchComfy.desc }
ent-BenchColorfulComfy = { ent-BenchComfy }
.desc = { ent-BenchComfy.desc }
ent-BenchBlueComfy = { ent-BenchComfy }
.desc = { ent-BenchComfy.desc }
ent-ChairGreyscale = стул
.desc = стул
.suffix = Белый

View File

@@ -31,7 +31,10 @@ ent-GasPipeBroken = сломанная труба
.desc = Раньше в ней был газ.
ent-SpaceHeater = космический обогреватель
.desc = Устройство технологии синего пространства, изменяющее локальную температуру. Обычно его называют "Космический обогреватель".
.suffix = Unanchored
ent-SpaceHeaterAnchored = { ent-SpaceHeater }
.desc = { ent-SpaceHeater.desc }
ent-SpaceHeaterEnabled = { ent-SpaceHeater }
.desc = { ent-SpaceHeater.desc }
ent-BaseGasCondenser = конденсатор
.desc = Конденсирует газы в жидкости. Теперь нам нужны только трубы.
ent-DisposalSignalRouter = маршрутизатор сигналов утилизации

View File

@@ -7,7 +7,9 @@ ent-ShelfBar = барная полка
ent-ShelfKitchen = кухонная полка
.desc = Вместит ножи, специи и все самое приятное!
ent-ShelfChemistry = полка для химикатов
.desc = Хранит все ваши химикаты в безопасности и вне до- эээ, публичных рук!
.desc = Хранит все ваши химикаты в безопасности и вне доступности клоу... эээ, публичных рук!
ent-ShelfChemistryChemistrySecure = { ent-ShelfChemistry }
.desc = { ent-ShelfChemistry.desc }
ent-ShotGunCabinet = шкаф для дробовика
.desc = На нем есть маленькая этикетка с надписью "Только для аварийных случаев" с описанием безопасного использования дробовика. Как будто.
ent-ShotGunCabinetFilled = { ent-ShotGunCabinet }
@@ -17,13 +19,13 @@ ent-ShotGunCabinetFilledOpen = { ent-ShotGunCabinet }
ent-ShotGunCabinetOpen = { ent-ShotGunCabinet }
.desc = { ent-ShotGunCabinet.desc }
ent-SignalSwitchDirectional = сигнальный выключатель
.desc = сигнальный выключатель
.desc = Это переключатель питания устройств.
.suffix = направленный
ent-SignalButtonDirectional = сигнальная кнопка
.desc = сигнальная кнопка
.desc = Эта кнопка что-то активирует.
.suffix = направленный
ent-ApcNetSwitchDirectional = коммутатор сети АПЦ
.desc = коммутатор сети АПЦ
ent-ApcNetSwitchDirectional = переключатель сети АПЦ
.desc = Это переключатель источников света, использующих локальный контроллер питания.
.suffix = направленный
ent-CleanerDispenser = дозатор для космического чистящего средства
.desc = Настенный дозатор реагентов.

View File

@@ -32,6 +32,12 @@ ent-WallRockChromite = хромит
.desc = хромит
ent-WallRockAndesite = андезит
.desc = андезит
ent-FenceMetalCorner = сетка-рабица
.desc = Металлическое ограждение, отгораживающее что-то, вероятно, очень важное.
ent-FenceMetalEnd = { ent-FenceMetalCorner }
.desc = { ent-FenceMetalCorner.desc }
ent-FenceMetalStraight = { ent-FenceMetalCorner }
.desc = { ent-FenceMetalCorner.desc }
ent-FenceMetalBroken = сломанный забор из цепной сетки
.desc = Кто-то очень сильно разозлился на неодушевленный предмет.
ent-FenceMetalGate = ворота из цепной сетки
@@ -40,3 +46,11 @@ ent-FenceWoodHighGate = деревянные ворота
.desc = Тебе известно, что тебя ждет за этими воротами? Это может быть как туалет, так и роскошный особняк. Но ты продолжаешь любить своих эмо-мальчиков.
ent-FenceWoodSmallGate = деревянные ворота
.desc = Глядя на эти ворота, в голове всплывает знакомый образ. Где моя свинка?
ent-FenceWoodSmallCorner = малый деревянный забор
.desc = Малый деревянный забор. Лучшая защита для ограждения частной территории!
ent-FenceWoodSmallEnd = { ent-FenceWoodSmallCorner }
.desc = { ent-FenceWoodSmallCorner.desc }
ent-FenceWoodSmallStraight = { ent-FenceWoodSmallCorner }
.desc = { ent-FenceWoodSmallCorner.desc }
ent-FenceWoodSmallTJunction = { ent-FenceWoodSmallCorner }
.desc = { ent-FenceWoodSmallCorner.desc }

View File

@@ -33,8 +33,8 @@ ent-ClothingEyesGlassesSunglassesMeaty = солнцезащитные очки
.desc = Полезны как для безопасности, так и для каргонии.
ent-ClothingEyesGlassesChemical = очки для химического анализа
.desc = Очки, которые могут сканировать химический состав раствора.
ent-ClothingEyesVisorNinja = шлем ниндзя
.desc = Усовершенствованный шлем, защищающий глаза ниндзя от вспышек света.
ent-ClothingEyesVisorNinja = визор ниндзя
.desc = Усовершенствованный визор, защищающий глаза ниндзя от вспышек света.
ent-ClothingEyesHudSyndicate = визор синдиката
.desc = Профессиональный дисплей синдиката, предназначенный для лучшего обнаружения гуманоидов и их последующего уничтожения.
ent-ClothingEyesHudSyndicateAgent = визор агента синдиката

View File

@@ -25,7 +25,7 @@ traitor-death-match-end-round-description-entry = ПДА { $originalName }, с {
traitor-role-greeting =
Вы - агент Синдиката.
Ваши цели и кодовые слова перечислены в меню персонажа.
Воспользуйтесь аплинком, встроенным в ваш ПДА, чтобы приобрести всё необходимое для выполнения работы.
Воспользуйтесь аплинком, чтобы приобрести всё необходимое для выполнения работы.
Смерть НаноТрейзен!
traitor-role-codewords =
@@ -37,6 +37,9 @@ traitor-role-codewords =
traitor-role-uplink-code =
Установите мелодия рингтона на {$code} чтобы разблокировать аплинк.
Не забудьте заблокировать его после этого, иначе сотрудники станции тоже легко откроют его!
traitor-role-uplink-implant =
Ваш имплант аплинк активирован, воспользуйтесь им из хотбара.
Аплинк надежно защищён, пока кто-нибудь не извлечёт его из вашего тела.
# don't need all the flavour text for character menu
traitor-role-codewords-short =
@@ -44,3 +47,4 @@ traitor-role-codewords-short =
{$codewords}.
traitor-role-uplink-code-short = Код от вашего аплинка - {$code}. Установите его в качестве рингтона на своём ПДА для доступа к аплинку.
traitor-role-uplink-implant-short = Ваш аплинк был имплантирован. Воспользуйтесь им из хотбара.

View File

@@ -0,0 +1,5 @@
geras-popup-morph-message-user = Ты трансформируешься в малую версию себя!
geras-popup-morph-message-others = {CAPITALIZE($entity)} трансформировался в слизня!
ent-MobSlimesGeras = герас
.desc = Герас - особая форма слаймолюда.

View File

@@ -1,5 +1,7 @@
ent-BaseWhistle = свисток
.desc = Кто-то явно забыл выключить чайник!
ent-Whistle = свисток
.desc = Кто-то явно забыл выключить чайник!
ent-SecurityWhistle = свисток
.desc = От одного звука становится страшно.
ent-TurboItemRecharger = турбо зарядник

View File

@@ -14,7 +14,7 @@ reagent-desc-thc-oil = Чистое масло ТГК, полученное из
reagent-name-bananadine = бананадин
reagent-desc-bananadine = Слабый психоделик, содержащийся в небольших в шкурках от бананов.
reagent-name-nicotine = никотинколичествах
reagent-name-nicotine = никотин
reagent-desc-nicotine = Опасен и вызывает сильное привыкание.
reagent-name-impedrezene = импедризин
reagent-desc-impedrezene = Наркотик, который лишает человека дееспособности, замедляя высшие функции клеток мозга. Вызывает обширные повреждения мозга.

View File

@@ -5,6 +5,9 @@ ent-MobBee = пчела
ent-MobAngryBee = пчела
.desc = Какая милая пчелка. О нет, она выглядит злой и хочет мою пиццу.
.suffix = Злая
ent-MobTemporaryAngryBee = { ent-MobAngryBee }
.desc = { ent-MobAngryBee.desc }
.suffix = Злая, Временная
ent-MobChicken = курица
.desc = Была раньше яйца, динозавром!
ent-MobChicken1 = { ent-MobChicken }

View File

@@ -15,4 +15,6 @@ ent-BoxShotgunIncendiary = коробка ружейных патронов (з
ent-BoxShotgunPractice = коробка ружейных патронов (учебные)
.desc = Полная коробка учебных ружейных патронов.
ent-BoxShellTranquilizer = коробка ружейных патронов (транквилизаторы)
.desc = Полная коробка ружейных патронов-транквилизаторов.
.desc = Полная коробка ружейных патронов-транквилизаторов.
ent-BoxRubberShot = коробка ружейных патронов (резиновые).
.desc = Полная коробка резиновых ружейных патронов.

View File

@@ -14,9 +14,8 @@ ent-AlwaysPoweredLightLED = { ent-AlwaysPoweredWallLight }
.desc = { ent-AlwaysPoweredWallLight.desc }
ent-PoweredlightExterior = { ent-Poweredlight }
.desc = Осветительный прибор. Потребляет энергию и излучает свет, если оснащен лампой-трубкой.
.suffix = Синий
ent-AlwaysPoweredLightExterior = { ent-AlwaysPoweredWallLight }
.suffix = Всегда запитанный, Синий
.suffix = Всегда запитанный
.desc = { ent-AlwaysPoweredWallLight.desc }
ent-PoweredlightSodium = { ent-Poweredlight }
.desc = Осветительный прибор. Потребляет энергию и излучает свет, если оснащен лампой-трубкой.
@@ -34,3 +33,27 @@ ent-PoweredSmallLight = { ent-PoweredSmallLightEmpty }
.desc = { ent-PoweredSmallLightEmpty.desc }
ent-EmergencyLight = аварийная лампа
.desc = Маленькая лампочка с внутренним аккумулятором, которая включается, как только перестает получать питание извне. Технология НаноТрейзен позволяет ей адаптировать свой цвет для оповещения экипажа об обстановке на станции.
ent-PoweredlightBlue = { ent-Poweredlight }
.desc = { ent-Poweredlight.desc }
ent-PoweredlightCyan = { ent-Poweredlight }
.desc = { ent-Poweredlight.desc }
ent-PoweredlightGreen = { ent-Poweredlight }
.desc = { ent-Poweredlight.desc }
ent-PoweredlightOrange = { ent-Poweredlight }
.desc = { ent-Poweredlight.desc }
ent-PoweredlightPink = { ent-Poweredlight }
.desc = { ent-Poweredlight.desc }
ent-PoweredlightRed = { ent-Poweredlight }
.desc = { ent-Poweredlight.desc }
ent-AlwaysPoweredlightBlue = { ent-AlwaysPoweredWallLight }
.desc = { ent-AlwaysPoweredWallLight.desc }
ent-AlwaysPoweredlightCyan = { ent-AlwaysPoweredWallLight }
.desc = { ent-AlwaysPoweredWallLight.desc }
ent-AlwaysPoweredlightGreen = { ent-AlwaysPoweredWallLight }
.desc = { ent-AlwaysPoweredWallLight.desc }
ent-AlwaysPoweredlightOrange = { ent-AlwaysPoweredWallLight }
.desc = { ent-AlwaysPoweredWallLight.desc }
ent-AlwaysPoweredlightPink = { ent-AlwaysPoweredWallLight }
.desc = { ent-AlwaysPoweredWallLight.desc }
ent-AlwaysPoweredlightRed = { ent-AlwaysPoweredWallLight }
.desc = { ent-AlwaysPoweredWallLight.desc }

View File

@@ -7,6 +7,8 @@ ent-DebugThruster = ракетный двигатель
.suffix = DEBUG
ent-Gyroscope = гироскоп
.desc = Увеличивает потенциальное угловое вращение шаттла.
ent-GyroscopeUnanchored = { ent-Gyroscope }
.desc = { ent-Gyroscope.desc }
ent-DebugGyroscope = гироскоп
.desc = Увеличивает потенциальное угловое вращение шаттла.
.suffix = DEBUG

View File

@@ -6,3 +6,112 @@ ent-ApcNetSwitch = переключатель сети АПЦ
.desc = Это переключатель источников света, использующих локальный контроллер питания.
ent-TwoWayLever = двухпозиционный рычаг
.desc = Двухпозиционный рычаг.
ent-LockableButton = кнопка с замком
.desc = { ent-SignalButtonDirectional.desc }
ent-LockableButtonCaptain = { ent-LockableButton }
.suffix = Капитан
.desc = { ent-LockableButton.desc }
ent-LockableButtonHeadOfPersonnel = { ent-LockableButton }
.suffix = Глава персонала
.desc = { ent-LockableButton.desc }
ent-LockableButtonChiefEngineer = { ent-LockableButton }
.suffix = Старший инженер
.desc = { ent-LockableButton.desc }
ent-LockableButtonChiefMedicalOfficer = { ent-LockableButton }
.suffix = Главный врач
.desc = { ent-LockableButton.desc }
ent-LockableButtonHeadOfSecurity = { ent-LockableButton }
.suffix = Глава службы безопасности
.desc = { ent-LockableButton.desc }
ent-LockableButtonResearchDirector = { ent-LockableButton }
.suffix = Научный руководитель
.desc = { ent-LockableButton.desc }
ent-LockableButtonCommand = { ent-LockableButton }
.suffix = Командование
.desc = { ent-LockableButton.desc }
ent-LockableButtonCryogenics = { ent-LockableButton }
.suffix = Криогеника
.desc = { ent-LockableButton.desc }
ent-LockableButtonSecurity = { ent-LockableButton }
.suffix = Служба безопасности
.desc = { ent-LockableButton.desc }
ent-LockableButtonDetective = { ent-LockableButton }
.suffix = Детектив
.desc = { ent-LockableButton.desc }
ent-LockableButtonArmory = { ent-LockableButton }
.suffix = Оружейная
.desc = { ent-LockableButton.desc }
ent-LockableButtonBrig = { ent-LockableButton }
.suffix = Бриг
.desc = { ent-LockableButton.desc }
ent-LockableButtonLawyer = { ent-LockableButton }
.suffix = Юридический
.desc = { ent-LockableButton.desc }
ent-LockableButtonEngineering = { ent-LockableButton }
.suffix = Инженерный
.desc = { ent-LockableButton.desc }
ent-LockableButtonMedical = { ent-LockableButton }
.suffix = Медицинский
.desc = { ent-LockableButton.desc }
ent-LockableButtonQuartermaster = { ent-LockableButton }
.suffix = Квартирмейстер
.desc = { ent-LockableButton.desc }
ent-LockableButtonSalvage = { ent-LockableButton }
.suffix = Утилизаторы
.desc = { ent-LockableButton.desc }
ent-LockableButtonCargo = { ent-LockableButton }
.suffix = Снабжение
.desc = { ent-LockableButton.desc }
ent-LockableButtonResearch = { ent-LockableButton }
.suffix = Научный
.desc = { ent-LockableButton.desc }
ent-LockableButtonService = { ent-LockableButton }
.suffix = Сервисный
.desc = { ent-LockableButton.desc }
ent-LockableButtonMaintenance = { ent-LockableButton }
.suffix = Техобслуживание
.desc = { ent-LockableButton.desc }
ent-LockableButtonExternal = { ent-LockableButton }
.suffix = Внешний
.desc = { ent-LockableButton.desc }
ent-LockableButtonJanitor = { ent-LockableButton }
.suffix = Уборщик
.desc = { ent-LockableButton.desc }
ent-LockableButtonTheatre = { ent-LockableButton }
.suffix = Театр
.desc = { ent-LockableButton.desc }
ent-LockableButtonBar = { ent-LockableButton }
.suffix = Бар
.desc = { ent-LockableButton.desc }
ent-LockableButtonChemistry = { ent-LockableButton }
.suffix = Химия
.desc = { ent-LockableButton.desc }
ent-LockableButtonKitchen = { ent-LockableButton }
.suffix = Кухня
.desc = { ent-LockableButton.desc }
ent-LockableButtonChapel = { ent-LockableButton }
.suffix = Церковь
.desc = { ent-LockableButton.desc }
ent-LockableButtonHydroponics = { ent-LockableButton }
.suffix = Гидропоника
.desc = { ent-LockableButton.desc }
ent-LockableButtonAtmospherics = { ent-LockableButton }
.suffix = Атмосферный
.desc = { ent-LockableButton.desc }
ent-ButtonFrame = каркас кнопки
.desc = Это каркас, помогающий визуально различать переключатели.
ent-ButtonFrameGrey = { ent-ButtonFrame }
.suffix = Серый
.desc = { ent-ButtonFrame.desc }
ent-ButtonFrameCaution = { ent-ButtonFrame }
.suffix = Внимание
.desc = { ent-ButtonFrame.desc }
ent-ButtonFrameCautionSecurity = { ent-ButtonFrame }
.suffix = Внимание, Служба безопасности
.desc = { ent-ButtonFrame.desc }
ent-ButtonFrameExit = { ent-ButtonFrame }
.suffix = Выход
.desc = { ent-ButtonFrame.desc }
ent-ButtonFrameJanitor = { ent-ButtonFrame }
.suffix = Уборщик
.desc = { ent-ButtonFrame.desc }

View File

@@ -1335,8 +1335,7 @@
components:
# make the player a traitor once its taken
- type: AutoTraitor
giveUplink: false
giveObjectives: false
profile: TraitorReinforcement
- type: entity
id: MobMonkeySyndicateAgentNukeops # Reinforcement exclusive to nukeops uplink
@@ -1491,8 +1490,7 @@
components:
# make the player a traitor once its taken
- type: AutoTraitor
giveUplink: false
giveObjectives: false
profile: TraitorReinforcement
- type: entity
id: MobKoboldSyndicateAgentNukeops # Reinforcement exclusive to nukeops uplink

View File

@@ -27,8 +27,7 @@
components:
# make the player a traitor once its taken
- type: AutoTraitor
giveUplink: false
giveObjectives: false
profile: TraitorReinforcement
- type: entity
parent: MobHumanSyndicateAgentBase

View File

@@ -163,6 +163,20 @@
- type: TraitorRole
prototype: Traitor
- type: entity # WD AHEAD OF WIZDEN UPSTREAM
id: TraitorReinforcement
parent: Traitor
components:
- type: TraitorRule
giveUplink: false
giveCodewords: false # It would actually give them a different set of codewords than the regular traitors, anyway
giveBriefing: false
- type: AntagSelection
definitions:
- prefRoles: [ Traitor ]
mindRoles:
- MindRoleTraitor
- type: entity
id: Revolutionary
parent: BaseGameRule

View File

@@ -277,22 +277,22 @@
category: Security
group: market
- type: cargoProduct # WD ahead of wd upstream
- type: cargoProduct
id: cargoBoxesRubberShot
icon:
sprite: Objects/Storage/boxes.rsi
state: shellRubber
state: shellrubber
product: CrateBoxesRubberShot
cost: 3000
category: cargoproduct-category-name-armory
cost: 800
category: Security
group: market
- type: cargoProduct
id: cargoRubberShotgun
icon:
sprite: _Honk/Objects/Weapons/Guns/Shotguns/pump.rsi
sprite: White/Objects/Weapons/Guns/Shotguns/rubber_pump.rsi
state: icon
product: CrateRubberShotgun
cost: 4000
category: cargoproduct-category-name-armory
cost: 2000
category: Security
group: market

View File

@@ -1,4 +1,4 @@
- type: entity # WD ahead of wd upstream
- type: entity
id: CrateBoxesRubberShot
parent: CrateWeaponSecure
name: ящик с коробками резиновой дроби