Merge branch 'master' into ed-god-hair
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
using Content.Shared._CP14.Knowledge;
|
||||
using Content.Shared._CP14.Knowledge.Events;
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client._CP14.Knowledge;
|
||||
|
||||
public sealed partial class ClientCP14KnowledgeSystem : SharedCP14KnowledgeSystem
|
||||
public sealed class ClientCP14KnowledgeSystem : SharedCP14KnowledgeSystem
|
||||
{
|
||||
[Dependency] private readonly IPlayerManager _players = default!;
|
||||
|
||||
@@ -24,7 +25,7 @@ public sealed partial class ClientCP14KnowledgeSystem : SharedCP14KnowledgeSyste
|
||||
if (entity is null)
|
||||
return;
|
||||
|
||||
RaiseNetworkEvent(new RequestKnowledgeInfoEvent(GetNetEntity(entity.Value)));
|
||||
RaiseNetworkEvent(new CP14RequestKnowledgeInfoEvent(GetNetEntity(entity.Value)));
|
||||
}
|
||||
|
||||
private void OnCharacterKnowledgeEvent(CP14KnowledgeInfoEvent msg, EntitySessionEventArgs args)
|
||||
@@ -37,6 +38,6 @@ public sealed partial class ClientCP14KnowledgeSystem : SharedCP14KnowledgeSyste
|
||||
|
||||
public readonly record struct KnowledgeData(
|
||||
EntityUid Entity,
|
||||
HashSet<ProtoId<CP14KnowledgePrototype>> AllKnowledges
|
||||
HashSet<ProtoId<CP14KnowledgePrototype>> AllKnowledge
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
<Control xmlns="https://spacestation14.io">
|
||||
<Button Name="ProductButton" Access="Public">
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<EntityPrototypeView Name="EntityView"
|
||||
MinSize="48 48"
|
||||
MaxSize="48 48"
|
||||
Scale="2,2"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Visible="False"/>
|
||||
<TextureRect Name="View"
|
||||
MinSize="48 48"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Stretch="KeepAspectCentered" />
|
||||
Stretch="KeepAspectCentered"
|
||||
Visible="False"/>
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<RichTextLabel Name="SpecialLabel" Text="{Loc 'cp14-store-ui-tab-special'}" VerticalAlignment="Center" Access="Public" Visible="False" />
|
||||
<RichTextLabel Name="ProductName" VerticalAlignment="Center" Access="Public" />
|
||||
|
||||
@@ -3,7 +3,6 @@ using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client._CP14.TravelingStoreShip;
|
||||
|
||||
@@ -26,10 +25,16 @@ public sealed partial class CP14StoreProductControl : Control
|
||||
ProductName.Text = $"[bold]{entry.Name}[/bold]";
|
||||
|
||||
SpecialLabel.Visible = entry.Special;
|
||||
View.Texture = _sprite.Frame0(entry.Icon);
|
||||
}
|
||||
|
||||
private void UpdateView(SpriteSpecifier spriteSpecifier)
|
||||
{
|
||||
if (entry.Icon is not null)
|
||||
{
|
||||
View.Visible = true;
|
||||
View.Texture = _sprite.Frame0(entry.Icon);
|
||||
}
|
||||
else if (entry.EntityView is not null)
|
||||
{
|
||||
EntityView.Visible = true;
|
||||
EntityView.SetPrototype(entry.EntityView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
Title="{Loc 'cp14-store-ui-title'}"
|
||||
Name="Window"
|
||||
Title=""
|
||||
MinSize="800 600"
|
||||
SetSize="800 600">
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
|
||||
@@ -11,9 +11,6 @@ public sealed partial class CP14StoreWindow : DefaultWindow
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
|
||||
private TimeSpan? _nextTravelTime;
|
||||
private bool _onStation;
|
||||
|
||||
public CP14StoreWindow()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
@@ -25,24 +22,8 @@ public sealed partial class CP14StoreWindow : DefaultWindow
|
||||
|
||||
public void UpdateUI(CP14StoreUiState state)
|
||||
{
|
||||
Window.Title = Loc.GetString("cp14-store-ui-title", ("name", state.ShopName));
|
||||
UpdateProducts(state);
|
||||
|
||||
_nextTravelTime = state.NextTravelTime;
|
||||
_onStation = state.OnStation;
|
||||
}
|
||||
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
base.FrameUpdate(args);
|
||||
|
||||
//Updating time
|
||||
if (_nextTravelTime is not null)
|
||||
{
|
||||
var time = _nextTravelTime.Value - _timing.CurTime;
|
||||
|
||||
TravelTimeLabel.Text =
|
||||
$"{Loc.GetString(_onStation ? "cp14-store-ui-next-travel-out" : "cp14-store-ui-next-travel-in")} {Math.Max(time.Minutes, 0):00}:{Math.Max(time.Seconds, 0):00}";
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateProducts(CP14StoreUiState state)
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
using Content.Shared._CP14.Vampire;
|
||||
using Content.Shared.Humanoid;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client._CP14.Vampire;
|
||||
|
||||
public sealed class CP14ClientVampireVisualsSystem : CP14SharedVampireVisualsSystem
|
||||
{
|
||||
protected override void OnVampireVisualsInit(Entity<CP14VampireVisualsComponent> vampire, ref ComponentInit args)
|
||||
{
|
||||
base.OnVampireVisualsInit(vampire, ref args);
|
||||
|
||||
if (!EntityManager.TryGetComponent(vampire, out SpriteComponent? sprite))
|
||||
return;
|
||||
|
||||
if (sprite.LayerMapTryGet(vampire.Comp.FangsMap, out var fangsLayerIndex))
|
||||
sprite.LayerSetVisible(fangsLayerIndex, true);
|
||||
|
||||
}
|
||||
|
||||
protected override void OnVampireVisualsShutdown(Entity<CP14VampireVisualsComponent> vampire, ref ComponentShutdown args)
|
||||
{
|
||||
base.OnVampireVisualsShutdown(vampire, ref args);
|
||||
|
||||
if (!EntityManager.TryGetComponent(vampire, out SpriteComponent? sprite))
|
||||
return;
|
||||
|
||||
if (sprite.LayerMapTryGet(vampire.Comp.FangsMap, out var fangsLayerIndex))
|
||||
sprite.LayerSetVisible(fangsLayerIndex, false);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Server._CP14.GameTicking.Rules.Components;
|
||||
using Content.Server.Administration.Commands;
|
||||
using Content.Server.Antag;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
@@ -36,6 +37,11 @@ public sealed partial class AdminVerbSystem
|
||||
[ValidatePrototypeId<StartingGearPrototype>]
|
||||
private const string PirateGearId = "PirateGear";
|
||||
|
||||
//CP14
|
||||
[ValidatePrototypeId<EntityPrototype>]
|
||||
private const string CP14VampireRule = "CP14Vampire";
|
||||
//CP14 end
|
||||
|
||||
// All antag verbs have names so invokeverb works.
|
||||
private void AddAntagVerbs(GetVerbsEvent<Verb> args)
|
||||
{
|
||||
@@ -52,6 +58,21 @@ public sealed partial class AdminVerbSystem
|
||||
|
||||
var targetPlayer = targetActor.PlayerSession;
|
||||
|
||||
Verb vampire = new()
|
||||
{
|
||||
Text = Loc.GetString("cp14-admin-verb-text-make-vampire"),
|
||||
Category = VerbCategory.Antag,
|
||||
Icon = new SpriteSpecifier.Rsi(new ResPath("/Textures/_CP14/Actions/Spells/vampire.rsi"),
|
||||
"bite"),
|
||||
Act = () =>
|
||||
{
|
||||
_antag.ForceMakeAntag<CP14VampireRuleComponent>(targetPlayer, CP14VampireRule);
|
||||
},
|
||||
Impact = LogImpact.High,
|
||||
Message = Loc.GetString("cp14-admin-verb-make-vampire"),
|
||||
};
|
||||
args.Verbs.Add(vampire);
|
||||
|
||||
/* CP14 disable default antags
|
||||
Verb traitor = new()
|
||||
{
|
||||
|
||||
55
Content.Server/_CP14/Cargo/CP14CargoSystem.Portals.cs
Normal file
55
Content.Server/_CP14/Cargo/CP14CargoSystem.Portals.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using Content.Server.Storage.Components;
|
||||
using Content.Shared._CP14.Cargo;
|
||||
using Content.Shared.Storage.Components;
|
||||
|
||||
namespace Content.Server._CP14.Cargo;
|
||||
|
||||
public sealed partial class CP14CargoSystem
|
||||
{
|
||||
private void InitializePortals()
|
||||
{
|
||||
SubscribeLocalEvent<CP14TradingPortalComponent, MapInitEvent>(OnTradePortalMapInit);
|
||||
|
||||
SubscribeLocalEvent<CP14TradingPortalComponent, StorageAfterCloseEvent>(OnTradePortalClose);
|
||||
SubscribeLocalEvent<CP14TradingPortalComponent, StorageAfterOpenEvent>(OnTradePortalOpen);
|
||||
}
|
||||
|
||||
private void UpdatePortals(float frameTime)
|
||||
{
|
||||
var query = EntityQueryEnumerator<CP14TradingPortalComponent, EntityStorageComponent>();
|
||||
while (query.MoveNext(out var ent, out var portal, out var storage))
|
||||
{
|
||||
if (portal.ProcessFinishTime == TimeSpan.Zero || portal.ProcessFinishTime >= _timing.CurTime)
|
||||
continue;
|
||||
|
||||
portal.ProcessFinishTime = TimeSpan.Zero;
|
||||
|
||||
SellingThings((ent, portal), storage);
|
||||
TopUpBalance((ent, portal), storage);
|
||||
BuyThings((ent, portal), storage);
|
||||
CashOut((ent, portal), storage);
|
||||
ThrowAllItems((ent, portal), storage);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTradePortalMapInit(Entity<CP14TradingPortalComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
AddRoundstartTradingPositions(ent);
|
||||
UpdateStaticPositions(ent);
|
||||
|
||||
ent.Comp.CurrentSpecialBuyPositions.Clear();
|
||||
ent.Comp.CurrentSpecialSellPositions.Clear();
|
||||
AddRandomBuySpecialPosition(ent, ent.Comp.SpecialBuyPositionCount);
|
||||
AddRandomSellSpecialPosition(ent, ent.Comp.SpecialSellPositionCount);
|
||||
}
|
||||
|
||||
private void OnTradePortalClose(Entity<CP14TradingPortalComponent> ent, ref StorageAfterCloseEvent args)
|
||||
{
|
||||
ent.Comp.ProcessFinishTime = _timing.CurTime + ent.Comp.Delay;
|
||||
}
|
||||
|
||||
private void OnTradePortalOpen(Entity<CP14TradingPortalComponent> ent, ref StorageAfterOpenEvent args)
|
||||
{
|
||||
ent.Comp.ProcessFinishTime = TimeSpan.Zero;
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
using System.Numerics;
|
||||
using Content.Server.Shuttles.Components;
|
||||
using Content.Server.Shuttles.Events;
|
||||
using Content.Shared._CP14.Cargo;
|
||||
using Content.Shared.Gravity;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server._CP14.Cargo;
|
||||
|
||||
public sealed partial class CP14CargoSystem
|
||||
{
|
||||
private void InitializeShuttle()
|
||||
{
|
||||
SubscribeLocalEvent<CP14TravelingStoreShipComponent, FTLCompletedEvent>(OnFTLCompleted);
|
||||
SubscribeLocalEvent<CP14TravelingStoreShipComponent, MapInitEvent>(OnMapInit);
|
||||
}
|
||||
|
||||
private void OnMapInit(Entity<CP14TravelingStoreShipComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
//TODO: This is shitcode! Because shouldnt related to traveling ship
|
||||
EnsureComp<GravityComponent>(ent, out var gravity);
|
||||
gravity.Enabled = true;
|
||||
gravity.Inherent = true;
|
||||
}
|
||||
|
||||
private void UpdateShuttle()
|
||||
{
|
||||
var query = EntityQueryEnumerator<CP14StationTravelingStoreShipTargetComponent>();
|
||||
while (query.MoveNext(out var uid, out var ship))
|
||||
{
|
||||
if (_timing.CurTime < ship.NextTravelTime || ship.NextTravelTime == TimeSpan.Zero)
|
||||
continue;
|
||||
|
||||
if (ship.Shuttle is null || ship.TradePostMap is null)
|
||||
continue;
|
||||
|
||||
if (Transform(ship.Shuttle.Value).MapUid == Transform(ship.TradePostMap.Value).MapUid)
|
||||
{
|
||||
// if landed on trade post
|
||||
ship.NextTravelTime = _timing.CurTime + ship.StationWaitTime;
|
||||
SendShuttleToStation(ship.Shuttle.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if landed on station
|
||||
ship.NextTravelTime = _timing.CurTime + ship.TradePostWaitTime;
|
||||
SendShuttleToTradepost(ship.Shuttle.Value, ship.TradePostMap.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SendShuttleToStation(EntityUid shuttle, float startupTime = 0f)
|
||||
{
|
||||
var targetPoints = new List<EntityUid>();
|
||||
var targetEnumerator =
|
||||
EntityQueryEnumerator<CP14TravelingStoreShipFTLTargetComponent,
|
||||
TransformComponent>(); //TODO - different method position location
|
||||
while (targetEnumerator.MoveNext(out var uid, out _, out _))
|
||||
{
|
||||
targetPoints.Add(uid);
|
||||
}
|
||||
|
||||
if (targetPoints.Count == 0)
|
||||
return;
|
||||
|
||||
var target = _random.Pick(targetPoints);
|
||||
var targetXform = Transform(target);
|
||||
|
||||
var shuttleComp = Comp<ShuttleComponent>(shuttle);
|
||||
|
||||
_shuttles.FTLToCoordinates(shuttle,
|
||||
shuttleComp,
|
||||
targetXform.Coordinates,
|
||||
targetXform.LocalRotation,
|
||||
hyperspaceTime: 20f,
|
||||
startupTime: startupTime);
|
||||
}
|
||||
|
||||
private void SendShuttleToTradepost(EntityUid shuttle, EntityUid tradePostMap)
|
||||
{
|
||||
var shuttleComp = Comp<ShuttleComponent>(shuttle);
|
||||
|
||||
_shuttles.FTLToCoordinates(shuttle,
|
||||
shuttleComp,
|
||||
new EntityCoordinates(tradePostMap, Vector2.Zero),
|
||||
Angle.Zero,
|
||||
startupTime: 10f,
|
||||
hyperspaceTime: 20f);
|
||||
}
|
||||
|
||||
private void OnFTLCompleted(Entity<CP14TravelingStoreShipComponent> ent, ref FTLCompletedEvent args)
|
||||
{
|
||||
if (!TryComp<CP14StationTravelingStoreShipTargetComponent>(ent.Comp.Station, out var station))
|
||||
return;
|
||||
|
||||
if (station.TradePostMap is not null &&
|
||||
Transform(ent).MapUid == Transform(station.TradePostMap.Value).MapUid) //Landed on tradepost
|
||||
{
|
||||
station.OnStation = false;
|
||||
|
||||
SellingThings((ent.Comp.Station, station)); // +balance
|
||||
TopUpBalance((ent.Comp.Station, station)); //+balance
|
||||
BuyToQueue((ent.Comp.Station, station)); //-balance +buyQueue
|
||||
TrySpawnBuyedThings((ent.Comp.Station, station));
|
||||
UpdateStorePositions((ent.Comp.Station, station));
|
||||
}
|
||||
else //Landed on station
|
||||
{
|
||||
station.OnStation = true;
|
||||
|
||||
CashOut((ent.Comp.Station, station));
|
||||
station.Balance = 0;
|
||||
}
|
||||
|
||||
UpdateAllStores();
|
||||
}
|
||||
}
|
||||
@@ -8,101 +8,109 @@ public sealed partial class CP14CargoSystem
|
||||
{
|
||||
public void InitializeUI()
|
||||
{
|
||||
SubscribeLocalEvent<CP14CargoStoreComponent, BeforeActivatableUIOpenEvent>(OnBeforeUIOpen);
|
||||
SubscribeLocalEvent<CP14TradingInfoBoardComponent, BeforeActivatableUIOpenEvent>(OnBeforeUIOpen);
|
||||
}
|
||||
|
||||
private void TryInitStore(Entity<CP14CargoStoreComponent> ent)
|
||||
private void TryInitStore(Entity<CP14TradingInfoBoardComponent> ent)
|
||||
{
|
||||
//TODO: There's no support for multiple stations. (settlements).
|
||||
var stations = _station.GetStations();
|
||||
|
||||
if (stations.Count == 0)
|
||||
return;
|
||||
|
||||
if (!TryComp<CP14StationTravelingStoreShipTargetComponent>(stations[0], out var station))
|
||||
return;
|
||||
|
||||
ent.Comp.Station = new Entity<CP14StationTravelingStoreShipTargetComponent>(stations[0], station);
|
||||
//TODO: more accurate way to find the trading portal, without lookup
|
||||
var entitiesInRange = _lookup.GetEntitiesInRange<CP14TradingPortalComponent>(Transform(ent).Coordinates, 2);
|
||||
foreach (var trading in entitiesInRange)
|
||||
{
|
||||
ent.Comp.TradingPortal = trading;
|
||||
ent.Comp.CahcedFaction = trading.Comp.Faction;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBeforeUIOpen(Entity<CP14CargoStoreComponent> ent, ref BeforeActivatableUIOpenEvent args)
|
||||
private void OnBeforeUIOpen(Entity<CP14TradingInfoBoardComponent> ent, ref BeforeActivatableUIOpenEvent args)
|
||||
{
|
||||
//TODO: If you open a store on a mapping, and initStore() it, the entity will throw an error when you try to save the grid\map.
|
||||
|
||||
if (ent.Comp.Station is null)
|
||||
if (ent.Comp.TradingPortal is null)
|
||||
TryInitStore(ent);
|
||||
|
||||
UpdateUIProducts(ent);
|
||||
}
|
||||
|
||||
private void UpdateAllStores()
|
||||
private void UpdateUIProducts(Entity<CP14TradingInfoBoardComponent> ent)
|
||||
{
|
||||
//TODO: redo
|
||||
var query = EntityQueryEnumerator<CP14CargoStoreComponent>();
|
||||
while (query.MoveNext(out var uid, out var store))
|
||||
{
|
||||
UpdateUIProducts((uid, store));
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateUIProducts(Entity<CP14CargoStoreComponent> ent)
|
||||
{
|
||||
if (ent.Comp.Station is null)
|
||||
if (ent.Comp.TradingPortal is null)
|
||||
return;
|
||||
|
||||
if (!TryComp<CP14StationTravelingStoreShipTargetComponent>(ent.Comp.Station.Value, out var storeTargetComp))
|
||||
if (!TryComp<CP14TradingPortalComponent>(ent.Comp.TradingPortal.Value, out var tradePortalComp))
|
||||
return;
|
||||
|
||||
var prodBuy = new HashSet<CP14StoreUiProductEntry>();
|
||||
var prodSell = new HashSet<CP14StoreUiProductEntry>();
|
||||
|
||||
//Add special buy positions
|
||||
foreach (var (proto, price) in storeTargetComp.CurrentSpecialBuyPositions)
|
||||
foreach (var (proto, price) in tradePortalComp.CurrentSpecialBuyPositions)
|
||||
{
|
||||
var name = Loc.GetString(proto.Name);
|
||||
var name = proto.NameOverride ?? proto.Service.GetName(_proto);
|
||||
var desc = new StringBuilder();
|
||||
desc.Append(Loc.GetString(proto.Desc) + "\n");
|
||||
desc.Append("\n" + Loc.GetString("cp14-store-buy-hint", ("name", Loc.GetString(proto.Name)), ("code", "[color=yellow][bold]#" + proto.Code + "[/bold][/color]")));
|
||||
//desc.Append(Loc.GetString(proto.Desc) + "\n");
|
||||
desc.Append("\n" + Loc.GetString("cp14-store-buy-hint", ("name", name), ("code", "[color=yellow][bold]#" + proto.Code + "[/bold][/color]")));
|
||||
|
||||
prodBuy.Add(new CP14StoreUiProductEntry(proto.ID, proto.Icon, name, desc.ToString(), price, true));
|
||||
prodBuy.Add(new CP14StoreUiProductEntry(proto.ID, proto.IconOverride ?? proto.Service.GetTexture(_proto), proto.Service.GetEntityView(_proto), name, desc.ToString(), price, true));
|
||||
}
|
||||
|
||||
//Add static buy positions
|
||||
foreach (var (proto, price) in storeTargetComp.CurrentBuyPositions)
|
||||
foreach (var (proto, price) in tradePortalComp.CurrentBuyPositions)
|
||||
{
|
||||
var name = Loc.GetString(proto.Name);
|
||||
var name = proto.NameOverride ?? proto.Service.GetName(_proto);
|
||||
var desc = new StringBuilder();
|
||||
desc.Append(Loc.GetString(proto.Desc) + "\n");
|
||||
desc.Append("\n" + Loc.GetString("cp14-store-buy-hint", ("name", Loc.GetString(proto.Name)), ("code", "[color=yellow][bold]#" + proto.Code + "[/bold][/color]")));
|
||||
//desc.Append(Loc.GetString(proto.Desc) + "\n");
|
||||
desc.Append("\n" + Loc.GetString("cp14-store-buy-hint", ("name", name), ("code", "[color=yellow][bold]#" + proto.Code + "[/bold][/color]")));
|
||||
|
||||
prodBuy.Add(new CP14StoreUiProductEntry(proto.ID, proto.Icon, name, desc.ToString(), price, false));
|
||||
prodBuy.Add(new CP14StoreUiProductEntry(proto.ID, proto.IconOverride ?? proto.Service.GetTexture(_proto), proto.Service.GetEntityView(_proto), name, desc.ToString(), price, false));
|
||||
}
|
||||
|
||||
//Add special sell positions
|
||||
foreach (var (proto, price) in storeTargetComp.CurrentSpecialSellPositions)
|
||||
foreach (var (proto, price) in tradePortalComp.CurrentSpecialSellPositions)
|
||||
{
|
||||
var name = Loc.GetString(proto.Name);
|
||||
var name = proto.Service.GetName(_proto);
|
||||
|
||||
var desc = new StringBuilder();
|
||||
desc.Append(Loc.GetString(proto.Desc) + "\n");
|
||||
desc.Append("\n" + Loc.GetString("cp14-store-sell-hint", ("name", Loc.GetString(proto.Name))));
|
||||
//desc.Append(Loc.GetString(proto.Desc) + "\n");
|
||||
desc.Append("\n" + Loc.GetString("cp14-store-sell-hint", ("name", name)));
|
||||
|
||||
prodSell.Add(new CP14StoreUiProductEntry(proto.ID, proto.Icon, name, desc.ToString(), price, true));
|
||||
prodSell.Add(new CP14StoreUiProductEntry(
|
||||
proto.ID,
|
||||
proto.Service.GetTexture(_proto),
|
||||
proto.Service.GetEntityView(_proto),
|
||||
name,
|
||||
desc.ToString(),
|
||||
price,
|
||||
true));
|
||||
}
|
||||
|
||||
//Add static sell positions
|
||||
foreach (var proto in storeTargetComp.CurrentSellPositions)
|
||||
foreach (var proto in tradePortalComp.CurrentSellPositions)
|
||||
{
|
||||
var name = Loc.GetString(proto.Key.Name);
|
||||
var name = proto.Key.Service.GetName(_proto);
|
||||
|
||||
var desc = new StringBuilder();
|
||||
desc.Append(Loc.GetString(proto.Key.Desc) + "\n");
|
||||
desc.Append("\n" + Loc.GetString("cp14-store-sell-hint", ("name", Loc.GetString(proto.Key.Name))));
|
||||
//desc.Append(Loc.GetString(proto.Key.Desc) + "\n");
|
||||
desc.Append("\n" + Loc.GetString("cp14-store-sell-hint", ("name", name)));
|
||||
|
||||
prodSell.Add(new CP14StoreUiProductEntry(proto.Key.ID, proto.Key.Icon, name, desc.ToString(), proto.Value, false));
|
||||
prodSell.Add(new CP14StoreUiProductEntry(
|
||||
proto.Key.ID,
|
||||
proto.Key.Service.GetTexture(_proto),
|
||||
proto.Key.Service.GetEntityView(_proto),
|
||||
name,
|
||||
desc.ToString(),
|
||||
proto.Value,
|
||||
false));
|
||||
}
|
||||
|
||||
var stationComp = storeTargetComp;
|
||||
_userInterface.SetUiState(ent.Owner, CP14StoreUiKey.Key, new CP14StoreUiState(prodBuy, prodSell, stationComp.OnStation, stationComp.NextTravelTime));
|
||||
var shopName = ":3";
|
||||
//Get shop name
|
||||
if (ent.Comp.CahcedFaction is not null && _proto.TryIndex(ent.Comp.CahcedFaction.Value, out var indexedShop))
|
||||
{
|
||||
shopName = Loc.GetString(indexedShop.Name);
|
||||
}
|
||||
|
||||
_userInterface.SetUiState(ent.Owner, CP14StoreUiKey.Key, new CP14StoreUiState(shopName, prodBuy, prodSell));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Server._CP14.Currency;
|
||||
using Content.Server._CP14.RoundRemoveShuttle;
|
||||
using Content.Server.Shuttles.Systems;
|
||||
using Content.Server.Station.Events;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Server.Storage.Components;
|
||||
using Content.Server.Storage.EntitySystems;
|
||||
using Content.Shared._CP14.Cargo;
|
||||
using Content.Shared._CP14.Cargo.Prototype;
|
||||
using Content.Shared.Maps;
|
||||
using Content.Shared.Paper;
|
||||
using Content.Shared.Physics;
|
||||
using Content.Shared.Station.Components;
|
||||
using Content.Shared.Storage;
|
||||
using Content.Shared.Storage.EntitySystems;
|
||||
using JetBrains.Annotations;
|
||||
using Content.Shared.Throwing;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.EntitySerialization.Systems;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Timing;
|
||||
@@ -24,20 +16,15 @@ namespace Content.Server._CP14.Cargo;
|
||||
|
||||
public sealed partial class CP14CargoSystem : CP14SharedCargoSystem
|
||||
{
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly MapLoaderSystem _loader = default!;
|
||||
[Dependency] private readonly ShuttleSystem _shuttles = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _userInterface = default!;
|
||||
[Dependency] private readonly StationSystem _station = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly CP14CurrencySystem _currency = default!;
|
||||
[Dependency] private readonly SharedStorageSystem _storage = default!;
|
||||
[Dependency] private readonly TurfSystem _turf = default!;
|
||||
|
||||
private EntityQuery<TransformComponent> _xformQuery;
|
||||
[Dependency] private readonly EntityStorageSystem _entityStorage = default!;
|
||||
[Dependency] private readonly ThrowingSystem _throwing = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
|
||||
private IEnumerable<CP14StoreBuyPositionPrototype>? _buyProto;
|
||||
private IEnumerable<CP14StoreSellPositionPrototype>? _sellProto;
|
||||
@@ -48,15 +35,18 @@ public sealed partial class CP14CargoSystem : CP14SharedCargoSystem
|
||||
base.Initialize();
|
||||
|
||||
InitializeUI();
|
||||
InitializeShuttle();
|
||||
|
||||
_xformQuery = GetEntityQuery<TransformComponent>();
|
||||
InitializePortals();
|
||||
|
||||
_buyProto = _proto.EnumeratePrototypes<CP14StoreBuyPositionPrototype>();
|
||||
_sellProto = _proto.EnumeratePrototypes<CP14StoreSellPositionPrototype>();
|
||||
|
||||
SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnProtoReload);
|
||||
SubscribeLocalEvent<CP14StationTravelingStoreShipTargetComponent, StationPostInitEvent>(OnPostInit);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
UpdatePortals(frameTime);
|
||||
}
|
||||
|
||||
private void OnProtoReload(PrototypesReloadedEventArgs ev)
|
||||
@@ -65,61 +55,14 @@ public sealed partial class CP14CargoSystem : CP14SharedCargoSystem
|
||||
_sellProto = _proto.EnumeratePrototypes<CP14StoreSellPositionPrototype>();
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
UpdateShuttle();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows other systems to additionally add items to the queue that are brought to the settlement on a merchant ship.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public void AddBuyQueue(Entity<CP14StationTravelingStoreShipTargetComponent> station, List<EntProtoId> products)
|
||||
{
|
||||
foreach (var product in products)
|
||||
{
|
||||
station.Comp.BuyedQueue.Enqueue(product);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPostInit(Entity<CP14StationTravelingStoreShipTargetComponent> station, ref StationPostInitEvent args)
|
||||
{
|
||||
if (!Deleted(station.Comp.Shuttle))
|
||||
return;
|
||||
|
||||
var tradepostMap = _mapManager.CreateMap();
|
||||
|
||||
if (!_loader.TryLoadGrid(tradepostMap ,station.Comp.ShuttlePath, out var shuttle))
|
||||
return;
|
||||
|
||||
|
||||
station.Comp.Shuttle = shuttle;
|
||||
station.Comp.TradePostMap = _mapManager.GetMapEntityId(tradepostMap);
|
||||
var travelingStoreShipComp = EnsureComp<CP14TravelingStoreShipComponent>(station.Comp.Shuttle.Value);
|
||||
travelingStoreShipComp.Station = station;
|
||||
|
||||
var member = EnsureComp<StationMemberComponent>(shuttle.Value);
|
||||
member.Station = station;
|
||||
|
||||
var roundRemover = EnsureComp<CP14RoundRemoveShuttleComponent>(shuttle.Value);
|
||||
roundRemover.Station = station;
|
||||
|
||||
station.Comp.NextTravelTime = _timing.CurTime + TimeSpan.FromSeconds(10f);
|
||||
|
||||
AddRoundstartTradingPositions(station);
|
||||
UpdateStorePositions(station);
|
||||
}
|
||||
|
||||
private void AddRoundstartTradingPositions(Entity<CP14StationTravelingStoreShipTargetComponent> station)
|
||||
private void AddRoundstartTradingPositions(Entity<CP14TradingPortalComponent> portal)
|
||||
{
|
||||
if (_buyProto is not null)
|
||||
{
|
||||
foreach (var buy in _buyProto)
|
||||
{
|
||||
if (buy.RoundstartAvailable)
|
||||
station.Comp.AvailableBuyPosition.Add(buy);
|
||||
portal.Comp.AvailableBuyPosition.Add(buy);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,123 +71,149 @@ public sealed partial class CP14CargoSystem : CP14SharedCargoSystem
|
||||
foreach (var sell in _sellProto)
|
||||
{
|
||||
if (sell.RoundstartAvailable)
|
||||
station.Comp.AvailableSellPosition.Add(sell);
|
||||
portal.Comp.AvailableSellPosition.Add(sell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateStorePositions(Entity<CP14StationTravelingStoreShipTargetComponent> station)
|
||||
private void UpdateStaticPositions(Entity<CP14TradingPortalComponent> portal)
|
||||
{
|
||||
station.Comp.CurrentBuyPositions.Clear();
|
||||
station.Comp.CurrentSellPositions.Clear();
|
||||
station.Comp.CurrentSpecialBuyPositions.Clear();
|
||||
station.Comp.CurrentSpecialSellPositions.Clear();
|
||||
|
||||
var availableSpecialSellPositions = new List<CP14StoreSellPositionPrototype>();
|
||||
var availableSpecialBuyPositions = new List<CP14StoreBuyPositionPrototype>();
|
||||
portal.Comp.CurrentBuyPositions.Clear();
|
||||
portal.Comp.CurrentSellPositions.Clear();
|
||||
|
||||
//Add static positions + cash special ones
|
||||
foreach (var buyPos in station.Comp.AvailableBuyPosition)
|
||||
foreach (var buyPos in portal.Comp.AvailableBuyPosition)
|
||||
{
|
||||
if (buyPos.Special)
|
||||
availableSpecialBuyPositions.Add(buyPos);
|
||||
else
|
||||
station.Comp.CurrentBuyPositions.Add(buyPos, buyPos.Price);
|
||||
continue;
|
||||
|
||||
if (buyPos.Factions.Count > 0 && !buyPos.Factions.Contains(portal.Comp.Faction))
|
||||
continue;
|
||||
|
||||
portal.Comp.CurrentBuyPositions.Add(buyPos, buyPos.Price);
|
||||
}
|
||||
foreach (var sellPos in station.Comp.AvailableSellPosition)
|
||||
|
||||
foreach (var sellPos in portal.Comp.AvailableSellPosition)
|
||||
{
|
||||
if (sellPos.Special)
|
||||
availableSpecialSellPositions.Add(sellPos);
|
||||
else
|
||||
station.Comp.CurrentSellPositions.Add(sellPos, sellPos.Price);
|
||||
continue;
|
||||
|
||||
if (sellPos.Factions.Count > 0 && !sellPos.Factions.Contains(portal.Comp.Faction))
|
||||
continue;
|
||||
|
||||
portal.Comp.CurrentSellPositions.Add(sellPos, sellPos.Price);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddRandomBuySpecialPosition(Entity<CP14TradingPortalComponent> portal, int count)
|
||||
{
|
||||
if (_buyProto is null)
|
||||
return;
|
||||
|
||||
var availableSpecialBuyPositions = new List<CP14StoreBuyPositionPrototype>();
|
||||
foreach (var buyPos in _buyProto)
|
||||
{
|
||||
if (!buyPos.Special)
|
||||
continue;
|
||||
|
||||
if (portal.Comp.CurrentSpecialBuyPositions.ContainsKey(buyPos))
|
||||
continue;
|
||||
|
||||
if (buyPos.Factions.Count > 0 && !buyPos.Factions.Contains(portal.Comp.Faction))
|
||||
continue;
|
||||
|
||||
availableSpecialBuyPositions.Add(buyPos);
|
||||
}
|
||||
|
||||
//Random and select special positions
|
||||
_random.Shuffle(availableSpecialSellPositions);
|
||||
_random.Shuffle(availableSpecialBuyPositions);
|
||||
|
||||
var currentSpecialBuyPositions = station.Comp.SpecialBuyPositionCount.Next(_random);
|
||||
var currentSpecialSellPositions = station.Comp.SpecialSellPositionCount.Next(_random);
|
||||
|
||||
var added = 0;
|
||||
foreach (var buyPos in availableSpecialBuyPositions)
|
||||
{
|
||||
if (station.Comp.CurrentSpecialBuyPositions.Count >= currentSpecialBuyPositions)
|
||||
if (added >= count)
|
||||
break;
|
||||
station.Comp.CurrentSpecialBuyPositions.Add(buyPos, buyPos.Price);
|
||||
portal.Comp.CurrentSpecialBuyPositions.Add(buyPos, buyPos.Price);
|
||||
added++;
|
||||
}
|
||||
}
|
||||
|
||||
private void AddRandomSellSpecialPosition(Entity<CP14TradingPortalComponent> portal, int count)
|
||||
{
|
||||
if (_sellProto is null)
|
||||
return;
|
||||
|
||||
var availableSpecialSellPositions = new List<CP14StoreSellPositionPrototype>();
|
||||
foreach (var sellPos in _sellProto)
|
||||
{
|
||||
if (!sellPos.Special)
|
||||
continue;
|
||||
|
||||
if (portal.Comp.CurrentSpecialSellPositions.ContainsKey(sellPos))
|
||||
continue;
|
||||
|
||||
if (sellPos.Factions.Count > 0 && !sellPos.Factions.Contains(portal.Comp.Faction))
|
||||
continue;
|
||||
|
||||
availableSpecialSellPositions.Add(sellPos);
|
||||
}
|
||||
|
||||
_random.Shuffle(availableSpecialSellPositions);
|
||||
|
||||
var added = 0;
|
||||
foreach (var sellPos in availableSpecialSellPositions)
|
||||
{
|
||||
if (station.Comp.CurrentSpecialSellPositions.Count >= currentSpecialSellPositions)
|
||||
if (added >= count)
|
||||
break;
|
||||
station.Comp.CurrentSpecialSellPositions.Add(sellPos, sellPos.Price);
|
||||
portal.Comp.CurrentSpecialSellPositions.Add(sellPos, sellPos.Price);
|
||||
added++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sell all the items we can, and replenish the internal balance
|
||||
/// </summary>
|
||||
private void SellingThings(Entity<CP14StationTravelingStoreShipTargetComponent> station)
|
||||
private void SellingThings(Entity<CP14TradingPortalComponent> portal, EntityStorageComponent storage)
|
||||
{
|
||||
var shuttle = station.Comp.Shuttle;
|
||||
var containedEntities = storage.Contents.ContainedEntities.ToHashSet();
|
||||
//var ev = new BeforeSellEntities(ref portal.Comp.EntitiesInPortal);
|
||||
//RaiseLocalEvent(ev);
|
||||
|
||||
//Get all entities sent to trading posts
|
||||
var toSell = new HashSet<EntityUid>();
|
||||
|
||||
var query = EntityQueryEnumerator<CP14SellingPalettComponent, TransformComponent>();
|
||||
while (query.MoveNext(out var uid, out _, out var palletXform))
|
||||
foreach (var sellPos in portal.Comp.CurrentSellPositions)
|
||||
{
|
||||
if (palletXform.ParentUid != shuttle || !palletXform.Anchored)
|
||||
continue;
|
||||
|
||||
var sentEntities = new HashSet<EntityUid>();
|
||||
|
||||
_lookup.GetEntitiesInRange(uid, 0.5f, sentEntities, LookupFlags.Dynamic | LookupFlags.Sundries);
|
||||
|
||||
foreach (var ent in sentEntities)
|
||||
//WHILE = sell all we can
|
||||
while (sellPos.Key.Service.TrySell(EntityManager, containedEntities))
|
||||
{
|
||||
if (toSell.Contains(ent) || !_xformQuery.TryGetComponent(ent, out _))
|
||||
continue;
|
||||
|
||||
toSell.Add(ent);
|
||||
portal.Comp.Balance += sellPos.Value;
|
||||
}
|
||||
}
|
||||
|
||||
var ev = new BeforeSellEntities(ref toSell);
|
||||
RaiseLocalEvent(ev);
|
||||
|
||||
foreach (var sellPos in station.Comp.CurrentSellPositions)
|
||||
List<CP14StoreSellPositionPrototype> toRemove = new();
|
||||
foreach (var sellPos in portal.Comp.CurrentSpecialSellPositions)
|
||||
{
|
||||
while (sellPos.Key.Service.TrySell(EntityManager, toSell))
|
||||
//IF = only 1 try
|
||||
if (sellPos.Key.Service.TrySell(EntityManager, containedEntities))
|
||||
{
|
||||
station.Comp.Balance += sellPos.Value;
|
||||
portal.Comp.Balance += sellPos.Value;
|
||||
toRemove.Add(sellPos.Key);
|
||||
}
|
||||
}
|
||||
foreach (var sellPos in station.Comp.CurrentSpecialSellPositions)
|
||||
|
||||
//Remove this special position from the list and add new random one
|
||||
foreach (var position in toRemove)
|
||||
{
|
||||
while (sellPos.Key.Service.TrySell(EntityManager, toSell))
|
||||
{
|
||||
station.Comp.Balance += sellPos.Value;
|
||||
}
|
||||
portal.Comp.CurrentSpecialSellPositions.Remove(position);
|
||||
AddRandomSellSpecialPosition(portal, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Take all the money from the tradebox, and credit it to the internal balance
|
||||
/// Take all the money from the portal, and credit it to the internal balance
|
||||
/// </summary>
|
||||
private void TopUpBalance(Entity<CP14StationTravelingStoreShipTargetComponent> station)
|
||||
private void TopUpBalance(Entity<CP14TradingPortalComponent> portal, EntityStorageComponent storage)
|
||||
{
|
||||
var tradebox = GetTradeBox(station);
|
||||
|
||||
if (tradebox is null)
|
||||
return;
|
||||
|
||||
if (!TryComp<StorageComponent>(tradebox, out var tradeStorage))
|
||||
return;
|
||||
|
||||
//Get all currency in tradebox
|
||||
int cash = 0;
|
||||
foreach (var stored in tradeStorage.Container.ContainedEntities)
|
||||
//Get all currency in portal
|
||||
var cash = 0;
|
||||
foreach (var stored in storage.Contents.ContainedEntities)
|
||||
{
|
||||
var price = _currency.GetTotalCurrency(stored);
|
||||
if (price > 0)
|
||||
@@ -254,22 +223,14 @@ public sealed partial class CP14CargoSystem : CP14SharedCargoSystem
|
||||
}
|
||||
}
|
||||
|
||||
station.Comp.Balance += cash;
|
||||
portal.Comp.Balance += cash;
|
||||
}
|
||||
|
||||
private void BuyToQueue(Entity<CP14StationTravelingStoreShipTargetComponent> station)
|
||||
private void BuyThings(Entity<CP14TradingPortalComponent> portal, EntityStorageComponent storage)
|
||||
{
|
||||
var tradebox = GetTradeBox(station);
|
||||
|
||||
if (tradebox is null)
|
||||
return;
|
||||
|
||||
if (!TryComp<StorageComponent>(tradebox, out var tradeStorage))
|
||||
return;
|
||||
|
||||
//Reading all papers in tradebox
|
||||
//Reading all papers in portal
|
||||
List<KeyValuePair<CP14StoreBuyPositionPrototype, int>> requests = new();
|
||||
foreach (var stored in tradeStorage.Container.ContainedEntities)
|
||||
foreach (var stored in storage.Contents.ContainedEntities)
|
||||
{
|
||||
if (!TryComp<PaperComponent>(stored, out var paper))
|
||||
continue;
|
||||
@@ -277,12 +238,13 @@ public sealed partial class CP14CargoSystem : CP14SharedCargoSystem
|
||||
var splittedText = paper.Content.Split("#");
|
||||
foreach (var fragment in splittedText)
|
||||
{
|
||||
foreach (var buyPosition in station.Comp.CurrentBuyPositions)
|
||||
foreach (var buyPosition in portal.Comp.CurrentBuyPositions)
|
||||
{
|
||||
if (fragment.StartsWith(buyPosition.Key.Code))
|
||||
requests.Add(buyPosition);
|
||||
}
|
||||
foreach (var buyPosition in station.Comp.CurrentSpecialBuyPositions)
|
||||
|
||||
foreach (var buyPosition in portal.Comp.CurrentSpecialBuyPositions)
|
||||
{
|
||||
if (fragment.StartsWith(buyPosition.Key.Code))
|
||||
requests.Add(buyPosition);
|
||||
@@ -292,80 +254,57 @@ public sealed partial class CP14CargoSystem : CP14SharedCargoSystem
|
||||
QueueDel(stored);
|
||||
}
|
||||
|
||||
//Trying spend tradebox money to buy requested things
|
||||
//Trying to spend inner money to buy requested things
|
||||
foreach (var request in requests)
|
||||
{
|
||||
if (station.Comp.Balance < request.Value)
|
||||
if (portal.Comp.Balance < request.Value)
|
||||
continue;
|
||||
|
||||
station.Comp.Balance -= request.Value;
|
||||
portal.Comp.Balance -= request.Value;
|
||||
|
||||
if (!_proto.TryIndex<CP14StoreBuyPositionPrototype>(request.Key, out var indexedBuyed))
|
||||
continue;
|
||||
|
||||
foreach (var service in indexedBuyed.Services)
|
||||
//Remove this position from the list and add new random one
|
||||
if (request.Key.Special)
|
||||
{
|
||||
service.Buy(EntityManager, _proto, station);
|
||||
portal.Comp.CurrentSpecialBuyPositions.Remove(request.Key);
|
||||
AddRandomBuySpecialPosition(portal, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Dequeue buyed items, and spawn they on shuttle
|
||||
private void TrySpawnBuyedThings(Entity<CP14StationTravelingStoreShipTargetComponent> station)
|
||||
{
|
||||
var shuttle = station.Comp.Shuttle;
|
||||
|
||||
var query = EntityQueryEnumerator<CP14BuyingPalettComponent, TransformComponent>();
|
||||
while (query.MoveNext(out var uid, out _, out var palletXform))
|
||||
{
|
||||
if (station.Comp.BuyedQueue.Count <= 0)
|
||||
break;
|
||||
|
||||
if (palletXform.ParentUid != shuttle || !palletXform.Anchored)
|
||||
continue;
|
||||
|
||||
var tileRef = palletXform.Coordinates.GetTileRef();
|
||||
if (tileRef is null)
|
||||
continue;
|
||||
|
||||
if (_turf.IsTileBlocked(tileRef.Value, CollisionGroup.ItemMask))
|
||||
continue;
|
||||
|
||||
var buyedThing = station.Comp.BuyedQueue.Dequeue();
|
||||
Spawn(buyedThing, palletXform.Coordinates);
|
||||
indexedBuyed.Service.Buy(EntityManager, _proto, portal);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transform all the accumulated balance into physical money, which we will give to the players.
|
||||
/// </summary>
|
||||
private void CashOut(Entity<CP14StationTravelingStoreShipTargetComponent> station)
|
||||
private void CashOut(Entity<CP14TradingPortalComponent> portal, EntityStorageComponent storage)
|
||||
{
|
||||
var moneyBox = GetTradeBox(station);
|
||||
if (moneyBox is not null)
|
||||
var coins = _currency.GenerateMoney(portal.Comp.Balance, Transform(portal).Coordinates);
|
||||
foreach (var coin in coins)
|
||||
{
|
||||
var coord = Transform(moneyBox.Value).Coordinates;
|
||||
|
||||
var coins = _currency.GenerateMoney(station.Comp.Balance, coord);
|
||||
foreach (var coin in coins)
|
||||
{
|
||||
_storage.Insert(moneyBox.Value, coin, out _);
|
||||
}
|
||||
_entityStorage.Insert(coin, portal, storage);
|
||||
}
|
||||
portal.Comp.Balance = 0;
|
||||
}
|
||||
|
||||
private EntityUid? GetTradeBox(Entity<CP14StationTravelingStoreShipTargetComponent> station)
|
||||
/// <summary>
|
||||
/// Return all items to the map
|
||||
/// </summary>
|
||||
private void ThrowAllItems(Entity<CP14TradingPortalComponent> portal, EntityStorageComponent storage)
|
||||
{
|
||||
var query = EntityQueryEnumerator<CP14CargoMoneyBoxComponent, TransformComponent>();
|
||||
var containedEntities = storage.Contents.ContainedEntities.ToList();
|
||||
|
||||
while (query.MoveNext(out var uid, out _, out var xform))
|
||||
_entityStorage.OpenStorage(portal, storage);
|
||||
|
||||
var xform = Transform(portal);
|
||||
var rotation = xform.LocalRotation;
|
||||
foreach (var stored in containedEntities)
|
||||
{
|
||||
if (xform.GridUid != station.Comp.Shuttle)
|
||||
continue;
|
||||
|
||||
return uid;
|
||||
_transform.AttachToGridOrMap(stored);
|
||||
var targetThrowPosition = xform.Coordinates.Offset(rotation.ToWorldVec() * 1);
|
||||
_throwing.TryThrow(stored, targetThrowPosition.Offset(new Vector2(_random.NextFloat(-0.5f, 0.5f), _random.NextFloat(-0.5f, 0.5f))));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Content.Server._CP14.Cargo;
|
||||
|
||||
[RegisterComponent, Access(typeof(CP14CargoSystem))]
|
||||
public sealed partial class CP14TravelingStoreShipComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public EntityUid Station;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
namespace Content.Server._CP14.Cargo;
|
||||
|
||||
/// <summary>
|
||||
/// One of the possible points where an traveling store ship might land
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(CP14CargoSystem))]
|
||||
public sealed partial class CP14TravelingStoreShipFTLTargetComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -7,6 +7,7 @@ using Content.Shared.Stacks;
|
||||
using Content.Shared.Storage;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Server.Audio;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._CP14.Currency;
|
||||
@@ -28,12 +29,14 @@ public sealed partial class CP14CurrencySystem : CP14SharedCurrencySystem
|
||||
SubscribeLocalEvent<CP14CurrencyExaminableComponent, ExaminedEvent>(OnExamine);
|
||||
|
||||
SubscribeLocalEvent<CP14CurrencyComponent, CP14GetCurrencyEvent>(OnGetCurrency);
|
||||
//SubscribeLocalEvent<EntityStorageComponent, CP14GetCurrencyEvent>(OnEntityStorageGetCurrency);
|
||||
//SubscribeLocalEvent<StorageComponent, CP14GetCurrencyEvent>(OnStorageGetCurrency);
|
||||
SubscribeLocalEvent<ContainerManagerComponent, CP14GetCurrencyEvent>(OnContainerGetCurrency);
|
||||
}
|
||||
|
||||
private void OnGetCurrency(Entity<CP14CurrencyComponent> ent, ref CP14GetCurrencyEvent args)
|
||||
{
|
||||
if (args.CheckedEntities.Contains(ent))
|
||||
return;
|
||||
|
||||
var total = ent.Comp.Currency;
|
||||
if (TryComp<StackComponent>(ent, out var stack))
|
||||
{
|
||||
@@ -41,29 +44,22 @@ public sealed partial class CP14CurrencySystem : CP14SharedCurrencySystem
|
||||
}
|
||||
|
||||
args.Currency += total;
|
||||
args.CheckedEntities.Add(ent);
|
||||
}
|
||||
|
||||
//private void OnEntityStorageGetCurrency(Entity<EntityStorageComponent> ent, ref CP14GetCurrencyEvent args)
|
||||
//{
|
||||
// var total = 0;
|
||||
// foreach (var entity in ent.Comp.Contents.ContainedEntities)
|
||||
// {
|
||||
// total += GetTotalCurrency(entity);
|
||||
// }
|
||||
//
|
||||
// args.Currency += total;
|
||||
//}
|
||||
//
|
||||
//private void OnStorageGetCurrency(Entity<StorageComponent> ent, ref CP14GetCurrencyEvent args)
|
||||
//{
|
||||
// var total = 0;
|
||||
// foreach (var entity in ent.Comp.StoredItems)
|
||||
// {
|
||||
// total += GetTotalCurrency(entity.Key);
|
||||
// }
|
||||
//
|
||||
// args.Currency += total;
|
||||
//}
|
||||
private void OnContainerGetCurrency(Entity<ContainerManagerComponent> ent, ref CP14GetCurrencyEvent args)
|
||||
{
|
||||
var total = 0;
|
||||
foreach (var container in ent.Comp.Containers.Values)
|
||||
{
|
||||
foreach (var containedEnt in container.ContainedEntities)
|
||||
{
|
||||
total += GetTotalCurrency(containedEnt);
|
||||
}
|
||||
}
|
||||
|
||||
args.Currency += total;
|
||||
}
|
||||
|
||||
private void OnExamine(Entity<CP14CurrencyExaminableComponent> currency, ref ExaminedEvent args)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
using Content.Server._CP14.DayCycle;
|
||||
using Content.Server._CP14.GameTicking.Rules.Components;
|
||||
using Content.Server._CP14.Vampire;
|
||||
using Content.Server.Atmos.Components;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.GameTicking.Rules;
|
||||
using Content.Server.Temperature.Components;
|
||||
using Content.Server.Temperature.Systems;
|
||||
using Content.Shared._CP14.Vampire;
|
||||
using Content.Shared.Nutrition.Components;
|
||||
using Content.Shared.Nutrition.EntitySystems;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server._CP14.GameTicking.Rules;
|
||||
|
||||
public sealed class CP14VampireRuleSystem : GameRuleSystem<CP14VampireRuleComponent>
|
||||
{
|
||||
[Dependency] private readonly BloodstreamSystem _bloodstream = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly TemperatureSystem _temperature = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
[Dependency] private readonly CP14DayCycleSystem _dayCycle = default!;
|
||||
[Dependency] private readonly FlammableSystem _flammable = default!;
|
||||
[Dependency] private readonly BodySystem _body = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<CP14VampireComponent, MapInitEvent>(OnVampireInit);
|
||||
SubscribeLocalEvent<CP14VampireComponent, CP14HungerChangedEvent>(OnVampireHungerChanged);
|
||||
}
|
||||
|
||||
private void OnVampireHungerChanged(Entity<CP14VampireComponent> ent, ref CP14HungerChangedEvent args)
|
||||
{
|
||||
if (args.NewThreshold == HungerThreshold.Starving || args.NewThreshold == HungerThreshold.Dead)
|
||||
{
|
||||
RevealVampire(ent);
|
||||
}
|
||||
else
|
||||
{
|
||||
HideVampire(ent);
|
||||
}
|
||||
}
|
||||
|
||||
private void RevealVampire(Entity<CP14VampireComponent> ent)
|
||||
{
|
||||
EnsureComp<CP14VampireVisualsComponent>(ent);
|
||||
}
|
||||
|
||||
private void HideVampire(Entity<CP14VampireComponent> ent)
|
||||
{
|
||||
RemCompDeferred<CP14VampireVisualsComponent>(ent);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
var query = EntityQueryEnumerator<CP14VampireComponent, TemperatureComponent, FlammableComponent>();
|
||||
while (query.MoveNext(out var uid, out var vampire, out var temperature, out var flammable))
|
||||
{
|
||||
if (_timing.CurTime < vampire.NextHeatTime)
|
||||
continue;
|
||||
|
||||
vampire.NextHeatTime = _timing.CurTime + vampire.HeatFrequency;
|
||||
|
||||
if (!_dayCycle.TryDaylightThere(uid))
|
||||
continue;
|
||||
|
||||
_temperature.ChangeHeat(uid, vampire.HeatUnderSunTemperature);
|
||||
_popup.PopupEntity(Loc.GetString("cp14-heat-under-sun"), uid, uid, PopupType.SmallCaution);
|
||||
|
||||
if (temperature.CurrentTemperature > vampire.IgniteThreshold && !flammable.OnFire)
|
||||
{
|
||||
_flammable.AdjustFireStacks(uid, 1, flammable);
|
||||
_flammable.Ignite(uid, uid, flammable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnVampireInit(Entity<CP14VampireComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
_bloodstream.ChangeBloodReagent(ent, ent.Comp.NewBloodReagent);
|
||||
|
||||
foreach (var (organUid, _) in _body.GetBodyOrgans(ent))
|
||||
{
|
||||
if (TryComp<MetabolizerComponent>(organUid, out var metabolizer) && metabolizer.MetabolizerTypes is not null)
|
||||
{
|
||||
metabolizer.MetabolizerTypes.Add(ent.Comp.MetabolizerType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Content.Server._CP14.GameTicking.Rules.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Stores data for <see cref="CP14VampireRuleSystem"/>.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(CP14VampireRuleSystem))]
|
||||
public sealed partial class CP14VampireRuleComponent : Component;
|
||||
@@ -0,0 +1,71 @@
|
||||
using Content.Shared._CP14.Knowledge.Components;
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Administration.Managers;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._CP14.Knowledge;
|
||||
|
||||
// TODO: Add UI
|
||||
public sealed class CP14KnowledgeAdminUtilitiesSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly ISharedAdminManager _admin = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly CP14KnowledgeSystem _knowledge = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<CP14KnowledgeStorageComponent, GetVerbsEvent<Verb>>(AddKnowledgeAdminVerb);
|
||||
}
|
||||
|
||||
private void AddKnowledgeAdminVerb(Entity<CP14KnowledgeStorageComponent> entity, ref GetVerbsEvent<Verb> args)
|
||||
{
|
||||
if (!_admin.HasAdminFlag(args.User, AdminFlags.Admin))
|
||||
return;
|
||||
|
||||
// Remove knowledge
|
||||
foreach (var knowledge in entity.Comp.Knowledge)
|
||||
{
|
||||
if (!_prototype.TryIndex(knowledge, out var indexedKnowledge))
|
||||
continue;
|
||||
|
||||
args.Verbs.Add(new Verb
|
||||
{
|
||||
Text = $"{Loc.GetString(indexedKnowledge.Name)}",
|
||||
Message = Loc.GetString(indexedKnowledge.Desc),
|
||||
Category = VerbCategory.CP14KnowledgeRemove,
|
||||
Act = () =>
|
||||
{
|
||||
_knowledge.TryRemove(entity.Owner, knowledge);
|
||||
},
|
||||
Impact = LogImpact.High,
|
||||
});
|
||||
}
|
||||
|
||||
// Add knowledge
|
||||
foreach (var knowledge in _prototype.EnumeratePrototypes<CP14KnowledgePrototype>())
|
||||
{
|
||||
// An entity with CP14AllKnowingComponent can't be taught anything,
|
||||
// it already knows everything
|
||||
if (_knowledge.HasKnowledge(entity.Owner, knowledge.ID))
|
||||
continue;
|
||||
|
||||
args.Verbs.Add(new Verb
|
||||
{
|
||||
Text = $"{Loc.GetString(knowledge.Name)}",
|
||||
Message = Loc.GetString(knowledge.Desc),
|
||||
Category = VerbCategory.CP14KnowledgeAdd,
|
||||
Act = () =>
|
||||
{
|
||||
_knowledge.TryAdd(entity.Owner, knowledge, true);
|
||||
},
|
||||
Impact = LogImpact.High,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,30 +1,23 @@
|
||||
using System.Text;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.Mind;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared._CP14.Knowledge;
|
||||
using Content.Shared._CP14.Knowledge.Components;
|
||||
using Content.Shared._CP14.Knowledge.Events;
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Administration.Managers;
|
||||
using Content.Shared.Chat;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server._CP14.Knowledge;
|
||||
|
||||
public sealed partial class CP14KnowledgeSystem : SharedCP14KnowledgeSystem
|
||||
public sealed class CP14KnowledgeSystem : SharedCP14KnowledgeSystem
|
||||
{
|
||||
[Dependency] private readonly ISharedAdminManager _admin = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageable = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly IChatManager _chat = default!;
|
||||
[Dependency] private readonly MindSystem _mind = default!;
|
||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||
@@ -35,32 +28,21 @@ public sealed partial class CP14KnowledgeSystem : SharedCP14KnowledgeSystem
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<CP14AutoAddKnowledgeComponent, MapInitEvent>(AutoAddSkill);
|
||||
SubscribeLocalEvent<CP14KnowledgeStorageComponent, GetVerbsEvent<Verb>>(AddKnowledgeAdminVerb);
|
||||
SubscribeLocalEvent<CP14KnowledgeLearningSourceComponent, GetVerbsEvent<Verb>>(AddKnowledgeLearningVerb);
|
||||
SubscribeLocalEvent<CP14KnowledgeStorageComponent, CP14KnowledgeLearnDoAfterEvent>(KnowledgeLearnedEvent);
|
||||
SubscribeLocalEvent<CP14KnowledgeLearningSourceComponent, GetVerbsEvent<Verb>>(AddKnowledgeLearningVerb);
|
||||
|
||||
SubscribeNetworkEvent<RequestKnowledgeInfoEvent>(OnRequestKnowledgeInfoEvent);
|
||||
}
|
||||
|
||||
private void KnowledgeLearnedEvent(Entity<CP14KnowledgeStorageComponent> ent, ref CP14KnowledgeLearnDoAfterEvent args)
|
||||
{
|
||||
if (args.Cancelled || args.Handled)
|
||||
return;
|
||||
|
||||
args.Handled = true;
|
||||
|
||||
TryLearnKnowledge(ent, args.Knowledge);
|
||||
SubscribeNetworkEvent<CP14RequestKnowledgeInfoEvent>(OnRequestKnowledgeInfoEvent);
|
||||
}
|
||||
|
||||
private void AddKnowledgeLearningVerb(Entity<CP14KnowledgeLearningSourceComponent> ent, ref GetVerbsEvent<Verb> args)
|
||||
{
|
||||
var user = args.User;
|
||||
foreach (var knowledge in ent.Comp.Knowledges)
|
||||
foreach (var knowledge in ent.Comp.Knowledge)
|
||||
{
|
||||
if (!_proto.TryIndex(knowledge, out var indexedKnowledge))
|
||||
if (!_prototype.TryIndex(knowledge, out var indexedKnowledge))
|
||||
continue;
|
||||
|
||||
args.Verbs.Add(new Verb()
|
||||
args.Verbs.Add(new Verb
|
||||
{
|
||||
Text = $"{Loc.GetString(indexedKnowledge.Name)}",
|
||||
Message = Loc.GetString(indexedKnowledge.Desc),
|
||||
@@ -70,7 +52,7 @@ public sealed partial class CP14KnowledgeSystem : SharedCP14KnowledgeSystem
|
||||
_doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager,
|
||||
user,
|
||||
ent.Comp.DoAfter,
|
||||
new CP14KnowledgeLearnDoAfterEvent() {Knowledge = knowledge},
|
||||
new CP14KnowledgeLearnDoAfterEvent { Knowledge = knowledge },
|
||||
user,
|
||||
ent,
|
||||
ent)
|
||||
@@ -85,176 +67,137 @@ public sealed partial class CP14KnowledgeSystem : SharedCP14KnowledgeSystem
|
||||
}
|
||||
}
|
||||
|
||||
private void AddKnowledgeAdminVerb(Entity<CP14KnowledgeStorageComponent> ent, ref GetVerbsEvent<Verb> args)
|
||||
private void KnowledgeLearnedEvent(Entity<CP14KnowledgeStorageComponent> ent, ref CP14KnowledgeLearnDoAfterEvent args)
|
||||
{
|
||||
if (!_admin.HasAdminFlag(args.User, AdminFlags.Admin))
|
||||
if (args.Cancelled || args.Handled)
|
||||
return;
|
||||
|
||||
//Remove knowledge
|
||||
foreach (var knowledge in ent.Comp.Knowledges)
|
||||
{
|
||||
if (!_proto.TryIndex(knowledge, out var indexedKnowledge))
|
||||
continue;
|
||||
|
||||
args.Verbs.Add(new Verb()
|
||||
{
|
||||
Text = $"{Loc.GetString(indexedKnowledge.Name)}",
|
||||
Message = Loc.GetString(indexedKnowledge.Desc),
|
||||
Category = VerbCategory.CP14KnowledgeRemove,
|
||||
Act = () =>
|
||||
{
|
||||
TryForgotKnowledge(ent, knowledge);
|
||||
},
|
||||
Impact = LogImpact.High,
|
||||
});
|
||||
}
|
||||
|
||||
//Add knowledge
|
||||
foreach (var knowledge in _proto.EnumeratePrototypes<CP14KnowledgePrototype>())
|
||||
{
|
||||
if (ent.Comp.Knowledges.Contains(knowledge))
|
||||
continue;
|
||||
|
||||
args.Verbs.Add(new Verb()
|
||||
{
|
||||
Text = $"{Loc.GetString(knowledge.Name)}",
|
||||
Message = Loc.GetString(knowledge.Desc),
|
||||
Category = VerbCategory.CP14KnowledgeAdd,
|
||||
Act = () =>
|
||||
{
|
||||
TryLearnKnowledge(ent, knowledge, true);
|
||||
},
|
||||
Impact = LogImpact.High,
|
||||
});
|
||||
}
|
||||
args.Handled = true;
|
||||
TryAdd(ent.Owner, args.Knowledge);
|
||||
}
|
||||
|
||||
private void AutoAddSkill(Entity<CP14AutoAddKnowledgeComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
foreach (var knowledge in ent.Comp.Knowledge)
|
||||
{
|
||||
TryLearnKnowledge(ent, knowledge);
|
||||
TryAdd(ent.Owner, knowledge);
|
||||
}
|
||||
|
||||
RemComp(ent, ent.Comp);
|
||||
}
|
||||
|
||||
public bool TryLearnKnowledge(EntityUid uid, ProtoId<CP14KnowledgePrototype> proto, bool force = false, bool silent = false)
|
||||
public bool TryAdd(Entity<CP14KnowledgeStorageComponent?> entity, ProtoId<CP14KnowledgePrototype> knowledgeId, bool force = false, bool silent = false)
|
||||
{
|
||||
if (!TryComp<CP14KnowledgeStorageComponent>(uid, out var knowledgeStorage))
|
||||
if (!Resolve(entity, ref entity.Comp, false))
|
||||
return false;
|
||||
|
||||
if (!_proto.TryIndex(proto, out var indexedKnowledge))
|
||||
if (HasKnowledge(entity, knowledgeId))
|
||||
return false;
|
||||
|
||||
if (knowledgeStorage.Knowledges.Contains(proto))
|
||||
if (!_prototype.TryIndex(knowledgeId, out var knowledge))
|
||||
return false;
|
||||
|
||||
foreach (var dependency in indexedKnowledge.Dependencies)
|
||||
MindComponent? mindComponent;
|
||||
|
||||
foreach (var dependencyKnowledgeId in knowledge.Dependencies)
|
||||
{
|
||||
if (!_proto.TryIndex(dependency, out var indexedDependency))
|
||||
if (!_prototype.TryIndex(dependencyKnowledgeId, out var dependencyKnowledge))
|
||||
return false;
|
||||
|
||||
if (force)
|
||||
{
|
||||
//If we teach by force - we automatically teach all the basics that are necessary for that skill.
|
||||
if (!TryLearnKnowledge(uid, dependency, true))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
var passed = true;
|
||||
var sb = new StringBuilder();
|
||||
// If we teach by force - we automatically teach all the basics that are necessary for that skill.
|
||||
if (force && !TryAdd(entity, dependencyKnowledge, true))
|
||||
return false;
|
||||
|
||||
sb.Append(Loc.GetString("cp14-cant-learn-knowledge-dependencies",
|
||||
("target", Loc.GetString(indexedKnowledge.Desc))));
|
||||
var sb = new StringBuilder();
|
||||
sb.Append(Loc.GetString("cp14-cant-learn-knowledge-dependencies", ("target", Loc.GetString(knowledge.Desc))));
|
||||
|
||||
//We cant learnt
|
||||
if (!HasKnowledge(uid, dependency))
|
||||
{
|
||||
passed = false;
|
||||
sb.Append("\n- " + Loc.GetString(indexedDependency.Desc));
|
||||
}
|
||||
// We cant learnt
|
||||
if (HasKnowledge(entity, dependencyKnowledge))
|
||||
continue;
|
||||
|
||||
if (!passed)
|
||||
{
|
||||
if (!silent && _mind.TryGetMind(uid, out var mind, out var mindComp) && mindComp.Session is not null)
|
||||
{
|
||||
var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", sb.ToString()));
|
||||
_chat.ChatMessageToOne(
|
||||
ChatChannel.Server,
|
||||
sb.ToString(),
|
||||
wrappedMessage,
|
||||
default,
|
||||
false,
|
||||
mindComp.Session.Channel);
|
||||
}
|
||||
sb.Append($"\n- {Loc.GetString(dependencyKnowledge.Desc)}");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (silent)
|
||||
return false;
|
||||
|
||||
//TODO: coding on a sleepy head is a bad idea. Remove duplicate variables. >:(
|
||||
if (!silent && _mind.TryGetMind(uid, out var mind2, out var mindComp2) && mindComp2.Session is not null)
|
||||
{
|
||||
var message = Loc.GetString("cp14-learned-new-knowledge", ("name", Loc.GetString(indexedKnowledge.Name)));
|
||||
var wrappedMessage2 = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
|
||||
if (!_mind.TryGetMind(entity, out _, out mindComponent) || mindComponent.Session is null)
|
||||
return false;
|
||||
|
||||
var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", sb.ToString()));
|
||||
_chat.ChatMessageToOne(
|
||||
ChatChannel.Server,
|
||||
message,
|
||||
wrappedMessage2,
|
||||
sb.ToString(),
|
||||
wrappedMessage,
|
||||
default,
|
||||
false,
|
||||
mindComp2.Session.Channel);
|
||||
mindComponent.Session.Channel);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
_adminLogger.Add(
|
||||
LogType.Mind,
|
||||
LogImpact.Medium,
|
||||
$"{EntityManager.ToPrettyString(uid):player} learned new knowledge: {Loc.GetString(indexedKnowledge.Name)}");
|
||||
return knowledgeStorage.Knowledges.Add(proto);
|
||||
}
|
||||
|
||||
public bool TryForgotKnowledge(EntityUid uid, ProtoId<CP14KnowledgePrototype> proto, bool silent = false)
|
||||
{
|
||||
if (!TryComp<CP14KnowledgeStorageComponent>(uid, out var knowledgeStorage))
|
||||
if (!entity.Comp.Knowledge.Add(knowledgeId))
|
||||
return false;
|
||||
|
||||
if (!knowledgeStorage.Knowledges.Contains(proto))
|
||||
_adminLogger.Add(LogType.Mind, LogImpact.Medium, $"{EntityManager.ToPrettyString(entity):player} learned new knowledge: {Loc.GetString(knowledge.Name)}");
|
||||
|
||||
// TODO: coding on a sleepy head is a bad idea. Remove duplicate variables. >:(
|
||||
if (silent)
|
||||
return true;
|
||||
|
||||
if (!_mind.TryGetMind(entity, out _, out mindComponent) || mindComponent.Session is null)
|
||||
return false;
|
||||
|
||||
if (!_proto.TryIndex(proto, out var indexedKnowledge))
|
||||
return false;
|
||||
var message = Loc.GetString("cp14-learned-new-knowledge", ("name", Loc.GetString(knowledge.Name)));
|
||||
var wrappedMessage2 = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
|
||||
|
||||
knowledgeStorage.Knowledges.Remove(proto);
|
||||
_chat.ChatMessageToOne(
|
||||
ChatChannel.Server,
|
||||
message,
|
||||
wrappedMessage2,
|
||||
default,
|
||||
false,
|
||||
mindComponent.Session.Channel);
|
||||
|
||||
if (_mind.TryGetMind(uid, out var mind, out var mindComp) && mindComp.Session is not null)
|
||||
{
|
||||
if (!silent)
|
||||
{
|
||||
var message = Loc.GetString("cp14-forgot-knowledge", ("name", Loc.GetString(indexedKnowledge.Name)));
|
||||
var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
|
||||
|
||||
_chat.ChatMessageToOne(
|
||||
ChatChannel.Server,
|
||||
message,
|
||||
wrappedMessage,
|
||||
default,
|
||||
false,
|
||||
mindComp.Session.Channel);
|
||||
}
|
||||
}
|
||||
|
||||
_adminLogger.Add(
|
||||
LogType.Mind,
|
||||
LogImpact.Medium,
|
||||
$"{EntityManager.ToPrettyString(uid):player} forgot knowledge: {Loc.GetString(indexedKnowledge.Name)}");
|
||||
return true;
|
||||
}
|
||||
|
||||
private void OnRequestKnowledgeInfoEvent(RequestKnowledgeInfoEvent msg, EntitySessionEventArgs args)
|
||||
public bool TryRemove(Entity<CP14KnowledgeStorageComponent?> entity, ProtoId<CP14KnowledgePrototype> proto, bool silent = false)
|
||||
{
|
||||
if (!Resolve(entity, ref entity.Comp, false))
|
||||
return false;
|
||||
|
||||
if (!entity.Comp.Knowledge.Contains(proto))
|
||||
return false;
|
||||
|
||||
if (!_prototype.TryIndex(proto, out var indexedKnowledge))
|
||||
return false;
|
||||
|
||||
if (!entity.Comp.Knowledge.Remove(proto))
|
||||
return false;
|
||||
|
||||
_adminLogger.Add(LogType.Mind, LogImpact.Medium, $"{EntityManager.ToPrettyString(entity):player} forgot knowledge: {Loc.GetString(indexedKnowledge.Name)}");
|
||||
|
||||
if (silent)
|
||||
return true;
|
||||
|
||||
if (!_mind.TryGetMind(entity, out _, out var mindComp) || mindComp.Session is null)
|
||||
return true;
|
||||
|
||||
var message = Loc.GetString("cp14-forgot-knowledge", ("name", Loc.GetString(indexedKnowledge.Name)));
|
||||
var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
|
||||
|
||||
_chat.ChatMessageToOne(
|
||||
ChatChannel.Server,
|
||||
message,
|
||||
wrappedMessage,
|
||||
default,
|
||||
false,
|
||||
mindComp.Session.Channel);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void OnRequestKnowledgeInfoEvent(CP14RequestKnowledgeInfoEvent msg, EntitySessionEventArgs args)
|
||||
{
|
||||
if (!args.SenderSession.AttachedEntity.HasValue || args.SenderSession.AttachedEntity != GetEntity(msg.NetEntity))
|
||||
return;
|
||||
@@ -264,6 +207,6 @@ public sealed partial class CP14KnowledgeSystem : SharedCP14KnowledgeSystem
|
||||
if (!TryComp<CP14KnowledgeStorageComponent>(entity, out var knowledgeComp))
|
||||
return;
|
||||
|
||||
RaiseNetworkEvent(new CP14KnowledgeInfoEvent(GetNetEntity(entity),knowledgeComp.Knowledges), args.SenderSession);
|
||||
RaiseNetworkEvent(new CP14KnowledgeInfoEvent(GetNetEntity(entity),knowledgeComp.Knowledge), args.SenderSession);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
using Content.Shared._CP14.Knowledge;
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Content.Shared.Roles;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._CP14.Knowledge;
|
||||
namespace Content.Server._CP14.Knowledge.Specials;
|
||||
|
||||
/// <summary>
|
||||
/// a component that can be hung on an entity to immediately teach it some skills
|
||||
@@ -13,15 +12,16 @@ namespace Content.Server._CP14.Knowledge;
|
||||
public sealed partial class CP14AddKnowledgeSpecial : JobSpecial
|
||||
{
|
||||
[DataField(required: true), ViewVariables(VVAccess.ReadOnly)]
|
||||
public List<ProtoId<CP14KnowledgePrototype>> Knowledge = new();
|
||||
public List<ProtoId<CP14KnowledgePrototype>> Knowledge = [];
|
||||
|
||||
public override void AfterEquip(EntityUid mob)
|
||||
{
|
||||
var entMan = IoCManager.Resolve<IEntityManager>();
|
||||
var knowledgeSystem = entMan.System<CP14KnowledgeSystem>();
|
||||
|
||||
foreach (var knowledge in Knowledge)
|
||||
{
|
||||
knowledgeSystem.TryLearnKnowledge(mob, knowledge, true, true);
|
||||
knowledgeSystem.TryAdd(mob, knowledge, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._CP14.MagicSpell;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class CP14AutoLearnActionComponent : Component
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public HashSet<EntProtoId> Actions = new();
|
||||
}
|
||||
@@ -7,6 +7,7 @@ using Content.Shared._CP14.MagicSpell;
|
||||
using Content.Shared._CP14.MagicSpell.Components;
|
||||
using Content.Shared._CP14.MagicSpell.Events;
|
||||
using Content.Shared._CP14.MagicSpell.Spells;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Projectiles;
|
||||
using Content.Shared.Throwing;
|
||||
@@ -25,6 +26,7 @@ public sealed partial class CP14MagicSystem : CP14SharedMagicSystem
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly SharedActionsSystem _action = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -43,6 +45,17 @@ public sealed partial class CP14MagicSystem : CP14SharedMagicSystem
|
||||
SubscribeLocalEvent<CP14MagicEffectManaCostComponent, CP14MagicEffectConsumeResourceEvent>(OnManaConsume);
|
||||
|
||||
SubscribeLocalEvent<CP14MagicEffectRequiredMusicToolComponent, CP14CastMagicEffectAttemptEvent>(OnMusicCheck);
|
||||
|
||||
SubscribeLocalEvent<CP14AutoLearnActionComponent, MapInitEvent>(OnAutoLearnAction);
|
||||
}
|
||||
|
||||
private void OnAutoLearnAction(Entity<CP14AutoLearnActionComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
foreach (var action in ent.Comp.Actions)
|
||||
{
|
||||
_action.AddAction(ent, action);
|
||||
}
|
||||
RemCompDeferred<CP14AutoLearnActionComponent>(ent);
|
||||
}
|
||||
|
||||
private void OnProjectileHit(Entity<CP14SpellEffectOnHitComponent> ent, ref ThrowDoHitEvent args)
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
using Content.Server._CP14.Objectives.Systems;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server._CP14.Objectives.Components;
|
||||
|
||||
[RegisterComponent, Access(typeof(CP14CurrencyCollectConditionSystem))]
|
||||
public sealed partial class CP14CurrencyStoredConditionComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public int Currency = 1000;
|
||||
|
||||
[DataField(required: true)]
|
||||
public LocId ObjectiveText;
|
||||
|
||||
[DataField(required: true)]
|
||||
public LocId ObjectiveDescription;
|
||||
|
||||
[DataField(required: true)]
|
||||
public SpriteSpecifier ObjectiveSprite;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using Content.Server._CP14.Objectives.Systems;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server._CP14.Objectives.Components;
|
||||
|
||||
/// <summary>
|
||||
/// The player must be the richest among the players among the specified list of roles
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(CP14RichestJobConditionSystem))]
|
||||
public sealed partial class CP14RichestJobConditionComponent : Component
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public ProtoId<JobPrototype> Job;
|
||||
|
||||
[DataField(required: true)]
|
||||
public LocId ObjectiveText;
|
||||
|
||||
[DataField(required: true)]
|
||||
public LocId ObjectiveDescription;
|
||||
|
||||
[DataField(required: true)]
|
||||
public SpriteSpecifier ObjectiveSprite;
|
||||
}
|
||||
@@ -16,24 +16,13 @@ public sealed class CP14CurrencyCollectConditionSystem : EntitySystem
|
||||
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
||||
[Dependency] private readonly SharedObjectivesSystem _objectives = default!;
|
||||
[Dependency] private readonly CP14SharedCurrencySystem _currency = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly SharedInteractionSystem _interaction = default!;
|
||||
|
||||
private EntityQuery<ContainerManagerComponent> _containerQuery;
|
||||
|
||||
private HashSet<Entity<TransformComponent>> _nearestEnts = new();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_containerQuery = GetEntityQuery<ContainerManagerComponent>();
|
||||
|
||||
SubscribeLocalEvent<CP14CurrencyCollectConditionComponent, ObjectiveAfterAssignEvent>(OnCollectAfterAssign);
|
||||
SubscribeLocalEvent<CP14CurrencyStoredConditionComponent, ObjectiveAfterAssignEvent>(OnStoredAfterAssign);
|
||||
|
||||
SubscribeLocalEvent<CP14CurrencyCollectConditionComponent, ObjectiveGetProgressEvent>(OnCollectGetProgress);
|
||||
SubscribeLocalEvent<CP14CurrencyStoredConditionComponent, ObjectiveGetProgressEvent>(OnStoredGetProgress);
|
||||
}
|
||||
|
||||
private void OnCollectAfterAssign(Entity<CP14CurrencyCollectConditionComponent> condition, ref ObjectiveAfterAssignEvent args)
|
||||
@@ -43,103 +32,23 @@ public sealed class CP14CurrencyCollectConditionSystem : EntitySystem
|
||||
_objectives.SetIcon(condition.Owner, condition.Comp.ObjectiveSprite);
|
||||
}
|
||||
|
||||
private void OnStoredAfterAssign(Entity<CP14CurrencyStoredConditionComponent> condition, ref ObjectiveAfterAssignEvent args)
|
||||
{
|
||||
_metaData.SetEntityName(condition.Owner, Loc.GetString(condition.Comp.ObjectiveText, ("coins", _currency.GetCurrencyPrettyString(condition.Comp.Currency))), args.Meta);
|
||||
_metaData.SetEntityDescription(condition.Owner, Loc.GetString(condition.Comp.ObjectiveDescription, ("coins", _currency.GetCurrencyPrettyString(condition.Comp.Currency))), args.Meta);
|
||||
_objectives.SetIcon(condition.Owner, condition.Comp.ObjectiveSprite);
|
||||
}
|
||||
|
||||
private void OnCollectGetProgress(Entity<CP14CurrencyCollectConditionComponent> condition, ref ObjectiveGetProgressEvent args)
|
||||
{
|
||||
args.Progress = GetProgress(args.Mind, condition);
|
||||
}
|
||||
|
||||
private void OnStoredGetProgress(Entity<CP14CurrencyStoredConditionComponent> condition, ref ObjectiveGetProgressEvent args)
|
||||
{
|
||||
args.Progress = GetStoredProgress(args.Mind, condition);
|
||||
}
|
||||
|
||||
private float GetProgress(MindComponent mind, CP14CurrencyCollectConditionComponent condition)
|
||||
{
|
||||
if (!_containerQuery.TryGetComponent(mind.OwnedEntity, out var currentManager))
|
||||
var count = 0;
|
||||
|
||||
if (mind.OwnedEntity is null)
|
||||
return 0;
|
||||
|
||||
var containerStack = new Stack<ContainerManagerComponent>();
|
||||
var count = 0;
|
||||
|
||||
//check pulling object
|
||||
if (TryComp<PullerComponent>(mind.OwnedEntity,
|
||||
out var pull)) //TO DO: to make the code prettier? don't like the repetition
|
||||
{
|
||||
var pulledEntity = pull.Pulling;
|
||||
if (pulledEntity != null)
|
||||
{
|
||||
CheckEntity(pulledEntity.Value, ref containerStack, ref count);
|
||||
}
|
||||
}
|
||||
|
||||
// recursively check each container for the item
|
||||
// checks inventory, bag, implants, etc.
|
||||
do
|
||||
{
|
||||
foreach (var container in currentManager.Containers.Values)
|
||||
{
|
||||
foreach (var entity in container.ContainedEntities)
|
||||
{
|
||||
// check if this is the item
|
||||
count += _currency.GetTotalCurrency(entity);
|
||||
|
||||
// if it is a container check its contents
|
||||
if (_containerQuery.TryGetComponent(entity, out var containerManager))
|
||||
containerStack.Push(containerManager);
|
||||
}
|
||||
}
|
||||
} while (containerStack.TryPop(out currentManager));
|
||||
count += _currency.GetTotalCurrency(mind.OwnedEntity.Value);
|
||||
|
||||
var result = count / (float)condition.Currency;
|
||||
result = Math.Clamp(result, 0, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
private float GetStoredProgress(MindComponent mind, CP14CurrencyStoredConditionComponent condition)
|
||||
{
|
||||
var containerStack = new Stack<ContainerManagerComponent>();
|
||||
var count = 0;
|
||||
|
||||
var areasQuery = AllEntityQuery<StealAreaComponent, TransformComponent>();
|
||||
while (areasQuery.MoveNext(out var uid, out var area, out var xform))
|
||||
{
|
||||
if (!area.Owners.Contains(mind.Owner))
|
||||
continue;
|
||||
|
||||
_nearestEnts.Clear();
|
||||
_lookup.GetEntitiesInRange(xform.Coordinates, area.Range, _nearestEnts);
|
||||
foreach (var ent in _nearestEnts)
|
||||
{
|
||||
if (!_interaction.InRangeUnobstructed((uid, xform), (ent, ent.Comp), area.Range))
|
||||
continue;
|
||||
|
||||
CheckEntity(ent, ref containerStack, ref count);
|
||||
}
|
||||
}
|
||||
|
||||
var result = count / (float)condition.Currency;
|
||||
result = Math.Clamp(result, 0, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void CheckEntity(EntityUid entity, ref Stack<ContainerManagerComponent> containerStack, ref int counter)
|
||||
{
|
||||
// check if this is the item
|
||||
counter += _currency.GetTotalCurrency(entity);
|
||||
|
||||
//we don't check the inventories of sentient entity
|
||||
if (!TryComp<MindContainerComponent>(entity, out _))
|
||||
{
|
||||
// if it is a container check its contents
|
||||
if (_containerQuery.TryGetComponent(entity, out var containerManager))
|
||||
containerStack.Push(containerManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
using Content.Server._CP14.Objectives.Components;
|
||||
using Content.Shared._CP14.Currency;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.Objectives.Components;
|
||||
using Content.Shared.Objectives.Systems;
|
||||
using Content.Shared.Roles.Jobs;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._CP14.Objectives.Systems;
|
||||
|
||||
public sealed class CP14RichestJobConditionSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
||||
[Dependency] private readonly SharedObjectivesSystem _objectives = default!;
|
||||
[Dependency] private readonly CP14SharedCurrencySystem _currency = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
[Dependency] private readonly SharedMindSystem _mind = default!;
|
||||
[Dependency] private readonly SharedJobSystem _job = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<CP14RichestJobConditionComponent, ObjectiveAfterAssignEvent>(OnCollectAfterAssign);
|
||||
SubscribeLocalEvent<CP14RichestJobConditionComponent, ObjectiveGetProgressEvent>(OnCollectGetProgress);
|
||||
}
|
||||
|
||||
private void OnCollectAfterAssign(Entity<CP14RichestJobConditionComponent> condition, ref ObjectiveAfterAssignEvent args)
|
||||
{
|
||||
if (!_proto.TryIndex(condition.Comp.Job, out var indexedJob))
|
||||
return;
|
||||
|
||||
_metaData.SetEntityName(condition.Owner, Loc.GetString(condition.Comp.ObjectiveText), args.Meta);
|
||||
_metaData.SetEntityDescription(condition.Owner, Loc.GetString(condition.Comp.ObjectiveDescription), args.Meta);
|
||||
_objectives.SetIcon(condition.Owner, condition.Comp.ObjectiveSprite);
|
||||
}
|
||||
|
||||
private void OnCollectGetProgress(Entity<CP14RichestJobConditionComponent> condition, ref ObjectiveGetProgressEvent args)
|
||||
{
|
||||
args.Progress = GetProgress(args.MindId, args.Mind, condition);
|
||||
}
|
||||
|
||||
private float GetProgress(EntityUid mindId, MindComponent mind, CP14RichestJobConditionComponent condition)
|
||||
{
|
||||
if (mind.OwnedEntity is null)
|
||||
return 0;
|
||||
|
||||
var ourValue = _currency.GetTotalCurrency(mind.OwnedEntity.Value);
|
||||
var otherMaxValue = 0;
|
||||
|
||||
var allHumans = _mind.GetAliveHumans(mindId);
|
||||
if (allHumans.Count == 0)
|
||||
return 1; // No one to compare to, so we're the richest.
|
||||
|
||||
foreach (var otherHuman in allHumans)
|
||||
{
|
||||
if (!_job.MindTryGetJob(otherHuman, out var otherJob))
|
||||
continue;
|
||||
|
||||
if (otherJob != condition.Job)
|
||||
continue;
|
||||
|
||||
if (otherHuman.Comp.OwnedEntity is null)
|
||||
continue;
|
||||
|
||||
var otherValue = _currency.GetTotalCurrency(otherHuman.Comp.OwnedEntity.Value);
|
||||
if (otherValue > otherMaxValue)
|
||||
otherMaxValue = otherValue;
|
||||
}
|
||||
|
||||
// if several players have the same amount of money, no one wins.
|
||||
return ourValue == otherMaxValue ? 0.99f : Math.Clamp(ourValue / (float)otherMaxValue, 0, 1);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,11 @@
|
||||
using System.Text;
|
||||
using Content.Server._CP14.Cargo;
|
||||
using Content.Server._CP14.Currency;
|
||||
using Content.Server.Mind;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Server.Station.Events;
|
||||
using Content.Shared._CP14.Cargo;
|
||||
using Content.Shared._CP14.Currency;
|
||||
using Content.Shared.Paper;
|
||||
using Content.Shared.Station.Components;
|
||||
using Content.Shared.Storage.EntitySystems;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
@@ -41,15 +36,15 @@ public sealed partial class CP14SalarySystem : EntitySystem
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
var query = EntityQueryEnumerator<CP14StationSalaryComponent, CP14StationTravelingStoreShipTargetComponent>();
|
||||
while (query.MoveNext(out var uid, out var salary, out var store))
|
||||
{
|
||||
if (_timing.CurTime < salary.NextSalaryTime)
|
||||
continue;
|
||||
|
||||
salary.NextSalaryTime = _timing.CurTime + salary.SalaryFrequency;
|
||||
_cargo.AddBuyQueue((uid, store), new List<EntProtoId> {salary.SalaryProto});
|
||||
}
|
||||
//var query = EntityQueryEnumerator<CP14StationSalaryComponent, CP14StationTravelingStoreShipTargetComponent>();
|
||||
//while (query.MoveNext(out var uid, out var salary, out var store))
|
||||
//{
|
||||
// if (_timing.CurTime < salary.NextSalaryTime)
|
||||
// continue;
|
||||
//
|
||||
// salary.NextSalaryTime = _timing.CurTime + salary.SalaryFrequency;
|
||||
// _cargo.AddBuyQueue((uid, store), new List<EntProtoId> {salary.SalaryProto});
|
||||
//}
|
||||
}
|
||||
|
||||
private void OnSalaryInit(Entity<CP14SalarySpawnerComponent> ent, ref MapInitEvent args)
|
||||
|
||||
11
Content.Server/_CP14/Roles/CP14VampireRoleComponent.cs
Normal file
11
Content.Server/_CP14/Roles/CP14VampireRoleComponent.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Content.Shared.Roles;
|
||||
|
||||
namespace Content.Server._CP14.Roles;
|
||||
|
||||
/// <summary>
|
||||
/// Added to mind role entities to tag that they are a Vampire.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class CP14VampireRoleComponent : BaseMindRoleComponent
|
||||
{
|
||||
}
|
||||
29
Content.Server/_CP14/Vampire/CP14VampireComponent.cs
Normal file
29
Content.Server/_CP14/Vampire/CP14VampireComponent.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using Content.Server._CP14.GameTicking.Rules;
|
||||
using Content.Shared.Body.Prototypes;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._CP14.Vampire;
|
||||
|
||||
[RegisterComponent]
|
||||
[Access(typeof(CP14VampireRuleSystem))]
|
||||
public sealed partial class CP14VampireComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public ProtoId<ReagentPrototype> NewBloodReagent = "CP14BloodVampire";
|
||||
|
||||
[DataField]
|
||||
public ProtoId<MetabolizerTypePrototype> MetabolizerType = "CP14Vampire";
|
||||
|
||||
[DataField]
|
||||
public float HeatUnderSunTemperature = 12000f;
|
||||
|
||||
[DataField]
|
||||
public TimeSpan HeatFrequency = TimeSpan.FromSeconds(1);
|
||||
|
||||
[DataField]
|
||||
public TimeSpan NextHeatTime = TimeSpan.Zero;
|
||||
|
||||
[DataField]
|
||||
public float IgniteThreshold = 350f;
|
||||
}
|
||||
7
Content.Server/_CP14/Vampire/CP14VampireVisualsSystem.cs
Normal file
7
Content.Server/_CP14/Vampire/CP14VampireVisualsSystem.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
using Content.Shared._CP14.Vampire;
|
||||
|
||||
namespace Content.Server._CP14.Vampire;
|
||||
|
||||
public sealed class CP14VampireVisualsSystem : CP14SharedVampireVisualsSystem
|
||||
{
|
||||
}
|
||||
@@ -134,6 +134,11 @@ public sealed class HungerSystem : EntitySystem
|
||||
if (calculatedHungerThreshold == component.CurrentThreshold)
|
||||
return;
|
||||
|
||||
//CP14 Raise hunger event for vampire
|
||||
var ev = new CP14HungerChangedEvent(component.CurrentThreshold, calculatedHungerThreshold);
|
||||
RaiseLocalEvent(uid, ev);
|
||||
//CP14 Raise hunger event for vampire end
|
||||
|
||||
component.CurrentThreshold = calculatedHungerThreshold;
|
||||
DoHungerThresholdEffects(uid, component);
|
||||
}
|
||||
@@ -277,3 +282,10 @@ public sealed class HungerSystem : EntitySystem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public sealed class CP14HungerChangedEvent(HungerThreshold oldThreshold, HungerThreshold newThreshold) : EntityEventArgs
|
||||
{
|
||||
public HungerThreshold OldThreshold { get; } = oldThreshold;
|
||||
public HungerThreshold NewThreshold { get; } = newThreshold;
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Content.Shared._CP14.Cargo;
|
||||
|
||||
/// <summary>
|
||||
/// marks an entity into which trade with the city will put money when selling, or take it when buying.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class CP14CargoMoneyBoxComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace Content.Shared._CP14.Cargo;
|
||||
|
||||
/// <summary>
|
||||
/// Allows users to view information on city trading opportunities
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class CP14CargoStoreComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public EntityUid? Station = null;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace Content.Shared._CP14.Cargo;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class CP14SellingPalettComponent : Component
|
||||
{
|
||||
}
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class CP14BuyingPalettComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -14,18 +14,15 @@ public enum CP14StoreUiKey
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class CP14StoreUiState : BoundUserInterfaceState
|
||||
{
|
||||
public readonly string ShopName;
|
||||
public readonly HashSet<CP14StoreUiProductEntry> ProductsBuy;
|
||||
public readonly HashSet<CP14StoreUiProductEntry> ProductsSell;
|
||||
|
||||
public bool OnStation;
|
||||
public readonly TimeSpan NextTravelTime;
|
||||
|
||||
public CP14StoreUiState(HashSet<CP14StoreUiProductEntry> productsBuy, HashSet<CP14StoreUiProductEntry> productsSell, bool onStation, TimeSpan time)
|
||||
public CP14StoreUiState(string name, HashSet<CP14StoreUiProductEntry> productsBuy, HashSet<CP14StoreUiProductEntry> productsSell)
|
||||
{
|
||||
ShopName = name;
|
||||
ProductsBuy = productsBuy;
|
||||
ProductsSell = productsSell;
|
||||
OnStation = onStation;
|
||||
NextTravelTime = time;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,16 +30,18 @@ public sealed class CP14StoreUiState : BoundUserInterfaceState
|
||||
public readonly struct CP14StoreUiProductEntry : IEquatable<CP14StoreUiProductEntry>
|
||||
{
|
||||
public readonly string ProtoId;
|
||||
public readonly SpriteSpecifier Icon;
|
||||
public readonly SpriteSpecifier? Icon;
|
||||
public readonly EntProtoId? EntityView;
|
||||
public readonly string Name;
|
||||
public readonly string Desc;
|
||||
public readonly int Price;
|
||||
public readonly bool Special;
|
||||
|
||||
public CP14StoreUiProductEntry(string protoId, SpriteSpecifier icon, string name, string desc, int price, bool special)
|
||||
public CP14StoreUiProductEntry(string protoId, SpriteSpecifier? icon, EntProtoId? entityView, string name, string desc, int price, bool special)
|
||||
{
|
||||
ProtoId = protoId;
|
||||
Icon = icon;
|
||||
EntityView = entityView;
|
||||
Name = name;
|
||||
Desc = desc;
|
||||
Price = price;
|
||||
|
||||
17
Content.Shared/_CP14/Cargo/CP14TradingInfoBoardComponent.cs
Normal file
17
Content.Shared/_CP14/Cargo/CP14TradingInfoBoardComponent.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using Content.Shared._CP14.Cargo.Prototype;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Cargo;
|
||||
|
||||
/// <summary>
|
||||
/// Allows users to view information on faction trading opportunities
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class CP14TradingInfoBoardComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public EntityUid? TradingPortal = null;
|
||||
|
||||
[DataField]
|
||||
public ProtoId<CP14StoreFactionPrototype>? CahcedFaction;
|
||||
}
|
||||
@@ -1,36 +1,29 @@
|
||||
using Content.Shared._CP14.Cargo.Prototype;
|
||||
using Content.Shared.Destructible.Thresholds;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared._CP14.Cargo;
|
||||
|
||||
/// <summary>
|
||||
/// Add to the station so that traveling store ship starts running on it
|
||||
/// Add to the station so ...
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class CP14StationTravelingStoreShipTargetComponent : Component
|
||||
[NetworkedComponent, RegisterComponent, AutoGenerateComponentPause, AutoGenerateComponentState]
|
||||
public sealed partial class CP14TradingPortalComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public EntityUid? Shuttle;
|
||||
[DataField(required: true), AutoNetworkedField]
|
||||
public ProtoId<CP14StoreFactionPrototype> Faction = default;
|
||||
|
||||
[DataField]
|
||||
public EntityUid? TradePostMap;
|
||||
public EntityCoordinates? TradingPosition = null;
|
||||
|
||||
[DataField]
|
||||
public bool OnStation;
|
||||
[DataField, AutoNetworkedField]
|
||||
public TimeSpan Delay = TimeSpan.FromSeconds(3f);
|
||||
|
||||
[DataField]
|
||||
public ResPath ShuttlePath = new("/Maps/_CP14/Ships/cargo_shuttle.yml");
|
||||
|
||||
[DataField]
|
||||
public TimeSpan NextTravelTime = TimeSpan.Zero;
|
||||
|
||||
[DataField]
|
||||
public TimeSpan StationWaitTime = TimeSpan.FromMinutes(6);
|
||||
|
||||
[DataField]
|
||||
public TimeSpan TradePostWaitTime = TimeSpan.FromMinutes(4);
|
||||
[DataField, AutoNetworkedField]
|
||||
[AutoPausedField]
|
||||
public TimeSpan ProcessFinishTime = TimeSpan.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// Available to random selecting and pusharing
|
||||
@@ -54,7 +47,7 @@ public sealed partial class CP14StationTravelingStoreShipTargetComponent : Compo
|
||||
public Dictionary<CP14StoreBuyPositionPrototype, int> CurrentSpecialBuyPositions = new(); //Proto, price
|
||||
|
||||
[DataField]
|
||||
public MinMax SpecialBuyPositionCount = new(1, 2);
|
||||
public int SpecialBuyPositionCount = 2;
|
||||
|
||||
[DataField]
|
||||
public Dictionary<CP14StoreSellPositionPrototype, int> CurrentSellPositions = new(); //Proto, price
|
||||
@@ -63,14 +56,8 @@ public sealed partial class CP14StationTravelingStoreShipTargetComponent : Compo
|
||||
public Dictionary<CP14StoreSellPositionPrototype, int> CurrentSpecialSellPositions = new(); //Proto, price
|
||||
|
||||
[DataField]
|
||||
public MinMax SpecialSellPositionCount = new(1, 2);
|
||||
public int SpecialSellPositionCount = 2;
|
||||
|
||||
[DataField]
|
||||
public int Balance = 0;
|
||||
|
||||
/// <summary>
|
||||
/// a queue of purchased items. The oldest purchases are taken out one by one to be unloaded onto the ship
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public Queue<EntProtoId> BuyedQueue = new();
|
||||
}
|
||||
@@ -1,21 +1,50 @@
|
||||
using System.Text;
|
||||
using Content.Shared.Stacks;
|
||||
using Content.Shared.Storage.EntitySystems;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared._CP14.Cargo.Prototype.BuyServices;
|
||||
|
||||
public sealed partial class CP14BuyItemsService : CP14StoreBuyService
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public Dictionary<EntProtoId, int> Product = new();
|
||||
public EntProtoId Product;
|
||||
|
||||
public override void Buy(EntityManager entManager, IPrototypeManager prototype, Entity<CP14StationTravelingStoreShipTargetComponent> station)
|
||||
[DataField]
|
||||
public int Count = 1;
|
||||
|
||||
public override void Buy(EntityManager entManager,
|
||||
IPrototypeManager prototype,
|
||||
Entity<CP14TradingPortalComponent> portal)
|
||||
{
|
||||
foreach (var (protoId, count) in Product)
|
||||
var storageSystem = entManager.System<SharedEntityStorageSystem>();
|
||||
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
station.Comp.BuyedQueue.Enqueue(protoId);
|
||||
}
|
||||
var spawned = entManager.Spawn(Product);
|
||||
storageSystem.Insert(spawned, portal);
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetName(IPrototypeManager protoMan)
|
||||
{
|
||||
if (!protoMan.TryIndex(Product, out var indexedProduct))
|
||||
return ":3";
|
||||
|
||||
var count = Count;
|
||||
if (indexedProduct.TryGetComponent<StackComponent>(out var stack))
|
||||
count *= stack.Count;
|
||||
|
||||
return Count > 0 ? $"{indexedProduct.Name} x{count}" : indexedProduct.Name;
|
||||
}
|
||||
|
||||
public override EntProtoId? GetEntityView(IPrototypeManager protoManager)
|
||||
{
|
||||
return Product;
|
||||
}
|
||||
|
||||
public override SpriteSpecifier? GetTexture(IPrototypeManager protoManager)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System.Text;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared._CP14.Cargo.Prototype.BuyServices;
|
||||
|
||||
@@ -14,17 +14,23 @@ public sealed partial class CP14UnlockPositionsService : CP14StoreBuyService
|
||||
[DataField]
|
||||
public HashSet<ProtoId<CP14StoreBuyPositionPrototype>> RemoveBuyPositions = new();
|
||||
|
||||
public override void Buy(EntityManager entManager, IPrototypeManager prototype, Entity<CP14StationTravelingStoreShipTargetComponent> station)
|
||||
[DataField]
|
||||
public HashSet<ProtoId<CP14StoreSellPositionPrototype>> RemoveSellPositions = new();
|
||||
|
||||
[DataField]
|
||||
public SpriteSpecifier? Icon = null;
|
||||
|
||||
[DataField]
|
||||
public LocId Name = string.Empty;
|
||||
|
||||
public override void Buy(EntityManager entManager, IPrototypeManager prototype, Entity<CP14TradingPortalComponent> portal)
|
||||
{
|
||||
foreach (var buy in AddBuyPositions)
|
||||
{
|
||||
if (!prototype.TryIndex(buy, out var indexedBuy))
|
||||
continue;
|
||||
|
||||
if (station.Comp.AvailableBuyPosition.Contains(indexedBuy))
|
||||
continue;
|
||||
|
||||
station.Comp.AvailableBuyPosition.Add(indexedBuy);
|
||||
portal.Comp.AvailableBuyPosition.Add(indexedBuy);
|
||||
}
|
||||
|
||||
foreach (var sell in AddSellPositions)
|
||||
@@ -32,10 +38,7 @@ public sealed partial class CP14UnlockPositionsService : CP14StoreBuyService
|
||||
if (!prototype.TryIndex(sell, out var indexedSell))
|
||||
continue;
|
||||
|
||||
if (station.Comp.AvailableSellPosition.Contains(indexedSell))
|
||||
continue;
|
||||
|
||||
station.Comp.AvailableSellPosition.Add(indexedSell);
|
||||
portal.Comp.AvailableSellPosition.Add(indexedSell);
|
||||
}
|
||||
|
||||
foreach (var rBuy in RemoveBuyPositions)
|
||||
@@ -43,10 +46,36 @@ public sealed partial class CP14UnlockPositionsService : CP14StoreBuyService
|
||||
if (!prototype.TryIndex(rBuy, out var indexedBuy))
|
||||
continue;
|
||||
|
||||
if (!station.Comp.AvailableBuyPosition.Contains(indexedBuy))
|
||||
if (!portal.Comp.AvailableBuyPosition.Contains(indexedBuy))
|
||||
continue;
|
||||
|
||||
station.Comp.AvailableBuyPosition.Remove(indexedBuy);
|
||||
portal.Comp.AvailableBuyPosition.Remove(indexedBuy);
|
||||
}
|
||||
|
||||
foreach (var rSell in RemoveSellPositions)
|
||||
{
|
||||
if (!prototype.TryIndex(rSell, out var indexedSell))
|
||||
continue;
|
||||
|
||||
if (!portal.Comp.AvailableSellPosition.Contains(indexedSell))
|
||||
continue;
|
||||
|
||||
portal.Comp.AvailableSellPosition.Remove(indexedSell);
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetName(IPrototypeManager protoMan)
|
||||
{
|
||||
return Loc.GetString(Name);
|
||||
}
|
||||
|
||||
public override EntProtoId? GetEntityView(IPrototypeManager protoManager)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override SpriteSpecifier? GetTexture(IPrototypeManager protoManager)
|
||||
{
|
||||
return Icon;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using Content.Shared.Destructible.Thresholds;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -17,23 +16,20 @@ public sealed partial class CP14StoreBuyPositionPrototype : IPrototype
|
||||
[DataField(required: true)]
|
||||
public int Price = 100;
|
||||
|
||||
[DataField(required: true)]
|
||||
public LocId Name = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// a unique code that can be used to purchase items.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public string Code = string.Empty;
|
||||
|
||||
[DataField(required: true)]
|
||||
public CP14StoreBuyService Service = default!;
|
||||
|
||||
[DataField]
|
||||
public LocId Desc = string.Empty;
|
||||
public SpriteSpecifier? IconOverride;
|
||||
|
||||
[DataField(required: true)]
|
||||
public SpriteSpecifier Icon = default!;
|
||||
|
||||
[DataField(required: true)]
|
||||
public List<CP14StoreBuyService> Services = new();
|
||||
[DataField]
|
||||
public LocId? NameOverride;
|
||||
|
||||
[DataField]
|
||||
public bool RoundstartAvailable = true;
|
||||
@@ -42,12 +38,27 @@ public sealed partial class CP14StoreBuyPositionPrototype : IPrototype
|
||||
/// If true, this item will randomly appear under the ‘Special Offer’ heading. With a chance to show up every time the ship arrives.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool Special = false;
|
||||
public bool Special;
|
||||
|
||||
[DataField]
|
||||
public HashSet<ProtoId<CP14StoreFactionPrototype>> Factions = new();
|
||||
}
|
||||
|
||||
[ImplicitDataDefinitionForInheritors]
|
||||
[MeansImplicitUse]
|
||||
public abstract partial class CP14StoreBuyService
|
||||
{
|
||||
public abstract void Buy(EntityManager entManager, IPrototypeManager prototype, Entity<CP14StationTravelingStoreShipTargetComponent> station);
|
||||
public abstract void Buy(EntityManager entManager, IPrototypeManager prototype, Entity<CP14TradingPortalComponent> portal);
|
||||
|
||||
public abstract string GetName(IPrototypeManager protoMan);
|
||||
|
||||
/// <summary>
|
||||
/// You can specify an icon generated from an entity. It will support layering, colour changes and other layer options. Return null to disable.
|
||||
/// </summary>
|
||||
public abstract EntProtoId? GetEntityView(IPrototypeManager protoManager);
|
||||
|
||||
/// <summary>
|
||||
/// You can specify the texture directly. Return null to disable.
|
||||
/// </summary>
|
||||
public abstract SpriteSpecifier? GetTexture(IPrototypeManager protoManager);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Cargo.Prototype;
|
||||
|
||||
[Prototype("storeFaction")]
|
||||
public sealed partial class CP14StoreFactionPrototype : IPrototype
|
||||
{
|
||||
[IdDataField, ViewVariables]
|
||||
public string ID { get; private set; } = default!;
|
||||
|
||||
[DataField(required: true)]
|
||||
public LocId Name = string.Empty;
|
||||
|
||||
[DataField]
|
||||
public LocId Desc = string.Empty;
|
||||
}
|
||||
@@ -17,15 +17,6 @@ public sealed partial class CP14StoreSellPositionPrototype : IPrototype
|
||||
[DataField(required: true)]
|
||||
public int Price = 100;
|
||||
|
||||
[DataField(required: true)]
|
||||
public LocId Name = string.Empty;
|
||||
|
||||
[DataField]
|
||||
public LocId Desc = string.Empty;
|
||||
|
||||
[DataField(required: true)]
|
||||
public SpriteSpecifier Icon = default!;
|
||||
|
||||
[DataField(required: true)]
|
||||
public CP14StoreSellService Service = default!;
|
||||
|
||||
@@ -37,6 +28,9 @@ public sealed partial class CP14StoreSellPositionPrototype : IPrototype
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool Special = false;
|
||||
|
||||
[DataField]
|
||||
public HashSet<ProtoId<CP14StoreFactionPrototype>> Factions = new();
|
||||
}
|
||||
|
||||
[ImplicitDataDefinitionForInheritors]
|
||||
@@ -44,4 +38,16 @@ public sealed partial class CP14StoreSellPositionPrototype : IPrototype
|
||||
public abstract partial class CP14StoreSellService
|
||||
{
|
||||
public abstract bool TrySell(EntityManager entManager, HashSet<EntityUid> entities);
|
||||
|
||||
public abstract string GetName(IPrototypeManager protoMan);
|
||||
|
||||
/// <summary>
|
||||
/// You can specify an icon generated from an entity. It will support layering, colour changes and other layer options. Return null to disable.
|
||||
/// </summary>
|
||||
public abstract EntProtoId? GetEntityView(IPrototypeManager protoManager);
|
||||
|
||||
/// <summary>
|
||||
/// You can specify the texture directly. Return null to disable.
|
||||
/// </summary>
|
||||
public abstract SpriteSpecifier? GetTexture(IPrototypeManager protoManager);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared._CP14.Cargo.Prototype.SellServices;
|
||||
|
||||
public sealed partial class CP14SellPrototypeService : CP14StoreSellService
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public EntProtoId Proto;
|
||||
|
||||
[DataField]
|
||||
public int Count = 1;
|
||||
|
||||
public override bool TrySell(EntityManager entManager, HashSet<EntityUid> entities)
|
||||
{
|
||||
HashSet<EntityUid> suitable = new();
|
||||
|
||||
var needCount = Count;
|
||||
foreach (var ent in entities)
|
||||
{
|
||||
if (needCount <= 0)
|
||||
break;
|
||||
|
||||
if (!entManager.TryGetComponent<MetaDataComponent>(ent, out var metaData))
|
||||
continue;
|
||||
|
||||
if (metaData.EntityPrototype is null)
|
||||
continue;
|
||||
|
||||
if (metaData.EntityPrototype != Proto)
|
||||
continue;
|
||||
|
||||
suitable.Add(ent);
|
||||
needCount -= 1;
|
||||
}
|
||||
|
||||
if (needCount > 0)
|
||||
return false;
|
||||
|
||||
foreach (var selledEnt in suitable)
|
||||
{
|
||||
entManager.QueueDeleteEntity(selledEnt);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string GetName(IPrototypeManager protoMan)
|
||||
{
|
||||
if (!protoMan.TryIndex(Proto, out var proto))
|
||||
return ":3";
|
||||
|
||||
return $"{proto.Name} x{Count}";
|
||||
}
|
||||
|
||||
public override EntProtoId? GetEntityView(IPrototypeManager protoManager)
|
||||
{
|
||||
return Proto;
|
||||
}
|
||||
|
||||
public override SpriteSpecifier? GetTexture(IPrototypeManager protoManager)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
using Content.Shared.Stacks;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared._CP14.Cargo.Prototype.SellServices;
|
||||
|
||||
public sealed partial class CP14SellStackService : CP14StoreSellService
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public ProtoId<StackPrototype> StackId = new();
|
||||
public ProtoId<StackPrototype> StackId;
|
||||
|
||||
[DataField(required: true)]
|
||||
public int Count = 1;
|
||||
@@ -17,7 +18,7 @@ public sealed partial class CP14SellStackService : CP14StoreSellService
|
||||
|
||||
Dictionary<Entity<StackComponent>, int> suitable = new();
|
||||
|
||||
int needCount = Count;
|
||||
var needCount = Count;
|
||||
foreach (var ent in entities)
|
||||
{
|
||||
if (needCount <= 0)
|
||||
@@ -49,4 +50,25 @@ public sealed partial class CP14SellStackService : CP14StoreSellService
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string GetName(IPrototypeManager protoMan)
|
||||
{
|
||||
if (!protoMan.TryIndex(StackId, out var proto))
|
||||
return ":3";
|
||||
|
||||
return $"{Loc.GetString(proto.Name)} x{Count}";
|
||||
}
|
||||
|
||||
public override EntProtoId? GetEntityView(IPrototypeManager protoManager)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override SpriteSpecifier? GetTexture(IPrototypeManager protoManager)
|
||||
{
|
||||
if (!protoManager.TryIndex(StackId, out var proto))
|
||||
return null;
|
||||
|
||||
return proto.Icon;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared._CP14.Cargo.Prototype.SellServices;
|
||||
|
||||
@@ -11,13 +12,19 @@ public sealed partial class CP14SellWhitelistService : CP14StoreSellService
|
||||
[DataField(required: true)]
|
||||
public int Count = 1;
|
||||
|
||||
[DataField(required: true)]
|
||||
public LocId Name = string.Empty;
|
||||
|
||||
[DataField(required: true)]
|
||||
public SpriteSpecifier? Sprite = null;
|
||||
|
||||
public override bool TrySell(EntityManager entManager, HashSet<EntityUid> entities)
|
||||
{
|
||||
var whitelistSystem = entManager.System<EntityWhitelistSystem>();
|
||||
|
||||
HashSet<EntityUid> suitable = new();
|
||||
|
||||
int needCount = Count;
|
||||
var needCount = Count;
|
||||
foreach (var ent in entities)
|
||||
{
|
||||
if (needCount <= 0)
|
||||
@@ -44,4 +51,19 @@ public sealed partial class CP14SellWhitelistService : CP14StoreSellService
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string GetName(IPrototypeManager protoMan)
|
||||
{
|
||||
return $"{Loc.GetString(Name)} x{Count}";
|
||||
}
|
||||
|
||||
public override EntProtoId? GetEntityView(IPrototypeManager protoManager)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override SpriteSpecifier? GetTexture(IPrototypeManager protoManager)
|
||||
{
|
||||
return Sprite;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,14 +46,9 @@ public partial class CP14SharedCurrencySystem : EntitySystem
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class CP14GetCurrencyEvent : EntityEventArgs
|
||||
public sealed class CP14GetCurrencyEvent(int currency = 0, int multiplier = 1) : EntityEventArgs
|
||||
{
|
||||
public int Currency;
|
||||
public float Multiplier;
|
||||
|
||||
public CP14GetCurrencyEvent(int cur = 0, int mult = 1)
|
||||
{
|
||||
Currency = cur;
|
||||
Multiplier = mult;
|
||||
}
|
||||
public HashSet<EntityUid> CheckedEntities = new();
|
||||
public int Currency = currency;
|
||||
public float Multiplier = multiplier;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
using System.Text;
|
||||
using Content.Shared._CP14.Knowledge.Components;
|
||||
using Content.Shared.Paper;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge;
|
||||
|
||||
public sealed class CP14KnowledgePaperTextSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly PaperSystem _paper = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<CP14KnowledgePaperTextComponent, MapInitEvent>(OnPaperMapInit);
|
||||
}
|
||||
|
||||
private void OnPaperMapInit(Entity<CP14KnowledgePaperTextComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
if (!TryComp<PaperComponent>(ent, out var paperComponent))
|
||||
return;
|
||||
|
||||
var paper = new Entity<PaperComponent>(ent, paperComponent);
|
||||
|
||||
if (!TryComp<CP14KnowledgeLearningSourceComponent>(ent, out var knowledge))
|
||||
return;
|
||||
|
||||
if (knowledge.Knowledge.Count == 0)
|
||||
return;
|
||||
|
||||
var content = GenerateText(knowledge);
|
||||
|
||||
_paper.SetContent(paper, content);
|
||||
paper.Comp.EditingDisabled = true;
|
||||
|
||||
// Yes we need to do synchronization after such changes,
|
||||
// yes predict, but we need to
|
||||
Dirty(paper);
|
||||
}
|
||||
|
||||
private string GenerateText(CP14KnowledgeLearningSourceComponent source)
|
||||
{
|
||||
var stringBuilder = new StringBuilder();
|
||||
|
||||
// Header
|
||||
stringBuilder.Append(Loc.GetString("cp14-knowledge-book-pre-text"));
|
||||
|
||||
// Main body
|
||||
foreach (var prototypeId in source.Knowledge)
|
||||
{
|
||||
if (!_prototype.TryIndex(prototypeId, out var indexedKnowledge))
|
||||
continue;
|
||||
|
||||
stringBuilder.Append($"\n{Loc.GetString(indexedKnowledge.Desc)}");
|
||||
}
|
||||
|
||||
// Footer
|
||||
stringBuilder.Append($"\n\n{Loc.GetString("cp14-knowledge-book-post-text")}");
|
||||
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge.Components;
|
||||
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class CP14AllKnowingComponent : Component;
|
||||
@@ -4,11 +4,12 @@ using Robust.Shared.Prototypes;
|
||||
namespace Content.Shared._CP14.Knowledge.Components;
|
||||
|
||||
/// <summary>
|
||||
/// The ability to add a skill to an entity and quickly teach it some skills
|
||||
/// The ability to add a <see cref="CP14KnowledgePrototype"/> to an entity
|
||||
/// and quickly teach it some skills.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedCP14KnowledgeSystem))]
|
||||
public sealed partial class CP14AutoAddKnowledgeComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public List<ProtoId<CP14KnowledgePrototype>> Knowledge = new();
|
||||
public List<ProtoId<CP14KnowledgePrototype>> Knowledge = [];
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Content.Shared._CP14.Knowledge.Components;
|
||||
public sealed partial class CP14KnowledgeLearningSourceComponent : Component
|
||||
{
|
||||
[DataField, ViewVariables(VVAccess.ReadOnly)]
|
||||
public HashSet<ProtoId<CP14KnowledgePrototype>> Knowledges { get; private set; } = new();
|
||||
public HashSet<ProtoId<CP14KnowledgePrototype>> Knowledge { get; private set; } = [];
|
||||
|
||||
[DataField]
|
||||
public TimeSpan DoAfter = TimeSpan.FromSeconds(5f);
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge.Components;
|
||||
|
||||
/// <summary>
|
||||
/// automatically generates content for PaperComponent, based on the knowledge that can be learnt from this object
|
||||
/// Automatically generates content for PaperComponent,
|
||||
/// based on the knowledge that can be learnt from this object.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedCP14KnowledgeSystem))]
|
||||
public sealed partial class CP14KnowledgePaperTextComponent : Component
|
||||
{
|
||||
}
|
||||
public sealed partial class CP14KnowledgePaperTextComponent : Component;
|
||||
|
||||
@@ -4,11 +4,11 @@ using Robust.Shared.Prototypes;
|
||||
namespace Content.Shared._CP14.Knowledge.Components;
|
||||
|
||||
/// <summary>
|
||||
/// a list of skills learned by this entity
|
||||
/// A list of <see cref="CP14KnowledgePrototype"/> learned by this entity.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedCP14KnowledgeSystem))]
|
||||
public sealed partial class CP14KnowledgeStorageComponent : Component
|
||||
{
|
||||
[DataField, ViewVariables(VVAccess.ReadOnly)]
|
||||
public HashSet<ProtoId<CP14KnowledgePrototype>> Knowledges { get; private set; } = new();
|
||||
public HashSet<ProtoId<CP14KnowledgePrototype>> Knowledge { get; private set; } = [];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge.Events;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class CP14KnowledgeInfoEvent : EntityEventArgs
|
||||
{
|
||||
public readonly NetEntity NetEntity;
|
||||
public readonly HashSet<ProtoId<CP14KnowledgePrototype>> AllKnowledge;
|
||||
|
||||
public CP14KnowledgeInfoEvent(NetEntity netEntity, HashSet<ProtoId<CP14KnowledgePrototype>> allKnowledge)
|
||||
{
|
||||
NetEntity = netEntity;
|
||||
AllKnowledge = allKnowledge;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Content.Shared.DoAfter;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge.Events;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class CP14KnowledgeLearnDoAfterEvent : DoAfterEvent
|
||||
{
|
||||
public ProtoId<CP14KnowledgePrototype> Knowledge;
|
||||
|
||||
public override DoAfterEvent Clone()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge.Events;
|
||||
|
||||
public sealed class CP14KnowledgeUsedEvent : EntityEventArgs
|
||||
{
|
||||
public readonly EntityUid User;
|
||||
public readonly ProtoId<CP14KnowledgePrototype> Knowledge;
|
||||
public readonly float Factor;
|
||||
|
||||
public CP14KnowledgeUsedEvent(EntityUid uid, ProtoId<CP14KnowledgePrototype> knowledge, float factor)
|
||||
{
|
||||
User = uid;
|
||||
Knowledge = knowledge;
|
||||
Factor = factor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge.Events;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class CP14RequestKnowledgeInfoEvent : EntityEventArgs
|
||||
{
|
||||
public readonly NetEntity NetEntity;
|
||||
|
||||
public CP14RequestKnowledgeInfoEvent(NetEntity netEntity)
|
||||
{
|
||||
NetEntity = netEntity;
|
||||
}
|
||||
}
|
||||
@@ -8,19 +8,18 @@ namespace Content.Shared._CP14.Knowledge.Prototypes;
|
||||
[Prototype("CP14Knowledge")]
|
||||
public sealed partial class CP14KnowledgePrototype : IPrototype
|
||||
{
|
||||
[ViewVariables]
|
||||
[IdDataField]
|
||||
public string ID { get; private set; } = default!;
|
||||
|
||||
[DataField(required: true)]
|
||||
public LocId Name { get; private set; } = default!;
|
||||
public LocId Name { get; private set; }
|
||||
|
||||
[DataField]
|
||||
public LocId Desc{ get; private set; } = default!;
|
||||
public LocId Desc { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// to study this knowledge, other knowledge on which it is based may be necessary.
|
||||
/// To study this knowledge, other knowledge on which it is based may be necessary.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public HashSet<ProtoId<CP14KnowledgePrototype>> Dependencies = new();
|
||||
public HashSet<ProtoId<CP14KnowledgePrototype>> Dependencies = [];
|
||||
}
|
||||
|
||||
@@ -1,122 +1,31 @@
|
||||
using System.Text;
|
||||
using Content.Shared._CP14.Knowledge.Components;
|
||||
using Content.Shared._CP14.Knowledge.Events;
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Ghost;
|
||||
using Content.Shared.MagicMirror;
|
||||
using Content.Shared.Paper;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge;
|
||||
|
||||
public abstract partial class SharedCP14KnowledgeSystem : EntitySystem
|
||||
public abstract class SharedCP14KnowledgeSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
[Dependency] private readonly PaperSystem _paper = default!;
|
||||
|
||||
public override void Initialize()
|
||||
public bool HasKnowledge(Entity<CP14KnowledgeStorageComponent?> entity, ProtoId<CP14KnowledgePrototype> knowledge)
|
||||
{
|
||||
SubscribeLocalEvent<CP14KnowledgePaperTextComponent, MapInitEvent>(OnPaperMapInit);
|
||||
if (HasComp<CP14AllKnowingComponent>(entity))
|
||||
return true;
|
||||
|
||||
return Resolve(entity, ref entity.Comp, false) && entity.Comp.Knowledge.Contains(knowledge);
|
||||
}
|
||||
|
||||
private void OnPaperMapInit(Entity<CP14KnowledgePaperTextComponent> ent, ref MapInitEvent args)
|
||||
public bool TryUseKnowledge(Entity<CP14KnowledgeStorageComponent?> entity, ProtoId<CP14KnowledgePrototype> knowledge, float factor = 1f)
|
||||
{
|
||||
if (!TryComp<PaperComponent>(ent, out var paper))
|
||||
return;
|
||||
if (!TryComp<CP14KnowledgeLearningSourceComponent>(ent, out var knowledge))
|
||||
return;
|
||||
if (knowledge.Knowledges.Count <= 0)
|
||||
return;
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.Append(Loc.GetString("cp14-knowledge-book-pre-text"));
|
||||
foreach (var k in knowledge.Knowledges)
|
||||
{
|
||||
if (!_proto.TryIndex(k, out var indexedKnowledge))
|
||||
continue;
|
||||
|
||||
sb.Append($"\n{Loc.GetString(indexedKnowledge.Desc)}");
|
||||
}
|
||||
|
||||
sb.Append($"\n\n{Loc.GetString("cp14-knowledge-book-post-text")}");
|
||||
|
||||
_paper.SetContent((ent, paper), sb.ToString());
|
||||
paper.EditingDisabled = true;
|
||||
}
|
||||
|
||||
public bool UseKnowledge(EntityUid uid,
|
||||
ProtoId<CP14KnowledgePrototype> knowledge,
|
||||
float factor = 1f,
|
||||
CP14KnowledgeStorageComponent? knowledgeStorage = null)
|
||||
{
|
||||
if (!Resolve(uid, ref knowledgeStorage, false))
|
||||
if (!Resolve(entity, ref entity.Comp, false))
|
||||
return false;
|
||||
|
||||
if (!knowledgeStorage.Knowledges.Contains(knowledge))
|
||||
if (!entity.Comp.Knowledge.Contains(knowledge))
|
||||
return false;
|
||||
|
||||
var ev = new CP14KnowledgeUsedEvent(uid, knowledge, factor);
|
||||
RaiseLocalEvent(uid, ev);
|
||||
var ev = new CP14KnowledgeUsedEvent(entity, knowledge, factor);
|
||||
RaiseLocalEvent(entity, ev);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool HasKnowledge(EntityUid uid,
|
||||
ProtoId<CP14KnowledgePrototype> knowledge,
|
||||
CP14KnowledgeStorageComponent? knowledgeStorage = null)
|
||||
{
|
||||
if (HasComp<GhostComponent>(uid)) //All-knowing ghosts
|
||||
return true;
|
||||
|
||||
if (!Resolve(uid, ref knowledgeStorage, false))
|
||||
return false;
|
||||
|
||||
return knowledgeStorage.Knowledges.Contains(knowledge);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class CP14KnowledgeUsedEvent : EntityEventArgs
|
||||
{
|
||||
public readonly EntityUid User;
|
||||
public readonly ProtoId<CP14KnowledgePrototype> Knowledge;
|
||||
public readonly float Factor;
|
||||
|
||||
public CP14KnowledgeUsedEvent(EntityUid uid, ProtoId<CP14KnowledgePrototype> knowledge, float factor)
|
||||
{
|
||||
User = uid;
|
||||
Knowledge = knowledge;
|
||||
Factor = factor;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class CP14KnowledgeLearnDoAfterEvent : DoAfterEvent
|
||||
{
|
||||
public ProtoId<CP14KnowledgePrototype> Knowledge;
|
||||
public override DoAfterEvent Clone() => this;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class CP14KnowledgeInfoEvent : EntityEventArgs
|
||||
{
|
||||
public readonly NetEntity NetEntity;
|
||||
public readonly HashSet<ProtoId<CP14KnowledgePrototype>> AllKnowledge;
|
||||
|
||||
public CP14KnowledgeInfoEvent(NetEntity netEntity, HashSet<ProtoId<CP14KnowledgePrototype>> allKnowledge)
|
||||
{
|
||||
NetEntity = netEntity;
|
||||
AllKnowledge = allKnowledge;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class RequestKnowledgeInfoEvent : EntityEventArgs
|
||||
{
|
||||
public readonly NetEntity NetEntity;
|
||||
|
||||
public RequestKnowledgeInfoEvent(NetEntity netEntity)
|
||||
{
|
||||
NetEntity = netEntity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,8 @@ public sealed partial class CP14MagicManacostModifySystem : EntitySystem
|
||||
msg.PushNewline();
|
||||
|
||||
var plus = (float)comp.GlobalModifier > 1 ? "+" : "";
|
||||
msg.AddMarkupOrThrow($"{Loc.GetString("cp14-clothing-magic-global")}: {plus}{((float)comp.GlobalModifier - 1)*100}%");
|
||||
msg.AddMarkupOrThrow(
|
||||
$"{Loc.GetString("cp14-clothing-magic-global")}: {plus}{MathF.Round((float)(comp.GlobalModifier - 1) * 100, MidpointRounding.AwayFromZero)}%");
|
||||
}
|
||||
|
||||
foreach (var modifier in comp.Modifiers)
|
||||
|
||||
30
Content.Shared/_CP14/MagicSpell/Spells/CP14SpellSuckBlood.cs
Normal file
30
Content.Shared/_CP14/MagicSpell/Spells/CP14SpellSuckBlood.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.FixedPoint;
|
||||
|
||||
namespace Content.Shared._CP14.MagicSpell.Spells;
|
||||
|
||||
public sealed partial class CP14SpellSuckBlood : CP14SpellEffect
|
||||
{
|
||||
[DataField]
|
||||
public FixedPoint2 SuckAmount = 25;
|
||||
public override void Effect(EntityManager entManager, CP14SpellEffectBaseArgs args)
|
||||
{
|
||||
if (args.Target is null)
|
||||
return;
|
||||
|
||||
if (args.User is null)
|
||||
return;
|
||||
|
||||
var solutionContainerSystem = entManager.System<SharedSolutionContainerSystem>();
|
||||
|
||||
if (!solutionContainerSystem.TryGetSolution(args.Target.Value, "bloodstream", out var targetBloodstreamSolution))
|
||||
return;
|
||||
|
||||
if (!solutionContainerSystem.TryGetSolution(args.User.Value, "chemicals", out var userSolution))
|
||||
return;
|
||||
|
||||
solutionContainerSystem.TryTransferSolution(userSolution.Value,
|
||||
targetBloodstreamSolution.Value.Comp.Solution,
|
||||
SuckAmount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Humanoid;
|
||||
|
||||
namespace Content.Shared._CP14.Vampire;
|
||||
|
||||
public abstract class CP14SharedVampireVisualsSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<CP14VampireVisualsComponent, ExaminedEvent>(OnVampireExamine);
|
||||
|
||||
SubscribeLocalEvent<CP14VampireVisualsComponent, ComponentInit>(OnVampireVisualsInit);
|
||||
SubscribeLocalEvent<CP14VampireVisualsComponent, ComponentShutdown>(OnVampireVisualsShutdown);
|
||||
}
|
||||
|
||||
protected virtual void OnVampireVisualsShutdown(Entity<CP14VampireVisualsComponent> vampire, ref ComponentShutdown args)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent(vampire, out HumanoidAppearanceComponent? humanoidAppearance))
|
||||
return;
|
||||
|
||||
humanoidAppearance.EyeColor = vampire.Comp.OriginalEyesColor;
|
||||
|
||||
Dirty(vampire, humanoidAppearance);
|
||||
}
|
||||
|
||||
protected virtual void OnVampireVisualsInit(Entity<CP14VampireVisualsComponent> vampire, ref ComponentInit args)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent(vampire, out HumanoidAppearanceComponent? humanoidAppearance))
|
||||
return;
|
||||
|
||||
vampire.Comp.OriginalEyesColor = humanoidAppearance.EyeColor;
|
||||
humanoidAppearance.EyeColor = vampire.Comp.EyesColor;
|
||||
|
||||
Dirty(vampire, humanoidAppearance);
|
||||
}
|
||||
|
||||
private void OnVampireExamine(Entity<CP14VampireVisualsComponent> ent, ref ExaminedEvent args)
|
||||
{
|
||||
args.PushMarkup(Loc.GetString("cp14-vampire-examine"));
|
||||
}
|
||||
}
|
||||
16
Content.Shared/_CP14/Vampire/CP14VampireVisualsComponent.cs
Normal file
16
Content.Shared/_CP14/Vampire/CP14VampireVisualsComponent.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared._CP14.Vampire;
|
||||
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class CP14VampireVisualsComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public Color EyesColor = Color.Red;
|
||||
|
||||
[DataField]
|
||||
public Color OriginalEyesColor = Color.White;
|
||||
|
||||
[DataField]
|
||||
public string FangsMap = "vampire_fangs";
|
||||
}
|
||||
@@ -26,7 +26,7 @@ public sealed partial class KnowledgeRequired : CP14WorkbenchCraftRequirement
|
||||
public override void PostCraft(EntityManager entManager, HashSet<EntityUid> placedEntities, EntityUid user)
|
||||
{
|
||||
var knowledgeSystem = entManager.System<SharedCP14KnowledgeSystem>();
|
||||
knowledgeSystem.UseKnowledge(user, Knowledge);
|
||||
knowledgeSystem.TryUseKnowledge(user, Knowledge);
|
||||
}
|
||||
|
||||
public override string GetRequirementTitle(IPrototypeManager protoManager)
|
||||
@@ -41,8 +41,8 @@ public sealed partial class KnowledgeRequired : CP14WorkbenchCraftRequirement
|
||||
return null;
|
||||
}
|
||||
|
||||
public override SpriteSpecifier? GetRequirementTexture(IPrototypeManager protoManager)
|
||||
public override SpriteSpecifier GetRequirementTexture(IPrototypeManager protoManager)
|
||||
{
|
||||
return new SpriteSpecifier.Texture(new("/Textures/Interface/students-cap.svg.192dpi.png"));
|
||||
return new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/students-cap.svg.192dpi.png"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,8 +63,12 @@
|
||||
copyright: 'by SpaceLife on Freesound.org'
|
||||
source: "https://freesound.org/people/SpaceLife/sounds/545938/"
|
||||
|
||||
|
||||
- files: ["essence_consume.ogg"]
|
||||
license: "CC0-1.0"
|
||||
copyright: 'by DustyWind on Freesound.org'
|
||||
source: "https://freesound.org/people/DustyWind/sounds/715784/"
|
||||
|
||||
- files: ["vampire_bite.ogg"]
|
||||
license: "CC0-1.0"
|
||||
copyright: 'by magnuswaker on Freesound.org'
|
||||
source: "https://freesound.org/people/magnuswaker/sounds/563491/"
|
||||
|
||||
BIN
Resources/Audio/_CP14/Effects/vampire_bite.ogg
Normal file
BIN
Resources/Audio/_CP14/Effects/vampire_bite.ogg
Normal file
Binary file not shown.
2
Resources/Locale/en-US/_CP14/administration/antag.ftl
Normal file
2
Resources/Locale/en-US/_CP14/administration/antag.ftl
Normal file
@@ -0,0 +1,2 @@
|
||||
cp14-admin-verb-text-make-vampire = Make vampire
|
||||
cp14-admin-verb-make-vampire = Add to target antagonist role “Vampire”
|
||||
3
Resources/Locale/en-US/_CP14/antag/antags.ftl
Normal file
3
Resources/Locale/en-US/_CP14/antag/antags.ftl
Normal file
@@ -0,0 +1,3 @@
|
||||
cp14-roles-antag-vampire-name = Vampire
|
||||
cp14-roles-antag-vampire-objective = You are a parasite on the body of society, hated by those around you, burned by the sun, and eternally hungry. You need to feed on the blood of the sentient to survive. And finding those who will volunteer to be your feeder is not easy...
|
||||
cp14-roles-antag-vampire-briefing = You are a parasite on society. It hates and fears you, but the blood of the living is your only food. Nature destroys you with sunlight, so you have to hide in the shadows. It's like the whole world is trying to destroy you, but your will to live is stronger than all of that. SURVIVE. That's all you have to do.
|
||||
@@ -18,7 +18,9 @@ cp14-modifier-mole = predatory moles
|
||||
cp14-modifier-rabbits = rabbits
|
||||
cp14-modifier-boars = wild boars
|
||||
cp14-modifier-invisible-whistler = invisible whistlers
|
||||
cp14-modifier-sheeps = sheeps
|
||||
cp14-modifier-chasm = bottomless chasms
|
||||
cp14-modifier-air-lily = air lilies
|
||||
cp14-modifier-time-limit-10 = temporary disintegration (10 minutes)
|
||||
cp14-modifier-shadow-kudzu = spreading darkness
|
||||
cp14-modifier-shadow-kudzu = spreading astral haze
|
||||
cp14-modifier-night = darkness
|
||||
@@ -54,6 +54,7 @@ cp14-loadout-merchant-shoes = Merchant's shoes
|
||||
# Guildmaster
|
||||
|
||||
cp14-loadout-guildmaster-outer = Guildmaster outer clothes
|
||||
cp14-loadout-guildmaster-head = Guildmaster hat
|
||||
cp14-loadout-guildmaster-cloak = Guildmaster cloak
|
||||
cp14-loadout-guildmaster-shirt = Guildmaster shirt
|
||||
cp14-loadout-guildmaster-pants = Guildmaster pants
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
cp14-lock-shape-bank-entrance = bank hall
|
||||
cp14-lock-shape-bank-staff = bank offices
|
||||
cp14-lock-shape-bank-commandant = commandant's house
|
||||
cp14-lock-shape-bank-safe = bank safes
|
||||
cp14-lock-shape-bank-vault = bank vault
|
||||
|
||||
cp14-lock-shape-tavern-hall = tavern hall
|
||||
cp14-lock-shape-tavern-staff = tavern staff quarters
|
||||
cp14-lock-shape-tavern-dorm1 = tavern room №1
|
||||
@@ -20,6 +14,10 @@ cp14-lock-shape-blacksmith1 = forge №1
|
||||
cp14-lock-shape-blacksmith2 = forge №2
|
||||
cp14-lock-shape-blacksmith3 = forge №3
|
||||
|
||||
cp14-lock-shape-merchant1 = shop №1
|
||||
cp14-lock-shape-merchant2 = shop №2
|
||||
cp14-lock-shape-merchant3 = shop №3
|
||||
|
||||
cp14-lock-shape-personalhouse1 = house №1
|
||||
cp14-lock-shape-personalhouse2 = house №2
|
||||
cp14-lock-shape-personalhouse3 = house №3
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
cp14-objective-issuer-personal = [color="#95a6c2"]Personal objectives[/color]
|
||||
|
||||
cp14-objective-personal-currency-collect-title = Earn{$coins}
|
||||
cp14-objective-personal-currency-collect-desc = I plan to earn at least{$coins} by working here.
|
||||
cp14-objective-personal-currency-collect-desc = I plan to earn at least{$coins} by working here.
|
||||
|
||||
cp14-objective-personal-richest-merchant-title = Become the richest of merchants
|
||||
cp14-objective-personal-richest-merchant-desc = I must beat all other merchants by making more money than all of them!
|
||||
@@ -1,3 +1,9 @@
|
||||
cp14-reagent-name-blood-animal = Animal blood
|
||||
cp14-reagent-desc-blood-animal = The life energy of a living unintelligent being.
|
||||
|
||||
cp14-reagent-name-blood-vampire = Vampire blood
|
||||
cp14-reagent-desc-blood-vampire = The life energy of a powerful blood-vampire.
|
||||
|
||||
cp14-reagent-name-blood = Blood
|
||||
cp14-reagent-desc-blood = The life energy of a living warm-blooded creatures.
|
||||
|
||||
|
||||
11
Resources/Locale/en-US/_CP14/store/factions.ftl
Normal file
11
Resources/Locale/en-US/_CP14/store/factions.ftl
Normal file
@@ -0,0 +1,11 @@
|
||||
cp14-faction-name-helmir = Helmir's descendants
|
||||
cp14-faction-desc-helmir = TODO
|
||||
|
||||
cp14-faction-name-sylphoria = The winds of Sylphoria
|
||||
cp14-faction-desc-sylphoria = TODO
|
||||
|
||||
cp14-faction-name-spice-stream = Spice Stream
|
||||
cp14-faction-desc-spice-stream = TODO
|
||||
|
||||
cp14-faction-name-brad-family = Brad's imperial family
|
||||
cp14-faction-desc-brad-family = TODO
|
||||
11
Resources/Locale/en-US/_CP14/store/ui.ftl
Normal file
11
Resources/Locale/en-US/_CP14/store/ui.ftl
Normal file
@@ -0,0 +1,11 @@
|
||||
cp14-store-ui-title = Trading outpost "{$name}"
|
||||
cp14-store-ui-order = More info
|
||||
|
||||
cp14-store-ui-next-travel-out = Before departure:
|
||||
cp14-store-ui-next-travel-in = Before arrival:
|
||||
|
||||
cp14-store-ui-tab-buy = Buying
|
||||
cp14-store-ui-tab-sell = Selling
|
||||
cp14-store-ui-tab-special = [bold][color=#eba346]One-off offer![/color][/bold]
|
||||
|
||||
cp14-store-sell-hint = To sell {$name}, put the item you want in the trade cabinet, and close it. Our people will figure out what's what, pick up the item, and send you the money through the same sales cabinet.
|
||||
@@ -11,7 +11,7 @@ cp14-tips-10 = Tall bushes are good for hiding your character! But they slow you
|
||||
cp14-tips-11 = Don't forget to lock your doors if you don't want anyone to get in!
|
||||
cp14-tips-12 = You can examine the demiplane key to see what you can find in it. The information may be incomplete, but you can still navigate by it, and choose where you want to go.
|
||||
cp14-tips-13 = As a farmer, don't forget to water your vegetable garden! Plants die without watering.
|
||||
cp14-tips-14 = To pierce the dish, try combining different ingredients on a plate.
|
||||
cp14-tips-14 = Demiplanes can be very dangerous, don't neglect medical consumables and alchemist potions.
|
||||
cp14-tips-15 = When you use the demiplane key, an unstable rift opens up that will draw in up to 4 nearby players after a while.
|
||||
cp14-tips-16 = When moving between or from the demiplane, you can additionally grab a large item (or the corpse of a dead friend) by pulling it with you during the teleportation time.
|
||||
cp14-tips-17 = If you wish to leave the round, you may board a traveling ship. When it travels to the empire, you will leave the round and free up your role for another player.
|
||||
@@ -1,37 +0,0 @@
|
||||
cp14-store-sell-hint = To sell {$name}, load the desired goods onto the selling pallets. Our people in town will sort it out, pick up the goods and leave the money in the trade box on the ship.
|
||||
|
||||
cp14-store-sell-wood-name = 30 wooden planks
|
||||
cp14-store-sell-wood-desc = Do you really think anyone needs planks from a faraway island? Well, you're right, we hope your settlement has something to keep you warm in the winter.
|
||||
|
||||
cp14-store-sell-glass-name = 10 glass
|
||||
cp14-store-sell-glass-desc = A fine material prized in the Empire for its versatility. The windows of palaces, the lenses of craftsmen, and even the mirrors of mages all require glass. Your labors are sure to find a use for it!
|
||||
|
||||
cp14-store-sell-alchemical-herbals-name = 10 alchemical herbals
|
||||
cp14-store-sell-alchemical-herbals-desc = TODO
|
||||
|
||||
# Metalls
|
||||
|
||||
cp14-store-sell-copperbar-name = 10 copper bars
|
||||
cp14-store-sell-copperbar-desc = Although copper is used mainly as a coin material, it is also often enjoyed by blacksmiths in various alloys.
|
||||
|
||||
cp14-store-sell-ironbar-name = 10 iron bars
|
||||
cp14-store-sell-ironbar-desc = Iron is an indispensable material in the manufacture of... almost anything that has any longevity in this world. And surely the Empire could use an extra shipment.
|
||||
|
||||
cp14-store-sell-goldbar-name = 10 gold bars
|
||||
cp14-store-sell-goldbar-desc = The mining and processing of gold ore is heavily sponsored by the empire, which uses gold as currency and material for jewelry.
|
||||
|
||||
cp14-store-sell-mithrilbar-name = 10 mithril bars
|
||||
cp14-store-sell-mithrilbar-desc = TODO
|
||||
|
||||
|
||||
cp14-store-sell-copperore-name = 10 copper ore
|
||||
cp14-store-sell-copperore-desc = TODO
|
||||
|
||||
cp14-store-sell-ironore-name = 10 iron ore
|
||||
cp14-store-sell-ironore-desc = TODO
|
||||
|
||||
cp14-store-sell-goldore-name = 10 gold ore
|
||||
cp14-store-sell-goldore-desc = TODO
|
||||
|
||||
cp14-store-sell-mithrilore-name = 10 mithril ore
|
||||
cp14-store-sell-mithrilore-desc = TODO
|
||||
@@ -1,20 +0,0 @@
|
||||
cp14-store-sell-special-wheat-name = 10 sheaves of wheat
|
||||
cp14-store-sell-special-wheat-desc = Urgent wheat order! Our lizards have gone berserk and devoured the entire supply! Any supplies of wheat would be appreciated!
|
||||
|
||||
cp14-store-sell-special-dye-name = 10 dyes
|
||||
cp14-store-sell-special-dye-desc = An aristocrat from the capital has suddenly shown an interest in painting, and requires dyes for his experiments. The Empire is buying up all the dyes you can provide her with.
|
||||
|
||||
cp14-store-sell-special-meat-name = 10 pieces of meat
|
||||
cp14-store-sell-special-meat-desc = Any kind of meat will do. Lambs, goats, cows, even giant worms! In fact, send anything you want, Isil Island has no food for carnivores at the moment.
|
||||
|
||||
cp14-store-sell-special-torch-name = 20 torches
|
||||
cp14-store-sell-special-torch-desc = The settlement of Grimstroke is requesting a large shipment of torches from the Empire! We're making a big march on the Great Tomb of Lazaric! And we have nothing to light it with.
|
||||
|
||||
cp14-store-sell-special-ash-name = 10 ashes
|
||||
cp14-store-sell-special-ash-desc = The Mermaid Council is requesting a shipment of ash to their oceanic domain for the reason, quote ‘Where do you think we should get ash from underwater?’
|
||||
|
||||
cp14-store-sell-special-lucen-name = 10 lucen planks
|
||||
cp14-store-sell-special-lucen-desc = A shipment of magical wood is needed to build an enchanted country house for an aristocrat. The whims of the rich are mysterious!
|
||||
|
||||
cp14-store-sell-special-spell-scroll-name = 5 spell scrolls
|
||||
cp14-store-sell-special-spell-scroll-desc = We don't really care what spells are in the scrolls, they are only for reporting the magical prosperity of the settlement to the local Commandant.
|
||||
@@ -1,9 +0,0 @@
|
||||
cp14-store-ui-title = Retail information board
|
||||
cp14-store-ui-order = More info
|
||||
|
||||
cp14-store-ui-next-travel-out = Before departure:
|
||||
cp14-store-ui-next-travel-in = Before arrival:
|
||||
|
||||
cp14-store-ui-tab-buy = Buying
|
||||
cp14-store-ui-tab-sell = Selling
|
||||
cp14-store-ui-tab-special = [bold][color=#eba346]Temporary offer![/color][/bold]
|
||||
3
Resources/Locale/en-US/_CP14/vampire/vampire.ftl
Normal file
3
Resources/Locale/en-US/_CP14/vampire/vampire.ftl
Normal file
@@ -0,0 +1,3 @@
|
||||
cp14-heat-under-sun = The sunlight stings unbearably...
|
||||
|
||||
cp14-vampire-examine = [color=red]Bright red eyes and long fangs tell you that you are facing a very dangerous vampire. Your instincts are telling you to run or fight![/color]
|
||||
@@ -601,6 +601,9 @@ ent-CP14ClothingHeadAlchemistBeret = берет алхимика
|
||||
ent-CP14ClothingHeadCaptainCap = капитанская кепка
|
||||
.desc = Нет, ну вы посмотрите какой красавчик!
|
||||
|
||||
ent-CP14ClothingHeadGildmaster = шляпа гильдмастера
|
||||
.desc = Знак безграничного опыта и чести.
|
||||
|
||||
ent-CP14ClothingHeadBeretBase = { ent-CP14ClothingHeadBase }
|
||||
.desc = Это берет.
|
||||
|
||||
|
||||
2
Resources/Locale/ru-RU/_CP14/administration/antag.ftl
Normal file
2
Resources/Locale/ru-RU/_CP14/administration/antag.ftl
Normal file
@@ -0,0 +1,2 @@
|
||||
cp14-admin-verb-text-make-vampire = Сделать вампиром
|
||||
cp14-admin-verb-make-vampire = Добавить цели роль "Вампир"
|
||||
3
Resources/Locale/ru-RU/_CP14/antag/antags.ftl
Normal file
3
Resources/Locale/ru-RU/_CP14/antag/antags.ftl
Normal file
@@ -0,0 +1,3 @@
|
||||
cp14-roles-antag-vampire-name = Вампир
|
||||
cp14-roles-antag-vampire-objective = Вы - паразит на теле общества, ненавидимый окружающими, сгораемый под солнцем и вечно голодный. Вам необходимо питаться кровью разумных, чтобы выжить. И найти тех, кто добровольно будет готов стать вашей кормушкой непросто...
|
||||
cp14-roles-antag-vampire-briefing = Вы - паразит на теле общества. Оно вас ненавидит и боится, но кровь живых - ваша единственная пища. Природа уничтожает вас солнечным светом, и вам приходится скрываться в тени. Словно весь мир пытается вас уничтожить, но ваше желание жить сильнее всего этого. ВЫЖИВИТЕ. Это все что от вас требуется.
|
||||
@@ -17,8 +17,10 @@ cp14-modifier-dyno = доисторической фауны
|
||||
cp14-modifier-mole = хищных кротов
|
||||
cp14-modifier-rabbits = кроликов
|
||||
cp14-modifier-boars = диких кабанов
|
||||
cp14-modifier-sheeps = овец
|
||||
cp14-modifier-invisible-whistler = невидимых свистунов
|
||||
cp14-modifier-chasm = бездонных пропастей
|
||||
cp14-modifier-air-lily = воздушных лилий
|
||||
cp14-modifier-time-limit-10 = временного распада (10 минут)
|
||||
cp14-modifier-shadow-kudzu = распространяющейся тьмы
|
||||
cp14-modifier-shadow-kudzu = распространяющгося астрального мрака
|
||||
cp14-modifier-night = темноты
|
||||
@@ -54,6 +54,7 @@ cp14-loadout-merchant-shoes = Ботинки торговца
|
||||
# Guildmaster
|
||||
|
||||
cp14-loadout-guildmaster-outer = Верхняя одежда гильдмастера
|
||||
cp14-loadout-guildmaster-head = Шляпа гильдмастера
|
||||
cp14-loadout-guildmaster-cloak = Накидка гильдмастера
|
||||
cp14-loadout-guildmaster-shirt = Рубашка гильдмастера
|
||||
cp14-loadout-guildmaster-pants = Штаны гильдмастера
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
cp14-lock-shape-bank-entrance = холл банка
|
||||
cp14-lock-shape-bank-staff = служебные помещения банка
|
||||
cp14-lock-shape-bank-commandant = дом комменданта
|
||||
cp14-lock-shape-bank-safe = сейфы банка
|
||||
cp14-lock-shape-bank-vault = хранилище банка
|
||||
|
||||
cp14-lock-shape-tavern-hall = зал таверны
|
||||
cp14-lock-shape-tavern-staff = служебные помещения таверны
|
||||
cp14-lock-shape-tavern-dorm1 = комната таверны №1
|
||||
@@ -20,6 +14,10 @@ cp14-lock-shape-blacksmith1 = кузня №1
|
||||
cp14-lock-shape-blacksmith2 = кузня №2
|
||||
cp14-lock-shape-blacksmith3 = кузня №3
|
||||
|
||||
cp14-lock-shape-merchant1 = магазин №1
|
||||
cp14-lock-shape-merchant2 = магазин №2
|
||||
cp14-lock-shape-merchant3 = магазин №3
|
||||
|
||||
cp14-lock-shape-personalhouse1 = дом №1
|
||||
cp14-lock-shape-personalhouse2 = дом №2
|
||||
cp14-lock-shape-personalhouse3 = дом №3
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
cp14-objective-issuer-personal = [color="#95a6c2"]Личные цели[/color]
|
||||
|
||||
cp14-objective-personal-currency-collect-title = Заработать{$coins}
|
||||
cp14-objective-personal-currency-collect-desc = Я планирую заработать как минимум{$coins}, работая здесь.
|
||||
cp14-objective-personal-currency-collect-desc = Я планирую заработать как минимум{$coins}, работая здесь.
|
||||
|
||||
cp14-objective-personal-richest-merchant-title = Стать самым богатым из торговцев
|
||||
cp14-objective-personal-richest-merchant-desc = Я должен обставить всех других торговцев, заработав денег больше чем все они!
|
||||
@@ -1,3 +1,9 @@
|
||||
cp14-reagent-name-blood-animal = Кровь животного
|
||||
cp14-reagent-desc-blood-animal = Жизненная энергия живого неразумного существа.
|
||||
|
||||
cp14-reagent-name-blood-vampire = Кровь вампира
|
||||
cp14-reagent-desc-blood-vampire = Жизненная энергия могущественного кровопийпы.
|
||||
|
||||
cp14-reagent-name-blood = Кровь
|
||||
cp14-reagent-desc-blood = Жизненная энергия живого теплокровного существа.
|
||||
|
||||
|
||||
11
Resources/Locale/ru-RU/_CP14/store/factions.ftl
Normal file
11
Resources/Locale/ru-RU/_CP14/store/factions.ftl
Normal file
@@ -0,0 +1,11 @@
|
||||
cp14-faction-name-helmir = Хельмировы потомки
|
||||
cp14-faction-desc-helmir = TODO
|
||||
|
||||
cp14-faction-name-sylphoria = Ветра Сильфории
|
||||
cp14-faction-desc-sylphoria = TODO
|
||||
|
||||
cp14-faction-name-spice-stream = Поток пряностей
|
||||
cp14-faction-desc-spice-stream = TODO
|
||||
|
||||
cp14-faction-name-brad-family = Имперская семья Брада
|
||||
cp14-faction-desc-brad-family = TODO
|
||||
11
Resources/Locale/ru-RU/_CP14/store/ui.ftl
Normal file
11
Resources/Locale/ru-RU/_CP14/store/ui.ftl
Normal file
@@ -0,0 +1,11 @@
|
||||
cp14-store-ui-title = Торговый аванпост "{$name}"
|
||||
cp14-store-ui-order = Дополнительная информация
|
||||
|
||||
cp14-store-ui-next-travel-out = До отправления:
|
||||
cp14-store-ui-next-travel-in = До прибытия:
|
||||
|
||||
cp14-store-ui-tab-buy = Покупка
|
||||
cp14-store-ui-tab-sell = Продажа
|
||||
cp14-store-ui-tab-special = [bold][color=#eba346]Разовое предложение![/color][/bold]
|
||||
|
||||
cp14-store-sell-hint = Чтобы продать {$name}, засуньте необходимый товар в торговый шкаф, и закройте его. Наши люди разберутся что к чему, заберут товар и отправят вам деньги через этот же торговый шкаф.
|
||||
@@ -11,7 +11,7 @@ cp14-tips-10 = Высокие кусты неплохо прячут вашег
|
||||
cp14-tips-11 = Не забывайте закрывать двери на ключ, если не хотите чтобы туда заходил кто попало!
|
||||
cp14-tips-12 = Вы можете осмотреть ключ демиплана, чтобы узнать, что вы можете в нем найти. Информация может быть неполной, но по ней вы все равно можете ориентироваться, и выбирать куда вы хотите отправиться.
|
||||
cp14-tips-13 = Будучи фермером, не забывайте поливать свой огород! Растения умирают без полива.
|
||||
cp14-tips-14 = Чтобы приготовить блюдо, попробуйте скомбинировать на тарелке разные ингредиенты.
|
||||
cp14-tips-14 = Демипланы могут быть очень опасны, не пренебрегайте медицинскими расходными материалами и алхимическими зельями.
|
||||
cp14-tips-15 = Когда вы используете ключ демиплана, открывается нестабильный разлом, который через некоторое время затянет в себя до 4 ближайших игроков.
|
||||
cp14-tips-16 = Перемещаясь между демипланом или из него, вы можете дополнительно захватить с собой большой предмет (или труп погибшего союзника), держа его во время момента телепортации.
|
||||
cp14-tips-17 = Если вы хотите покинуть раунд, вы можете сесть на странствующий корабль. Когда он отправится в империю, вы покинете раунд и освободите свою роль для другого игрока.
|
||||
@@ -1,20 +0,0 @@
|
||||
cp14-store-sell-special-wheat-name = 10 снопов пшеницы
|
||||
cp14-store-sell-special-wheat-desc = Срочный заказ пшеницы! Наши ящеры взбесились и сожрали вообще все запасы! Мы будем благодарны любым запасам пшена!
|
||||
|
||||
cp14-store-sell-special-dye-name = 10 красителей
|
||||
cp14-store-sell-special-dye-desc = Аристократ из столицы внезапно проявил интерес с рисованию, и требует красителей для своих экспериментов. Империя скупаем все красители, которые вы сможете ей предоставить.
|
||||
|
||||
cp14-store-sell-special-meat-name = 10 кусков мяса
|
||||
cp14-store-sell-special-meat-desc = Нам подойдет любое мясо. Бараны, козы, коровы, да хоть гигантские черви! В общем, присылайте любое, острову Изиль сейчас нечем кормить хищный скот.
|
||||
|
||||
cp14-store-sell-special-torch-name = 20 факелов
|
||||
cp14-store-sell-special-torch-desc = Поселение Гримстроук запрашивает большую партию факелов от Империи! Мы устраиваем большой поход на Великую Гробницу Лазарика! И нам нечем освещать ее.
|
||||
|
||||
cp14-store-sell-special-ash-name = 10 пепла
|
||||
cp14-store-sell-special-ash-desc = Совет русалок запрашивает партию пепла в свои океанические владения по причине, цитата 'Откуда мы должны под водой получать пепел по вашему?'
|
||||
|
||||
cp14-store-sell-special-lucen-name = 10 люценовых досок
|
||||
cp14-store-sell-special-lucen-desc = Необходима партия магической древесины для строительства зачарованной загородной дачи одного из аристократов. Причуды богатых неисповедимы!
|
||||
|
||||
cp14-store-sell-special-spell-scroll-name = 5 свитков заклинаний
|
||||
cp14-store-sell-special-spell-scroll-desc = Нам на самом деле не важно какие именно заклинания находятся в свитках, они нам только для отчетности магического процветания поселения перед местным Комендантом.
|
||||
@@ -1,37 +0,0 @@
|
||||
cp14-store-sell-hint = Чтобы продать {$name}, погрузите необходимый товар на продающие поддоны. Наши люди в городе разберутся что к чему, заберут товар и оставят деньги в торговом ящике на корабле.
|
||||
|
||||
cp14-store-sell-wood-name = 30 деревянных досок
|
||||
cp14-store-sell-wood-desc = Вы правда думаете что хоть кому то нужны доски с далекого острова? Что ж вы правы, надеемся у вашего поселения есть чем греться зимой.
|
||||
|
||||
cp14-store-sell-glass-name = 10 стекла
|
||||
cp14-store-sell-glass-desc = Изящный материал, который ценится в Империи за свою универсальность. Окна дворцов, линзы мастеров и даже зеркала магов — все это требует стекла. Ваши труды точно найдут применение!
|
||||
|
||||
cp14-store-sell-alchemical-herbals-name = 10 алхимических растений
|
||||
cp14-store-sell-alchemical-herbals-desc = TODO
|
||||
|
||||
# Metalls
|
||||
|
||||
cp14-store-sell-copperbar-name = 10 медных слитков
|
||||
cp14-store-sell-copperbar-desc = Хоть медь и используется в основном как материал для монет но и в разных сплавах он часто нравится кузнецам.
|
||||
|
||||
cp14-store-sell-ironbar-name = 10 железных слитков
|
||||
cp14-store-sell-ironbar-desc = Железо - незаменимый материал для производства... почти всего, что имеет хоть какую либо долговечность в этом мире. И конечно же, Империя не откажется от дополнительной партии.
|
||||
|
||||
cp14-store-sell-goldbar-name = 10 золотых слитков
|
||||
cp14-store-sell-goldbar-desc = Добыча и обработка золотой руды активно спонсируется империей, использующей золото как валюту и материал для ювелирных украшений.
|
||||
|
||||
cp14-store-sell-mithrilbar-name = 10 мифриловых слитков
|
||||
cp14-store-sell-mithrilbar-desc = TODO
|
||||
|
||||
|
||||
cp14-store-sell-copperore-name = 10 медной руды
|
||||
cp14-store-sell-copperore-desc = TODO
|
||||
|
||||
cp14-store-sell-ironore-name = 10 железной руды
|
||||
cp14-store-sell-ironore-desc = TODO
|
||||
|
||||
cp14-store-sell-goldore-name = 10 золотой руды
|
||||
cp14-store-sell-goldore-desc = TODO
|
||||
|
||||
cp14-store-sell-mithrilore-name = 10 мифриловой руды
|
||||
cp14-store-sell-mithrilore-desc = TODO
|
||||
@@ -1,9 +0,0 @@
|
||||
cp14-store-ui-title = Информационное торговое табло
|
||||
cp14-store-ui-order = Дополнительная информация
|
||||
|
||||
cp14-store-ui-next-travel-out = До отправления:
|
||||
cp14-store-ui-next-travel-in = До прибытия:
|
||||
|
||||
cp14-store-ui-tab-buy = Покупка
|
||||
cp14-store-ui-tab-sell = Продажа
|
||||
cp14-store-ui-tab-special = [bold][color=#eba346]Временное предложение![/color][/bold]
|
||||
3
Resources/Locale/ru-RU/_CP14/vampire/vampire.ftl
Normal file
3
Resources/Locale/ru-RU/_CP14/vampire/vampire.ftl
Normal file
@@ -0,0 +1,3 @@
|
||||
cp14-heat-under-sun = Солнечый свет нестерпимо жжется...
|
||||
|
||||
cp14-vampire-examine = [color=red]Ярко красные глаза и длинные клыки говорят вам что перед вами опаснейший вампир. Ваши инстинкты кричат вам бежать или сражаться![/color]
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -78,6 +78,7 @@ entities:
|
||||
parent: 1
|
||||
- type: BecomesStation
|
||||
id: Dev
|
||||
- type: Roof
|
||||
- type: MapGrid
|
||||
chunks:
|
||||
0,0:
|
||||
@@ -2489,7 +2490,7 @@ entities:
|
||||
- type: Transform
|
||||
pos: 5.5,-9.5
|
||||
parent: 2
|
||||
- proto: CP14TravelingShop
|
||||
- proto: CP14TradingBoardBase
|
||||
entities:
|
||||
- uid: 418
|
||||
components:
|
||||
@@ -2503,15 +2504,6 @@ entities:
|
||||
rot: -1.5707963267948966 rad
|
||||
pos: 0.5,11.5
|
||||
parent: 2
|
||||
- proto: CP14TravelingStoreshipAnchor
|
||||
entities:
|
||||
- uid: 467
|
||||
components:
|
||||
- type: Transform
|
||||
anchored: False
|
||||
rot: 1.5707963267948966 rad
|
||||
pos: 1.5,14.5
|
||||
parent: 1
|
||||
- proto: CP14VialMedium
|
||||
entities:
|
||||
- uid: 45
|
||||
@@ -3103,7 +3095,7 @@ entities:
|
||||
- type: Transform
|
||||
pos: 3.5,-0.5
|
||||
parent: 2
|
||||
- proto: CP14WoodenDoorTavernAlchemy1
|
||||
- proto: CP14WoodenDoorAlchemy1
|
||||
entities:
|
||||
- uid: 287
|
||||
components:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user