Антаг без ПДА - фикс от визденов (с костылями) (#788)
* Апстрима будет * Also this
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
using Content.Shared._White.Mood;
|
using Content.Shared._White.Mood;
|
||||||
using Content.Shared.Dataset;
|
using Content.Shared.Dataset;
|
||||||
|
using Content.Shared.FixedPoint;
|
||||||
using Content.Shared.NPC.Prototypes;
|
using Content.Shared.NPC.Prototypes;
|
||||||
using Content.Shared.Random;
|
using Content.Shared.Random;
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
@@ -34,7 +35,25 @@ public sealed partial class TraitorRuleComponent : Component
|
|||||||
|
|
||||||
[DataField]
|
[DataField]
|
||||||
public ProtoId<DatasetPrototype> ObjectiveIssuers = "TraitorCorporations";
|
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
|
// WD edit start
|
||||||
[DataField]
|
[DataField]
|
||||||
public ProtoId<MoodEffectPrototype> MoodBuffEffect = "TraitorFocused";
|
public ProtoId<MoodEffectPrototype> MoodBuffEffect = "TraitorFocused";
|
||||||
@@ -77,7 +96,7 @@ public sealed partial class TraitorRuleComponent : Component
|
|||||||
/// The amount of TC traitors start with.
|
/// The amount of TC traitors start with.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public int StartingBalance = 20;
|
public FixedPoint2 StartingBalance = 20; // WD EDIT AHEAD OF WIZDEN UPSTREAM
|
||||||
|
|
||||||
[DataField]
|
[DataField]
|
||||||
public int MaxDifficulty = 5;
|
public int MaxDifficulty = 5;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Content.Server.Objectives;
|
|||||||
using Content.Server.PDA.Ringer;
|
using Content.Server.PDA.Ringer;
|
||||||
using Content.Server.Roles;
|
using Content.Server.Roles;
|
||||||
using Content.Server.Traitor.Uplink;
|
using Content.Server.Traitor.Uplink;
|
||||||
|
using Content.Shared.FixedPoint;
|
||||||
using Content.Shared.Mind;
|
using Content.Shared.Mind;
|
||||||
using Content.Shared.NPC.Systems;
|
using Content.Shared.NPC.Systems;
|
||||||
using Content.Shared.Objectives.Components;
|
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
|
//Grab the mind if it wasnt provided
|
||||||
if (!_mindSystem.TryGetMind(traitor, out var mindId, out var mind))
|
if (!_mindSystem.TryGetMind(traitor, out var mindId, out var mind))
|
||||||
@@ -83,39 +84,46 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
|
|||||||
// WD START
|
// WD START
|
||||||
var richAspect = _gameTicker.GetActiveGameRules().Where(HasComp<TraitorRichAspectComponent>).Any();
|
var richAspect = _gameTicker.GetActiveGameRules().Where(HasComp<TraitorRichAspectComponent>).Any();
|
||||||
// WD END
|
// 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);
|
var issuer = _random.Pick(_prototypeManager.Index(component.ObjectiveIssuers).Values);
|
||||||
|
|
||||||
Note[]? code = null;
|
Note[]? code = null;
|
||||||
if (giveUplink)
|
if (component.GiveUplink) // WD EDIT AHEAD OF WIZDEN UPSTREAM
|
||||||
{
|
{
|
||||||
// Calculate the amount of currency on the uplink.
|
// Calculate the amount of currency on the uplink.
|
||||||
var startingBalance = component.StartingBalance;
|
var startingBalance = component.StartingBalance;
|
||||||
if (_jobs.MindTryGetJob(mindId, out _, out var prototype))
|
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)
|
if (richAspect)
|
||||||
{
|
{
|
||||||
startingBalance += 10;
|
startingBalance += 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
// creadth: we need to create uplink for the antag.
|
// Choose and generate an Uplink, and return the uplink code if applicable
|
||||||
// PDA should be in place already
|
var uplinkParams = RequestUplink(traitor, startingBalance, briefing);
|
||||||
var pda = _uplink.FindUplinkTarget(traitor);
|
code = uplinkParams.Item1;
|
||||||
if (pda == null || !_uplink.AddUplink(traitor, startingBalance))
|
briefing = uplinkParams.Item2;
|
||||||
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", "#"))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_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);
|
component.TraitorMinds.Add(mindId);
|
||||||
|
|
||||||
// Assign briefing
|
// Assign briefing
|
||||||
@@ -146,7 +154,33 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
|
|||||||
|
|
||||||
return true;
|
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)
|
private void OnObjectivesTextGetInfo(EntityUid uid, TraitorRuleComponent comp, ref ObjectivesTextGetInfoEvent args)
|
||||||
{
|
{
|
||||||
args.Minds = _antag.GetAntagMindEntityUids(uid);
|
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)));
|
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();
|
var sb = new StringBuilder();
|
||||||
sb.AppendLine(Loc.GetString("traitor-role-greeting", ("corporation", objectiveIssuer ?? Loc.GetString("objective-issuer-unknown"))));
|
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)
|
if (uplinkCode != null)
|
||||||
sb.AppendLine(Loc.GetString("traitor-role-uplink-code-short", ("code", string.Join("-", uplinkCode).Replace("sharp", "#"))));
|
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();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Traitor.Systems;
|
using Content.Server.Traitor.Systems;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Server.Traitor.Components;
|
namespace Content.Server.Traitor.Components;
|
||||||
|
|
||||||
@@ -9,14 +10,8 @@ namespace Content.Server.Traitor.Components;
|
|||||||
public sealed partial class AutoTraitorComponent : Component
|
public sealed partial class AutoTraitorComponent : Component
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether to give the traitor an uplink or not.
|
/// The traitor profile to use
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("giveUplink"), ViewVariables(VVAccess.ReadWrite)]
|
[DataField]
|
||||||
public bool GiveUplink = true;
|
public EntProtoId Profile = "Traitor"; // WD EDIT AHEAD OF WIZDEN UPSTREAM
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether to give the traitor objectives or not.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("giveObjectives"), ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public bool GiveObjectives = true;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,6 @@ public sealed class AutoTraitorSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly AntagSelectionSystem _antag = default!;
|
[Dependency] private readonly AntagSelectionSystem _antag = default!;
|
||||||
|
|
||||||
[ValidatePrototypeId<EntityPrototype>]
|
|
||||||
private const string DefaultTraitorRule = "Traitor";
|
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
@@ -24,6 +21,6 @@ public sealed class AutoTraitorSystem : EntitySystem
|
|||||||
|
|
||||||
private void OnMindAdded(EntityUid uid, AutoTraitorComponent comp, MindAddedMessage args)
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
7
Content.Server/Traitor/Uplink/UplinkComponent.cs
Normal file
7
Content.Server/Traitor/Uplink/UplinkComponent.cs
Normal 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;
|
||||||
@@ -1,94 +1,130 @@
|
|||||||
using Content.Server.Store.Systems;
|
using Content.Server.Store.Systems;
|
||||||
|
using Content.Shared.FixedPoint;
|
||||||
using Content.Shared.Hands.EntitySystems;
|
using Content.Shared.Hands.EntitySystems;
|
||||||
|
using Content.Shared.Implants;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
using Content.Shared.PDA;
|
using Content.Shared.PDA;
|
||||||
using Content.Server.Store.Components;
|
|
||||||
using Content.Shared.FixedPoint;
|
|
||||||
using Content.Shared.Store;
|
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!;
|
// Try to find target item if none passed
|
||||||
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
uplinkEntity ??= FindUplinkTarget(user);
|
||||||
[Dependency] private readonly StoreSystem _store = default!;
|
if (uplinkEntity == null)
|
||||||
|
return ImplantUplink(user, balance, giveDiscounts);
|
||||||
|
|
||||||
[ValidatePrototypeId<CurrencyPrototype>]
|
EnsureComp<UplinkComponent>(uplinkEntity.Value);
|
||||||
public const string TelecrystalCurrencyPrototype = "Telecrystal";
|
|
||||||
|
|
||||||
/// <summary>
|
SetUplink(user, uplinkEntity.Value, balance, giveDiscounts);
|
||||||
/// Gets the amount of TC on an "uplink"
|
|
||||||
/// Mostly just here for legacy systems based on uplink.
|
// TODO add BUI. Currently can't be done outside of yaml -_-
|
||||||
/// </summary>
|
// ^ What does this even mean?
|
||||||
/// <param name="component"></param>
|
|
||||||
/// <returns>the amount of TC</returns>
|
return true;
|
||||||
public int GetTCBalance(StoreComponent component)
|
}
|
||||||
|
|
||||||
|
/// <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);
|
while (containerSlotEnumerator.MoveNext(out var pdaUid))
|
||||||
return tcBalance?.Int() ?? 0;
|
{
|
||||||
|
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>
|
return null;
|
||||||
/// 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,22 +108,38 @@ public abstract class SharedSubdermalImplantSystem : EntitySystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void AddImplants(EntityUid uid, IEnumerable<String> implants)
|
public void AddImplants(EntityUid uid, IEnumerable<String> implants)
|
||||||
{
|
{
|
||||||
var coords = Transform(uid).Coordinates;
|
|
||||||
foreach (var id in implants)
|
foreach (var id in implants)
|
||||||
{
|
{
|
||||||
var ent = Spawn(id, coords);
|
AddImplant(uid, id);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <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>
|
/// <summary>
|
||||||
/// Forces an implant into a person
|
/// Forces an implant into a person
|
||||||
/// Good for on spawn related code or admin additions
|
/// Good for on spawn related code or admin additions
|
||||||
@@ -184,7 +200,7 @@ public abstract class SharedSubdermalImplantSystem : EntitySystem
|
|||||||
var relayEv = new ImplantRelayEvent<T>(args);
|
var relayEv = new ImplantRelayEvent<T>(args);
|
||||||
foreach (var implant in implantContainer.ContainedEntities)
|
foreach (var implant in implantContainer.ContainedEntities)
|
||||||
{
|
{
|
||||||
if (args is HandledEntityEventArgs { Handled : true })
|
if (args is HandledEntityEventArgs { Handled: true })
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RaiseLocalEvent(implant, relayEv);
|
RaiseLocalEvent(implant, relayEv);
|
||||||
@@ -223,7 +239,7 @@ public abstract class SharedSubdermalImplantSystem : EntitySystem
|
|||||||
// Remove the implant from the donor's implant container
|
// Remove the implant from the donor's implant container
|
||||||
_container.Remove(donorImplant, donorImplantContainer, force: true);
|
_container.Remove(donorImplant, donorImplantContainer, force: true);
|
||||||
|
|
||||||
if(!TryComp<SubdermalImplantComponent>(donorImplant, out var subdermal))
|
if (!TryComp<SubdermalImplantComponent>(donorImplant, out var subdermal))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Insert the implant into the recipient's implant container
|
// Insert the implant into the recipient's implant container
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ traitor-death-match-end-round-description-entry = {$originalName}'s PDA, with {$
|
|||||||
traitor-role-greeting =
|
traitor-role-greeting =
|
||||||
You are an agent sent by {$corporation} on behalf of The Syndicate.
|
You are an agent sent by {$corporation} on behalf of The Syndicate.
|
||||||
Your objectives and codewords are listed in the character menu.
|
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!
|
Death to Nanotrasen!
|
||||||
traitor-role-codewords =
|
traitor-role-codewords =
|
||||||
The codewords are:
|
The codewords are:
|
||||||
@@ -36,9 +36,13 @@ traitor-role-codewords =
|
|||||||
traitor-role-uplink-code =
|
traitor-role-uplink-code =
|
||||||
Set your ringtone to the notes {$code} to lock or unlock your uplink.
|
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!
|
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
|
# don't need all the flavour text for character menu
|
||||||
traitor-role-codewords-short =
|
traitor-role-codewords-short =
|
||||||
The codewords are:
|
The codewords are:
|
||||||
{$codewords}.
|
{$codewords}.
|
||||||
traitor-role-uplink-code-short = Your uplink code is {$code}. Set it as your PDA ringtone to access uplink.
|
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.
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ traitor-death-match-end-round-description-entry = ПДА { $originalName }, с {
|
|||||||
traitor-role-greeting =
|
traitor-role-greeting =
|
||||||
Вы - агент Синдиката.
|
Вы - агент Синдиката.
|
||||||
Ваши цели и кодовые слова перечислены в меню персонажа.
|
Ваши цели и кодовые слова перечислены в меню персонажа.
|
||||||
Воспользуйтесь аплинком, встроенным в ваш ПДА, чтобы приобрести всё необходимое для выполнения работы.
|
Воспользуйтесь аплинком, чтобы приобрести всё необходимое для выполнения работы.
|
||||||
Смерть НаноТрейзен!
|
Смерть НаноТрейзен!
|
||||||
|
|
||||||
traitor-role-codewords =
|
traitor-role-codewords =
|
||||||
@@ -37,6 +37,9 @@ traitor-role-codewords =
|
|||||||
traitor-role-uplink-code =
|
traitor-role-uplink-code =
|
||||||
Установите мелодия рингтона на {$code} чтобы разблокировать аплинк.
|
Установите мелодия рингтона на {$code} чтобы разблокировать аплинк.
|
||||||
Не забудьте заблокировать его после этого, иначе сотрудники станции тоже легко откроют его!
|
Не забудьте заблокировать его после этого, иначе сотрудники станции тоже легко откроют его!
|
||||||
|
traitor-role-uplink-implant =
|
||||||
|
Ваш имплант аплинк активирован, воспользуйтесь им из хотбара.
|
||||||
|
Аплинк надежно защищён, пока кто-нибудь не извлечёт его из вашего тела.
|
||||||
|
|
||||||
# don't need all the flavour text for character menu
|
# don't need all the flavour text for character menu
|
||||||
traitor-role-codewords-short =
|
traitor-role-codewords-short =
|
||||||
@@ -44,3 +47,4 @@ traitor-role-codewords-short =
|
|||||||
{$codewords}.
|
{$codewords}.
|
||||||
|
|
||||||
traitor-role-uplink-code-short = Код от вашего аплинка - {$code}. Установите его в качестве рингтона на своём ПДА для доступа к аплинку.
|
traitor-role-uplink-code-short = Код от вашего аплинка - {$code}. Установите его в качестве рингтона на своём ПДА для доступа к аплинку.
|
||||||
|
traitor-role-uplink-implant-short = Ваш аплинк был имплантирован. Воспользуйтесь им из хотбара.
|
||||||
|
|||||||
@@ -1335,8 +1335,7 @@
|
|||||||
components:
|
components:
|
||||||
# make the player a traitor once its taken
|
# make the player a traitor once its taken
|
||||||
- type: AutoTraitor
|
- type: AutoTraitor
|
||||||
giveUplink: false
|
profile: TraitorReinforcement
|
||||||
giveObjectives: false
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: MobMonkeySyndicateAgentNukeops # Reinforcement exclusive to nukeops uplink
|
id: MobMonkeySyndicateAgentNukeops # Reinforcement exclusive to nukeops uplink
|
||||||
@@ -1491,8 +1490,7 @@
|
|||||||
components:
|
components:
|
||||||
# make the player a traitor once its taken
|
# make the player a traitor once its taken
|
||||||
- type: AutoTraitor
|
- type: AutoTraitor
|
||||||
giveUplink: false
|
profile: TraitorReinforcement
|
||||||
giveObjectives: false
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: MobKoboldSyndicateAgentNukeops # Reinforcement exclusive to nukeops uplink
|
id: MobKoboldSyndicateAgentNukeops # Reinforcement exclusive to nukeops uplink
|
||||||
|
|||||||
@@ -27,8 +27,7 @@
|
|||||||
components:
|
components:
|
||||||
# make the player a traitor once its taken
|
# make the player a traitor once its taken
|
||||||
- type: AutoTraitor
|
- type: AutoTraitor
|
||||||
giveUplink: false
|
profile: TraitorReinforcement
|
||||||
giveObjectives: false
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: MobHumanSyndicateAgentBase
|
parent: MobHumanSyndicateAgentBase
|
||||||
|
|||||||
@@ -163,6 +163,20 @@
|
|||||||
- type: TraitorRole
|
- type: TraitorRole
|
||||||
prototype: Traitor
|
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
|
- type: entity
|
||||||
id: Revolutionary
|
id: Revolutionary
|
||||||
parent: BaseGameRule
|
parent: BaseGameRule
|
||||||
|
|||||||
Reference in New Issue
Block a user