# Conflicts: # Content.Client/Entry/EntryPoint.cs # Content.Client/Stylesheets/StyleNano.cs # Content.Server/Nutrition/EntitySystems/CreamPieSystem.cs # Content.Server/Nutrition/EntitySystems/FoodSystem.cs # Content.Shared/Follower/FollowerSystem.cs # Content.Shared/Humanoid/SharedHumanoidAppearanceSystem.cs # Content.Shared/Inventory/InventorySystem.Relay.cs # Content.Shared/PAI/SharedPAISystem.cs # Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs # Resources/Locale/en-US/_strings/access/components/genpop.ftl # Resources/Locale/en-US/_strings/doors/components/turnstile.ftl # Resources/Locale/en-US/_strings/power/battery.ftl # Resources/Locale/en-US/_strings/store/pai-catalog.ftl # Resources/Locale/en-US/_strings/tools/simple-tool-usage.ftl # Resources/Locale/en-US/_strings/ui/controls.ftl # Resources/Locale/en-US/_strings/weapons/ranged/upgrades.ftl # Resources/Prototypes/Access/misc.yml # Resources/Prototypes/Catalog/Cargo/cargo_vending.yml # Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml # Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml # Resources/Prototypes/Entities/Markers/Spawners/Random/crates.yml # Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml # Resources/Prototypes/Entities/Mobs/Player/dragon.yml # Resources/Prototypes/Entities/Mobs/Player/humanoid.yml # Resources/Prototypes/Entities/Objects/Fun/toys.yml # Resources/Prototypes/Entities/Objects/Misc/paper.yml # Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_modules.yml # Resources/Prototypes/Entities/Objects/Tools/access_configurator.yml # Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Magazines/shotgun.yml # Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml # Resources/Prototypes/Entities/Stations/base.yml # Resources/Prototypes/Entities/Structures/Walls/asteroid.yml # Resources/Prototypes/Loadouts/role_loadouts.yml # Resources/Prototypes/Recipes/Lathes/Packs/science.yml # Resources/Prototypes/Research/industrial.yml # Resources/Prototypes/Species/vox.yml # Resources/Prototypes/Store/currency.yml # Resources/Prototypes/Voice/speech_emotes.yml # Resources/Prototypes/ai_factions.yml # Resources/Prototypes/borg_types.yml # Resources/Textures/Clothing/Head/Hats/captain.rsi/meta.json # Resources/Textures/Clothing/Uniforms/Jumpskirt/capformaldress.rsi/meta.json # Resources/Textures/Clothing/Uniforms/Jumpskirt/captain.rsi/meta.json # Resources/Textures/Clothing/Uniforms/Jumpskirt/paramedic.rsi/equipped-INNERCLOTHING.png # Resources/Textures/Clothing/Uniforms/Jumpskirt/paramedic.rsi/icon.png # Resources/Textures/Clothing/Uniforms/Jumpsuit/capformal.rsi/equipped-INNERCLOTHING-monkey.png # Resources/Textures/Clothing/Uniforms/Jumpsuit/capformal.rsi/meta.json # Resources/Textures/Clothing/Uniforms/Jumpsuit/captain.rsi/equipped-INNERCLOTHING-monkey.png # Resources/Textures/Clothing/Uniforms/Jumpsuit/captain.rsi/meta.json # Resources/Textures/Clothing/Uniforms/Jumpsuit/paramedic.rsi/equipped-INNERCLOTHING-monkey.png # Resources/Textures/Clothing/Uniforms/Jumpsuit/paramedic.rsi/equipped-INNERCLOTHING.png # Resources/Textures/Clothing/Uniforms/Jumpsuit/paramedic.rsi/icon.png # Resources/Textures/Clothing/Uniforms/Jumpsuit/paramedic.rsi/meta.json # Resources/Textures/Objects/Weapons/Melee/captain_sabre.rsi/meta.json # Resources/Textures/Objects/Weapons/Melee/energykatana.rsi/meta.json # Resources/Textures/Objects/Weapons/Melee/katana.rsi/meta.json # Resources/Textures/Objects/Weapons/Melee/machete.rsi/meta.json # Resources/Textures/Structures/Doors/Airlocks/Glass/firelock.rsi/closed.png # Resources/Textures/Structures/Doors/Airlocks/Glass/firelock.rsi/closing.png # Resources/Textures/Structures/Doors/Airlocks/Glass/firelock.rsi/deny.png # Resources/Textures/Structures/Doors/Airlocks/Glass/firelock.rsi/locked.png # Resources/Textures/Structures/Doors/Airlocks/Glass/firelock.rsi/opening.png # Resources/Textures/Structures/Doors/Airlocks/Standard/atmospherics.rsi/assembly.png # Resources/Textures/Structures/Doors/Airlocks/Standard/atmospherics.rsi/closed.png # Resources/Textures/Structures/Doors/Airlocks/Standard/atmospherics.rsi/closing.png # Resources/Textures/Structures/Doors/Airlocks/Standard/atmospherics.rsi/meta.json # Resources/Textures/Structures/Doors/Airlocks/Standard/atmospherics.rsi/open.png # Resources/Textures/Structures/Doors/Airlocks/Standard/atmospherics.rsi/opening.png # Resources/Textures/Structures/Doors/Airlocks/Standard/firelock.rsi/closed.png # Resources/Textures/Structures/Doors/Airlocks/Standard/firelock.rsi/closing.png # Resources/Textures/Structures/Doors/Airlocks/Standard/firelock.rsi/opening.png # Resources/Textures/Structures/Wallmounts/posters.rsi/poster4_contraband.png # Resources/migration.yml
167 lines
7 KiB
C#
167 lines
7 KiB
C#
using System.Linq;
|
|
using Content.Shared.Cargo.Components;
|
|
using Content.Shared.CCVar;
|
|
using Content.Shared.Database;
|
|
using Content.Shared.Emag.Systems;
|
|
using Content.Shared.IdentityManagement;
|
|
using Content.Shared.UserInterface;
|
|
|
|
namespace Content.Server.Cargo.Systems;
|
|
|
|
public sealed partial class CargoSystem
|
|
{
|
|
private bool _allowPrimaryAccountAllocation;
|
|
private bool _allowPrimaryCutAdjustment;
|
|
|
|
public void InitializeFunds()
|
|
{
|
|
SubscribeLocalEvent<CargoOrderConsoleComponent, CargoConsoleWithdrawFundsMessage>(OnWithdrawFunds);
|
|
SubscribeLocalEvent<CargoOrderConsoleComponent, CargoConsoleToggleLimitMessage>(OnToggleLimit);
|
|
SubscribeLocalEvent<FundingAllocationConsoleComponent, SetFundingAllocationBuiMessage>(OnSetFundingAllocation);
|
|
SubscribeLocalEvent<FundingAllocationConsoleComponent, BeforeActivatableUIOpenEvent>(OnFundAllocationBuiOpen);
|
|
|
|
_cfg.OnValueChanged(CCVars.AllowPrimaryAccountAllocation, enabled => { _allowPrimaryAccountAllocation = enabled; }, true);
|
|
_cfg.OnValueChanged(CCVars.AllowPrimaryCutAdjustment, enabled => { _allowPrimaryCutAdjustment = enabled; }, true);
|
|
}
|
|
|
|
private void OnWithdrawFunds(Entity<CargoOrderConsoleComponent> ent, ref CargoConsoleWithdrawFundsMessage args)
|
|
{
|
|
if (_station.GetOwningStation(ent) is not { } station ||
|
|
!TryComp<StationBankAccountComponent>(station, out var bank))
|
|
return;
|
|
|
|
if (args.Account == ent.Comp.Account ||
|
|
args.Amount <= 0 ||
|
|
args.Amount > GetBalanceFromAccount((station, bank), ent.Comp.Account) * ent.Comp.TransferLimit)
|
|
return;
|
|
|
|
if (Timing.CurTime < ent.Comp.NextAccountActionTime)
|
|
return;
|
|
|
|
if (!_accessReaderSystem.IsAllowed(args.Actor, ent))
|
|
{
|
|
ConsolePopup(args.Actor, Loc.GetString("cargo-console-order-not-allowed"));
|
|
PlayDenySound(ent, ent.Comp.ErrorSound);
|
|
return;
|
|
}
|
|
|
|
ent.Comp.NextAccountActionTime = Timing.CurTime + ent.Comp.AccountActionDelay;
|
|
UpdateBankAccount((station, bank), -args.Amount, ent.Comp.Account, dirty: false);
|
|
_audio.PlayPvs(ApproveSound, ent);
|
|
|
|
var tryGetIdentityShortInfoEvent = new TryGetIdentityShortInfoEvent(ent, args.Actor);
|
|
RaiseLocalEvent(tryGetIdentityShortInfoEvent);
|
|
|
|
var ourAccount = _protoMan.Index(ent.Comp.Account);
|
|
if (args.Account == null)
|
|
{
|
|
var stackPrototype = _protoMan.Index(ent.Comp.CashType);
|
|
_stack.Spawn(args.Amount, stackPrototype, Transform(ent).Coordinates);
|
|
|
|
if (!_emag.CheckFlag(ent, EmagType.Interaction))
|
|
{
|
|
var msg = Loc.GetString("cargo-console-fund-withdraw-broadcast",
|
|
("name", tryGetIdentityShortInfoEvent.Title ?? Loc.GetString("cargo-console-fund-transfer-user-unknown")),
|
|
("amount", args.Amount),
|
|
("name1", Loc.GetString(ourAccount.Name)),
|
|
("code1", Loc.GetString(ourAccount.Code)));
|
|
_radio.SendRadioMessage(ent, msg, ourAccount.RadioChannel, ent, escapeMarkup: false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var otherAccount = _protoMan.Index(args.Account.Value);
|
|
UpdateBankAccount((station, bank), args.Amount, args.Account.Value);
|
|
|
|
if (!_emag.CheckFlag(ent, EmagType.Interaction))
|
|
{
|
|
var msg = Loc.GetString("cargo-console-fund-transfer-broadcast",
|
|
("name", tryGetIdentityShortInfoEvent.Title ?? Loc.GetString("cargo-console-fund-transfer-user-unknown")),
|
|
("amount", args.Amount),
|
|
("name1", Loc.GetString(ourAccount.Name)),
|
|
("code1", Loc.GetString(ourAccount.Code)),
|
|
("name2", Loc.GetString(otherAccount.Name)),
|
|
("code2", Loc.GetString(otherAccount.Code)));
|
|
_radio.SendRadioMessage(ent, msg, ourAccount.RadioChannel, ent, escapeMarkup: false);
|
|
_radio.SendRadioMessage(ent, msg, otherAccount.RadioChannel, ent, escapeMarkup: false);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnToggleLimit(Entity<CargoOrderConsoleComponent> ent, ref CargoConsoleToggleLimitMessage args)
|
|
{
|
|
if (!_accessReaderSystem.FindAccessTags(args.Actor).Intersect(ent.Comp.RemoveLimitAccess).Any())
|
|
{
|
|
ConsolePopup(args.Actor, Loc.GetString("cargo-console-order-not-allowed"));
|
|
PlayDenySound(ent, ent.Comp.ErrorSound);
|
|
return;
|
|
}
|
|
|
|
_audio.PlayPvs(ent.Comp.ToggleLimitSound, ent);
|
|
ent.Comp.TransferUnbounded = !ent.Comp.TransferUnbounded;
|
|
Dirty(ent);
|
|
}
|
|
|
|
|
|
private void OnSetFundingAllocation(Entity<FundingAllocationConsoleComponent> ent, ref SetFundingAllocationBuiMessage args)
|
|
{
|
|
if (_station.GetOwningStation(ent) is not { } station ||
|
|
!TryComp<StationBankAccountComponent>(station, out var bank))
|
|
return;
|
|
|
|
var expectedCount = _allowPrimaryAccountAllocation ? bank.RevenueDistribution.Count : bank.RevenueDistribution.Count - 1;
|
|
if (args.Percents.Count != expectedCount)
|
|
return;
|
|
|
|
var differs = false;
|
|
foreach (var (account, percent) in args.Percents)
|
|
{
|
|
if (percent != (int) Math.Round(bank.RevenueDistribution[account] * 100))
|
|
{
|
|
differs = true;
|
|
break;
|
|
}
|
|
}
|
|
differs = differs || args.PrimaryCut != bank.PrimaryCut || args.LockboxCut != bank.LockboxCut;
|
|
|
|
if (!differs)
|
|
return;
|
|
|
|
if (args.Percents.Values.Sum() != 100)
|
|
return;
|
|
|
|
var primaryCut = bank.RevenueDistribution[bank.PrimaryAccount];
|
|
bank.RevenueDistribution.Clear();
|
|
foreach (var (account, percent )in args.Percents)
|
|
{
|
|
bank.RevenueDistribution.Add(account, percent / 100.0);
|
|
}
|
|
if (!_allowPrimaryAccountAllocation)
|
|
{
|
|
bank.RevenueDistribution.Add(bank.PrimaryAccount, 0);
|
|
}
|
|
|
|
if (_allowPrimaryCutAdjustment && args.PrimaryCut is >= 0.0 and <= 1.0)
|
|
{
|
|
bank.PrimaryCut = args.PrimaryCut;
|
|
}
|
|
if (_lockboxCutEnabled && args.LockboxCut is >= 0.0 and <= 1.0)
|
|
{
|
|
bank.LockboxCut = args.LockboxCut;
|
|
}
|
|
|
|
Dirty(station, bank);
|
|
|
|
_audio.PlayPvs(ent.Comp.SetDistributionSound, ent);
|
|
_adminLogger.Add(
|
|
LogType.Action,
|
|
LogImpact.Medium,
|
|
$"{ToPrettyString(args.Actor):player} set station {ToPrettyString(station)} fund distribution: {string.Join(',', bank.RevenueDistribution.Select(p => $"{p.Key}: {p.Value}").ToList())}, primary cut: {bank.PrimaryCut}, lockbox cut: {bank.LockboxCut}");
|
|
}
|
|
|
|
private void OnFundAllocationBuiOpen(Entity<FundingAllocationConsoleComponent> ent, ref BeforeActivatableUIOpenEvent args)
|
|
{
|
|
if (_station.GetOwningStation(ent) is { } station)
|
|
_uiSystem.SetUiState(ent.Owner, FundingAllocationConsoleUiKey.Key, new FundingAllocationConsoleBuiState(GetNetEntity(station)));
|
|
}
|
|
}
|