Compare commits

...

33 Commits

Author SHA1 Message Date
Ed
a2b62c4ca4 Update GhostSystem.cs 2024-12-10 00:40:50 +03:00
Ed
b535123a66 Update GhostSystem.cs 2024-12-09 23:58:39 +03:00
Ed
9bb2177197 Update biome_template_caves.yml 2024-12-09 22:21:42 +03:00
Ed
4f7710619d comoss zlevel sewers 2024-12-09 22:19:28 +03:00
Ed
22b0f46890 Roundleave ship clean up (#653)
* cryo shuttle rework

* Update entities.ftl
2024-12-09 20:39:56 +03:00
Ed
bec8d7a7d4 Ghost z-levels move actions + mapping z-levels combine command (#654)
* some setup

* fast ghost zlevels-moving

* zlevel combine command for mapping
2024-12-09 20:39:46 +03:00
Ed
5384adb2b3 Blacksmith again (#652)
* golden and copper sword

* copper sickle

* maces

* shovels

* modular axes

* fixes
2024-12-09 00:40:27 +03:00
Ed
c2b7c5146d second blacksmith 2024-12-08 14:43:12 +03:00
Ed
61454e351c Another blacksmith minor update (#648)
* modular golden sickle

* anvil and furnace resprite

* Update comoss.yml
2024-12-08 14:17:48 +03:00
Ed
dc5333ee18 localization update 2024-12-08 01:19:57 +03:00
Ed
0662299120 Aftertest tweaks (#647)
* fix #641

* fix #639

* add copper, bloodflowers and wild sage into comoss island

* remove additional alchemist and blacksmithes roles

* more roundstart resources for alchemist and blacksmith

* disable footprints system

* cryo shuttle mechanic

* update cargo ship

* veryy magical

* tips update

* fix #635

* green cloak

* Update T0_cure_poison.yml
2024-12-08 00:52:35 +03:00
Ed
80be633aa1 Update ContentLocalizationManager.cs 2024-12-07 20:55:30 +03:00
Ed
264ef809bd Update personal_objectives.yml 2024-12-07 20:49:51 +03:00
Ed
ccc97f0e70 Update CP14SandboxRU.xml 2024-12-07 15:04:28 +03:00
Ed
15017b7c4f personal key loadout 2024-12-07 14:49:02 +03:00
Ed
2d54561a31 Update ContentLocalizationManager.cs 2024-12-07 12:41:51 +03:00
Nim
417668b88b Crayon (#634)
* crayon

* add crayon into loots

---------

Co-authored-by: Ed <edwardxperia2000@gmail.com>
2024-12-07 00:50:54 +03:00
Ed
52a0f44aa1 Bank progression mechanic (#633)
* bank progression mechanic

* loc fix

* minor random fixes

* minor tweaks

* lighthouse

* Vladimirs Alerts!

* offset alerts

* lighthouse
2024-12-07 00:39:05 +03:00
Ed
02cbeee6dc Demiplane fixes (#632)
* limit demiplace wshwooshing by interaction range, fix global gibbing

* Update base.yml

* fix #521
2024-12-06 17:16:38 +03:00
Ed
64df860b50 Salary for the guards (#631)
* public API

* salary init

* salary finish

* Update entities.ftl

* Update salary.yml
2024-12-06 00:59:37 +03:00
Ed
ce34c6f2a0 Update lockTypes.yml 2024-12-05 21:25:34 +03:00
Ed
8252418fdc Update personalHouse.yml 2024-12-05 18:19:10 +03:00
Ed
094fbc445f localization sync 2024-12-05 14:43:43 +03:00
Ed
319cd18ee8 demiplane closing - adventurers tp out and gib (#629) 2024-12-05 12:35:38 +03:00
Ed
304e1a268a Balance pack (#628)
* map fixes, move crystalls from houses into startgear

* fix lock types

* fix item throwing, reduce lock powers, add lockpick into anvil

* new store positions

* restruct swords

* nerf skeleton, bone halberd
2024-12-05 00:29:14 +03:00
A.Ne.
e6a6900719 Prototypes for Guard (#616)
* Prototypes for Guard

* imperial laws

* merge

* yml clean up

* flags + change in imperial laws

* map update

* guard clothing resprite

* cool guard helmet

* guards grip and halberd

* fill cabinets, add guard commander stamp

* key and keyring fix

* Update arenas.yml

* Update migration.yml

* tapestry fix

* guidebook spacing

* Update meta.json

* add bold tags

* Update flags_wallmount.yml

---------

Co-authored-by: Ed <edwardxperia2000@gmail.com>
2024-12-04 18:11:33 +03:00
Ed
0e88b6dc6f Table fences (#626)
* collision fucks

* map update
2024-12-03 16:21:07 +03:00
Ed
f6630e1ec9 Key distribution system (#625)
* data restruct

* yay

* Update arenas.yml

* fixes

* auto labeling

* shuffle
2024-12-03 12:34:07 +03:00
Ed
7e6e4709c4 Ed 01 12 2024 rapier (#623)
* Rapier blade

* file restruct

* golden garde

* iron sharp garde

* copper garde
2024-12-02 00:08:23 +03:00
Ed
c6ac192dfb Gold & Copper modular parts 1 (#621)
* gold & copper daggers

* copper and gold short grip

* gold & copper grips

* golden pickaxe

* copper pickaxe

* Update anvil.yml
2024-12-01 20:11:59 +03:00
Ed
bb43b37fd8 Bugfixes (#619)
* clean up

* Update empire_orders.yml
2024-11-30 14:16:48 +03:00
Ed
373d3a892b New Comoss island map (#618)
* Create island_new.yml

* first map state
2024-11-30 01:08:44 +03:00
Ed
109edeb4b5 Modular weapon crafting WIP (#611)
* data initalizing

* modular assembling

* grips and blades sprites

* first prototypes

* jewerly decoration

* disassemble modular weapon

* grip start stats

* blade modifiers

* inhand sprites generation

* resprites inhand, add sickle, add attempt modify size

* auto inhand sprite parsing

* icon default parsing

* spear blade

* mace ball

* sword blade

* sharedization + autonetwork hotswipe

* wielding sprite support!

* iron long grip

* wielded sickle, fix ERROR sprite if state not added

* Update grips.yml

* wielded spear + ruby rework

* wielding damage bonus modifier

* modular size fix

* fix storedOffset rotation

* parts offset

* fix inheriting modifiers

* some bugfix and balance tweaks

* DPS Meter

* fix dividing by zero

* rebalance

* replace baseknife to modular knife. Delete ice knife spell

* sickle and mace modular replace

* modular spear & sword replacement. add wielded icons

* Update CP14DPSMeterSystem.cs

* back to serverization

* grip disassemble drop again

* clothing sprite generation code

* back slot long grips and mace

* remove jewerly slot, add more clothing states

* finish clothing states

* shovel modular

* YEEEEE

* anvil modular craft

* bugfixes

* more integration check fixes
2024-11-29 01:31:42 +03:00
758 changed files with 132380 additions and 2604 deletions

View File

@@ -30,7 +30,7 @@ public sealed class ClientClothingSystem : ClothingSystem
/// For some context, im currently refactoring inventory. Part of that is slots not being indexed by a massive enum anymore, but by strings.
/// Problem here: Every rsi-state is using the old enum-names in their state. I already used the new inventoryslots ALOT. tldr: its this or another week of renaming files.
/// </summary>
private static readonly Dictionary<string, string> TemporarySlotMap = new()
public static readonly Dictionary<string, string> TemporarySlotMap = new() //CP14 Public
{
{"head", "HELMET"},
{"eyes", "EYES"},

View File

@@ -113,6 +113,10 @@ namespace Content.Client.Ghost
_actions.RemoveAction(uid, component.ToggleFoVActionEntity);
_actions.RemoveAction(uid, component.ToggleGhostsActionEntity);
_actions.RemoveAction(uid, component.ToggleGhostHearingActionEntity);
//CP14
_actions.RemoveAction(uid, component.CP14ZLevelUpActionEntity);
_actions.RemoveAction(uid, component.CP14ZLevelDownActionEntity);
//CP14 end
if (uid != _playerManager.LocalEntity)
return;

View File

@@ -1,6 +1,6 @@
<widgets:AlertsUI xmlns="https://spacestation14.io"
xmlns:widgets="clr-namespace:Content.Client.UserInterface.Systems.Alerts.Widgets"
MinSize="64 64">
MinSize="96 96">
<PanelContainer HorizontalAlignment="Right" VerticalAlignment="Top">
<BoxContainer Name="AlertContainer" Access="Public" Orientation="Vertical" />
</PanelContainer>

View File

@@ -160,8 +160,9 @@ public sealed class ItemGridPiece : Control, IEntityControl
}
// typically you'd divide by two, but since the textures are half a tile, this is done implicitly
var iconPosition = new Vector2((boundingGrid.Width + 1) * size.X + itemComponent.StoredOffset.X * 2,
(boundingGrid.Height + 1) * size.Y + itemComponent.StoredOffset.Y * 2);
var iconPosition = new Vector2(
(boundingGrid.Width + 1) * size.X + Location.Rotation.RotateVec(itemComponent.StoredOffset).X * 2,
(boundingGrid.Height + 1) * size.Y + Location.Rotation.RotateVec(itemComponent.StoredOffset).Y * 2);
var iconRotation = Location.Rotation + Angle.FromDegrees(itemComponent.StoredRotation);
if (itemComponent.StoredSprite is { } storageSprite)

View File

@@ -0,0 +1,213 @@
using Content.Client.Clothing;
using Content.Shared._CP14.ModularCraft;
using Content.Shared._CP14.ModularCraft.Components;
using Content.Shared.Clothing;
using Content.Shared.Hands;
using Content.Shared.Inventory;
using Content.Shared.Item;
using Content.Shared.Wieldable.Components;
using Robust.Client.GameObjects;
using Robust.Client.ResourceManagement;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations;
namespace Content.Client._CP14.ModularCraft;
public sealed class CP14ClientModularCraftSystem : CP14SharedModularCraftSystem
{
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly IResourceCache _resCache = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14ModularCraftStartPointComponent, AfterAutoHandleStateEvent>(OnAfterHandleState);
SubscribeLocalEvent<CP14ModularCraftStartPointComponent, GetInhandVisualsEvent>(OnGetInhandVisuals);
SubscribeLocalEvent<CP14ModularCraftStartPointComponent, GetEquipmentVisualsEvent>(OnGetEquipmentVisuals);
}
private void OnAfterHandleState(Entity<CP14ModularCraftStartPointComponent> start,
ref AfterAutoHandleStateEvent args)
{
if (!TryComp<SpriteComponent>(start, out var sprite))
return;
UpdateIcon(start, sprite);
}
private void UpdateIcon(Entity<CP14ModularCraftStartPointComponent> start, SpriteComponent? sprite = null)
{
if (!Resolve(start, ref sprite, false))
return;
//Remove old layers
foreach (var key in start.Comp.RevealedLayers)
{
sprite.RemoveLayer(key);
}
start.Comp.RevealedLayers.Clear();
//Add new layers
var counterPart = 0;
foreach (var part in start.Comp.InstalledParts)
{
var indexedPart = _proto.Index(part);
if (indexedPart.IconSprite is null)
{
//Try get default sprite
if (indexedPart.RsiPath is null)
continue;
var state = $"icon";
var rsi = _resCache
.GetResource<RSIResource>(SpriteSpecifierSerializer.TextureRoot / indexedPart.RsiPath)
.RSI;
if (!rsi.TryGetState(state, out _))
continue;
var defaultLayer = new PrototypeLayerData
{
RsiPath = indexedPart.RsiPath,
State = state,
};
var keyCode = $"cp14-modular-icon-layer-{counterPart}-default";
start.Comp.RevealedLayers.Add(keyCode);
var index = sprite.AddLayer(defaultLayer);
sprite.LayerMapSet(keyCode, index);
}
else
{
var counter = 0;
foreach (var layer in indexedPart.IconSprite)
{
var keyCode = $"cp14-modular-icon-layer-{counterPart}-{counter}";
start.Comp.RevealedLayers.Add(keyCode);
var index = sprite.AddLayer(layer);
sprite.LayerMapSet(keyCode, index);
counter++;
}
}
counterPart++;
}
}
private void OnGetInhandVisuals(Entity<CP14ModularCraftStartPointComponent> start, ref GetInhandVisualsEvent args)
{
var defaultKey = $"cp14-modular-inhand-layer-{args.Location.ToString().ToLowerInvariant()}";
if (!TryComp<ItemComponent>(start, out var item))
return;
var wielded = item.HeldPrefix == "wielded"; //SHITCOOOOOOODE
var counterPart = 0;
foreach (var part in start.Comp.InstalledParts)
{
var indexedPart = _proto.Index(part);
var targetLayers =
wielded ? indexedPart.WieldedInhandVisuals : indexedPart.InhandVisuals;
if (targetLayers is not null && targetLayers.TryGetValue(args.Location, out var layers))
{
var i = 0;
foreach (var layer in layers)
{
var key = $"{defaultKey}-{counterPart}-{i}";
args.Layers.Add((key, layer));
i++;
}
}
else
{
//Try get default visuals
if (indexedPart.RsiPath is null)
continue;
var rsi = _resCache
.GetResource<RSIResource>(SpriteSpecifierSerializer.TextureRoot / indexedPart.RsiPath)
.RSI;
var state = $"inhand-{args.Location.ToString().ToLowerInvariant()}";
if (wielded)
state = $"wielded-{state}";
if (!rsi.TryGetState(state, out _))
continue;
var defaultLayer = new PrototypeLayerData
{
RsiPath = indexedPart.RsiPath,
State = state,
};
var key = $"{defaultKey}-{counterPart}-default";
args.Layers.Add((key, defaultLayer));
}
counterPart++;
}
}
private void OnGetEquipmentVisuals(Entity<CP14ModularCraftStartPointComponent> start,
ref GetEquipmentVisualsEvent args)
{
if (!TryComp(args.Equipee, out InventoryComponent? inventory))
return;
var defaultKey = $"cp14-modular-clothing-layer-{args.Slot}";
var counterPart = 0;
foreach (var part in start.Comp.InstalledParts)
{
var indexedPart = _proto.Index(part);
if (indexedPart.ClothingVisuals is not null && indexedPart.ClothingVisuals.TryGetValue(args.Slot, out var layers))
{
var i = 0;
foreach (var layer in layers)
{
var key = $"{defaultKey}-{counterPart}-{i}";
args.Layers.Add((key, layer));
i++;
}
}
else
{
//Try get default sprites
if (indexedPart.RsiPath is null)
continue;
var rsi = _resCache
.GetResource<RSIResource>(SpriteSpecifierSerializer.TextureRoot / indexedPart.RsiPath)
.RSI;
if (!ClientClothingSystem.TemporarySlotMap.TryGetValue(args.Slot, out var correctedSlot))
continue;
var state = $"equipped-{correctedSlot}";
if (!rsi.TryGetState(state, out _))
continue;
var defaultLayer = new PrototypeLayerData
{
RsiPath = indexedPart.RsiPath,
State = state,
};
var key = $"{defaultKey}-{counterPart}-default";
args.Layers.Add((key, defaultLayer));
}
}
}
}

View File

@@ -51,7 +51,7 @@ namespace Content.IntegrationTests.Tests
//CrystallEdge maps
"Village",
"Island",
"Comoss",
//CrystallEdge Map replacement end
};

View File

@@ -448,6 +448,7 @@ namespace Content.Server.Atmos.EntitySystems
if (flammable.FireStacks > 0)
{
/* CP14 Airtight walls should burn too!
var air = _atmosphereSystem.GetContainingMixture(uid);
// If we're in an oxygenless environment, put the fire out.
@@ -456,7 +457,7 @@ namespace Content.Server.Atmos.EntitySystems
Extinguish(uid, flammable);
continue;
}
*/
var source = EnsureComp<IgnitionSourceComponent>(uid);
_ignitionSourceSystem.SetIgnited((uid, source));

View File

@@ -225,6 +225,10 @@ namespace Content.Server.Ghost
_actions.AddAction(uid, ref component.ToggleLightingActionEntity, component.ToggleLightingAction);
_actions.AddAction(uid, ref component.ToggleFoVActionEntity, component.ToggleFoVAction);
_actions.AddAction(uid, ref component.ToggleGhostsActionEntity, component.ToggleGhostsAction);
//CP14
_actions.AddAction(uid, ref component.CP14ZLevelUpActionEntity, component.CP14ZLevelUpAction);
_actions.AddAction(uid, ref component.CP14ZLevelDownActionEntity, component.CP14ZLevelDownAction);
//CP14 end
}
private void OnGhostExamine(EntityUid uid, GhostComponent component, ExaminedEvent args)

View File

@@ -2,7 +2,6 @@ using System.Numerics;
using Content.Server.Shuttles.Components;
using Content.Server.Shuttles.Events;
using Content.Shared._CP14.Cargo;
using Content.Shared._CP14.Cargo.Prototype;
using Robust.Shared.Map;
using Robust.Shared.Random;
@@ -10,10 +9,8 @@ namespace Content.Server._CP14.Cargo;
public sealed partial class CP14CargoSystem
{
private EntityQuery<ArrivalsBlacklistComponent> _blacklistQuery;
private void InitializeShuttle()
{
_blacklistQuery = GetEntityQuery<ArrivalsBlacklistComponent>();
SubscribeLocalEvent<CP14TravelingStoreShipComponent, FTLCompletedEvent>(OnFTLCompleted);
}
@@ -46,11 +43,14 @@ public sealed partial class CP14CargoSystem
private void SendShuttleToStation(EntityUid shuttle, float startupTime = 0f)
{
var targetPoints = new List<EntityUid>();
var targetEnumerator = EntityQueryEnumerator<CP14TravelingStoreShipFTLTargetComponent, TransformComponent>(); //TODO - different method position location
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;
@@ -59,14 +59,23 @@ public sealed partial class CP14CargoSystem
var shuttleComp = Comp<ShuttleComponent>(shuttle);
_shuttles.FTLToCoordinates(shuttle, shuttleComp, targetXform.Coordinates, targetXform.LocalRotation, hyperspaceTime: 5f, startupTime: startupTime);
_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, hyperspaceTime: 5f);
_shuttles.FTLToCoordinates(shuttle,
shuttleComp,
new EntityCoordinates(tradePostMap, Vector2.Zero),
Angle.Zero,
hyperspaceTime: 20f);
}
private void OnFTLCompleted(Entity<CP14TravelingStoreShipComponent> ent, ref FTLCompletedEvent args)
@@ -74,24 +83,24 @@ public sealed partial class CP14CargoSystem
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
if (station.TradePostMap is not null &&
Transform(ent).MapUid == Transform(station.TradePostMap.Value).MapUid) //Landed on tradepost
{
station.OnStation = false;
var b = station.Balance;
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
else //Landed on station
{
station.OnStation = true;
CashOut((ent.Comp.Station, station));
}
UpdateAllStores();
}
}

View File

@@ -1,4 +1,5 @@
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;
@@ -8,8 +9,10 @@ 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 Robust.Server.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
@@ -69,6 +72,18 @@ public sealed partial class CP14CargoSystem : CP14SharedCargoSystem
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))
@@ -85,28 +100,51 @@ public sealed partial class CP14CargoSystem : CP14SharedCargoSystem
var travelingStoreShipComp = EnsureComp<CP14TravelingStoreShipComponent>(station.Comp.Shuttle.Value);
travelingStoreShipComp.Station = station;
var member = EnsureComp<StationMemberComponent>(shuttle);
member.Station = station;
var roundRemover = EnsureComp<CP14RoundRemoveShuttleComponent>(shuttle);
roundRemover.Station = station;
station.Comp.NextTravelTime = _timing.CurTime + TimeSpan.FromSeconds(10f);
AddRoundstartTradingPositions(station);
UpdateStorePositions(station);
}
private void AddRoundstartTradingPositions(Entity<CP14StationTravelingStoreShipTargetComponent> station)
{
if (_buyProto is not null)
{
foreach (var buy in _buyProto)
{
if (buy.RoundstartAvailable)
station.Comp.AvailableBuyPosition.Add(buy);
}
}
if (_sellProto is not null)
{
foreach (var sell in _sellProto)
{
if (sell.RoundstartAvailable)
station.Comp.AvailableSellPosition.Add(sell);
}
}
}
private void UpdateStorePositions(Entity<CP14StationTravelingStoreShipTargetComponent> station)
{
station.Comp.CurrentBuyPositions.Clear();
station.Comp.CurrentSellPositions.Clear();
if (_buyProto is not null)
foreach (var buyPos in station.Comp.AvailableBuyPosition)
{
foreach (var buyPos in _buyProto)
{
station.Comp.CurrentBuyPositions.Add(buyPos, buyPos.Price.Next(_random)/10*10);
}
station.Comp.CurrentBuyPositions.Add(buyPos, buyPos.Price.Next(_random)/10*10);
}
if (_sellProto is not null)
foreach (var sellPos in station.Comp.AvailableSellPosition)
{
foreach (var sellPos in _sellProto)
{
station.Comp.CurrentSellPositions.Add(sellPos, sellPos.Price.Next(_random)/10*10);
}
station.Comp.CurrentSellPositions.Add(sellPos, sellPos.Price.Next(_random)/10*10);
}
}
@@ -222,7 +260,7 @@ public sealed partial class CP14CargoSystem : CP14SharedCargoSystem
foreach (var service in indexedBuyed.Services)
{
service.Buy(EntityManager, station);
service.Buy(EntityManager, _proto, station);
}
}
}
@@ -263,44 +301,10 @@ public sealed partial class CP14CargoSystem : CP14SharedCargoSystem
{
var coord = Transform(moneyBox.Value).Coordinates;
if (station.Comp.Balance > 0)
var coins = _currency.GenerateMoney(station.Comp.Balance, coord);
foreach (var coin in coins)
{
var coins = _currency.GenerateMoney(CP14SharedCurrencySystem.PP.Key, station.Comp.Balance, coord, out var remainder);
station.Comp.Balance = remainder;
foreach (var coin in coins)
{
_storage.Insert(moneyBox.Value, coin, out _);
}
}
if (station.Comp.Balance > 0)
{
var coins = _currency.GenerateMoney(CP14SharedCurrencySystem.GP.Key, station.Comp.Balance, coord, out var remainder);
station.Comp.Balance = remainder;
foreach (var coin in coins)
{
_storage.Insert(moneyBox.Value, coin, out _);
}
}
if (station.Comp.Balance > 0)
{
var coins = _currency.GenerateMoney(CP14SharedCurrencySystem.SP.Key, station.Comp.Balance, coord, out var remainder);
station.Comp.Balance = remainder;
foreach (var coin in coins)
{
_storage.Insert(moneyBox.Value, coin, out _);
}
}
if (station.Comp.Balance > 0)
{
var coins = _currency.GenerateMoney(CP14SharedCurrencySystem.CP.Key, station.Comp.Balance, coord, out var remainder);
station.Comp.Balance = remainder;
foreach (var coin in coins)
{
_storage.Insert(moneyBox.Value, coin, out _);
}
_storage.Insert(moneyBox.Value, coin, out _);
}
}
}

View File

@@ -1,6 +1,6 @@
namespace Content.Server._CP14.Cargo;
[RegisterComponent, Access(typeof(CP14CargoSystem)), AutoGenerateComponentPause]
[RegisterComponent, Access(typeof(CP14CargoSystem))]
public sealed partial class CP14TravelingStoreShipComponent : Component
{
[DataField]

View File

@@ -154,6 +154,56 @@ public sealed partial class CP14CurrencySystem
return spawns;
}
public HashSet<EntityUid> GenerateMoney(
int target,
EntityCoordinates coordinates)
{
HashSet<EntityUid> coins = new();
var balance = target;
//PP
if (balance > 0)
{
var ppCoin = GenerateMoney(PP.Key, balance, coordinates, out var remainder);
balance = remainder;
foreach (var pp in ppCoin)
{
coins.Add(pp);
}
}
//GP
if (balance > 0)
{
var gpCoin = GenerateMoney(GP.Key, balance, coordinates, out var remainder);
balance = remainder;
foreach (var gp in gpCoin)
{
coins.Add(gp);
}
}
//SP
if (balance > 0)
{
var spCoin = GenerateMoney(SP.Key, balance, coordinates, out var remainder);
balance = remainder;
foreach (var sp in spCoin)
{
coins.Add(sp);
}
}
//CP
if (balance > 0)
{
var cpCoin = GenerateMoney(CP.Key, balance, coordinates, out var remainder);
balance = remainder;
foreach (var cp in cpCoin)
{
coins.Add(cp);
}
}
return coins;
}
private bool ProcessEntity(EntityUid ent, ref int remainder, HashSet<EntityUid> spawns)
{
var singleCurrency = GetTotalCurrency(ent);

View File

@@ -0,0 +1,22 @@
using Content.Shared.Damage;
namespace Content.Server._CP14.DPSMeter;
[RegisterComponent]
public sealed partial class CP14DPSMeterComponent : Component
{
[DataField]
public DamageSpecifier TotalDamage = new DamageSpecifier();
[DataField]
public TimeSpan LastHitTime = TimeSpan.Zero;
[DataField]
public TimeSpan StartTrackTime = TimeSpan.Zero;
[DataField]
public TimeSpan EndTrackTime = TimeSpan.Zero;
[DataField]
public TimeSpan TrackTimeAfterHit = TimeSpan.FromSeconds(5f);
}

View File

@@ -0,0 +1,62 @@
using Content.Shared.Damage;
using Content.Shared.FixedPoint;
using Content.Shared.Popups;
using Robust.Shared.Timing;
namespace Content.Server._CP14.DPSMeter;
public sealed class CP14DPSMeterSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14DPSMeterComponent, DamageChangedEvent>(OnDamageChanged);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<CP14DPSMeterComponent>();
while (query.MoveNext(out var uid, out var meter))
{
if (_timing.CurTime < meter.EndTrackTime || meter.EndTrackTime == TimeSpan.Zero)
continue;
//Clear tracking
_popup.PopupEntity($"TOTAL DPS: {GetDPS((uid, meter))}", uid, PopupType.Large);
meter.TotalDamage = new DamageSpecifier();
meter.EndTrackTime = TimeSpan.Zero;
meter.StartTrackTime = TimeSpan.Zero;
}
}
private void OnDamageChanged(Entity<CP14DPSMeterComponent> ent, ref DamageChangedEvent args)
{
if (args.DamageDelta is null)
return;
ent.Comp.TotalDamage += args.DamageDelta;
if (ent.Comp.StartTrackTime == TimeSpan.Zero)
ent.Comp.StartTrackTime = _timing.CurTime;
ent.Comp.LastHitTime = _timing.CurTime;
ent.Comp.EndTrackTime = _timing.CurTime + ent.Comp.TrackTimeAfterHit;
_popup.PopupEntity($"DPS: {GetDPS(ent)}", ent);
}
private FixedPoint2 GetDPS(Entity<CP14DPSMeterComponent> ent)
{
var totalDamage = ent.Comp.TotalDamage.GetTotal();
var totalSeconds = (ent.Comp.LastHitTime - ent.Comp.StartTrackTime).TotalSeconds;
var DPS = totalDamage / Math.Max(totalSeconds, 1f);
return DPS;
}
}

View File

@@ -1,5 +1,4 @@
using Content.Server.Administration;
using Content.Shared._CP14.DayCycle;
using Content.Shared.Administration;
using Robust.Shared.Console;
using CP14DayCycleComponent = Content.Shared._CP14.DayCycle.Components.CP14DayCycleComponent;

View File

@@ -1,3 +1,4 @@
using Content.Server.Body.Systems;
using Content.Shared._CP14.Demiplane.Components;
using Content.Shared.Mobs.Systems;
@@ -9,6 +10,7 @@ public sealed partial class CP14DemiplaneSystem
private TimeSpan _nextCheckTime = TimeSpan.Zero;
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly BodySystem _body = default!;
private void InitStabilization()
{
@@ -49,13 +51,26 @@ public sealed partial class CP14DemiplaneSystem
}
var query2 = EntityQueryEnumerator<CP14DemiplaneComponent, CP14DemiplaneDestroyWithoutStabilizationComponent>();
while (query2.MoveNext(out var uid, out var demiplan, out var stabilization))
while (query2.MoveNext(out var uid, out var demiplane, out var stabilization))
{
if (_timing.CurTime < stabilization.EndProtectionTime)
continue;
if (!stabilizedMaps.Contains(uid))
QueueDel(uid);
DeleteDemiplane((uid, demiplane));
}
}
private void DeleteDemiplane(Entity<CP14DemiplaneComponent> demiplane)
{
var query = EntityQueryEnumerator<CP14DemiplaneStabilizerComponent, TransformComponent>();
while (query.MoveNext(out var uid, out var stabilizer, out var xform))
{
if (TryTeleportOutDemiplane(demiplane, uid))
_body.GibBody(uid);
}
QueueDel(demiplane);
}
}

View File

@@ -44,6 +44,7 @@ public sealed partial class CP14DemiplaneSystem : CP14SharedDemiplaneSystem
UpdateGeneration(frameTime);
UpdateStabilization(frameTime);
}
/// <summary>
/// Teleports the entity inside the demiplane, to one of the random entry points.
/// </summary>

View File

@@ -1,4 +1,5 @@
using Content.Server._CP14.Demiplane;
using Content.Server.Interaction;
using Content.Server.Mind;
using Content.Server.Popups;
using Content.Shared._CP14.Demiplane;
@@ -19,8 +20,8 @@ public sealed partial class CP14DemiplaneTravelingSystem : EntitySystem
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly MindSystem _mind = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly InteractionSystem _interaction = default!;
public override void Initialize()
{
@@ -43,6 +44,7 @@ public sealed partial class CP14DemiplaneTravelingSystem : EntitySystem
passWay.NextTimeTeleport = _timing.CurTime + passWay.Delay;
//Get all teleporting entities
HashSet<EntityUid> teleportedEnts = new();
var nearestEnts = _lookup.GetEntitiesInRange(uid, passWay.Radius);
foreach (var ent in nearestEnts)
@@ -53,6 +55,9 @@ public sealed partial class CP14DemiplaneTravelingSystem : EntitySystem
if (!_mind.TryGetMind(ent, out var mindId, out var mind))
continue;
if (!_interaction.InRangeUnobstructed(ent, uid))
continue;
teleportedEnts.Add(ent);
}
@@ -61,6 +66,7 @@ public sealed partial class CP14DemiplaneTravelingSystem : EntitySystem
teleportedEnts.Remove(_random.Pick(teleportedEnts));
}
//Aaaand teleport it
var map = Transform(uid).MapUid;
if (TryComp<CP14DemiplaneComponent>(map, out var demiplan))
{
@@ -101,7 +107,6 @@ public sealed partial class CP14DemiplaneTravelingSystem : EntitySystem
private void RadiusMapInit(Entity<CP14DemiplaneRadiusTimedPasswayComponent> radiusPassWay, ref MapInitEvent args)
{
radiusPassWay.Comp.NextTimeTeleport = _timing.CurTime + radiusPassWay.Comp.Delay;
//Popup caution here
}
private void OnOpenRiftInteractDoAfter(Entity<CP14DemiplaneRiftOpenedComponent> passWay, ref CP14DemiplanPasswayUseDoAfter args)

View File

@@ -8,7 +8,6 @@ using Content.Shared.Fluids.Components;
using Content.Shared.Interaction;
using Content.Shared.Inventory.Events;
using Content.Shared.Maps;
using Robust.Server.GameObjects;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
@@ -30,8 +29,8 @@ public sealed class CP14FootprintsSystem : EntitySystem
{
base.Initialize();
SubscribeLocalEvent<Components.CP14FootprintTrailerComponent, MoveEvent>(OnTrailerMove);
SubscribeLocalEvent<Components.CP14FootprintTrailerComponent, StartCollideEvent>(OnTrailerCollide);
SubscribeLocalEvent<CP14FootprintTrailerComponent, MoveEvent>(OnTrailerMove);
SubscribeLocalEvent<CP14FootprintTrailerComponent, StartCollideEvent>(OnTrailerCollide);
SubscribeLocalEvent<CP14FootprintHolderComponent, GotEquippedEvent>(OnHolderEquipped);
SubscribeLocalEvent<CP14FootprintHolderComponent, GotUnequippedEvent>(OnHolderUnequipped);
@@ -135,6 +134,9 @@ public sealed class CP14FootprintsSystem : EntitySystem
private void OnTrailerMove(Entity<Components.CP14FootprintTrailerComponent> ent, ref MoveEvent args)
{
//Temporaly disabled
return;
if (ent.Comp.holder is null)
return;
var footprint = ent.Comp.holder;

View File

@@ -0,0 +1,6 @@
namespace Content.Server._CP14.Lighthouse;
[RegisterComponent]
public sealed partial class CP14LighthouseComponent : Component
{
}

View File

@@ -0,0 +1,23 @@
using Robust.Server.GameStates;
namespace Content.Server._CP14.Lighthouse;
public sealed partial class CP14LighthouseSystem : EntitySystem
{
[Dependency] private readonly PvsOverrideSystem _pvs = default!;
public override void Initialize()
{
SubscribeLocalEvent<CP14LighthouseComponent, ComponentStartup>(OnLighthouseStartup);
SubscribeLocalEvent<CP14LighthouseComponent, ComponentShutdown>(OnLighthouseShutdown);
}
private void OnLighthouseShutdown(Entity<CP14LighthouseComponent> ent, ref ComponentShutdown args)
{
_pvs.RemoveGlobalOverride(ent);
}
private void OnLighthouseStartup(Entity<CP14LighthouseComponent> ent, ref ComponentStartup args)
{
_pvs.AddGlobalOverride(ent);
}
}

View File

@@ -0,0 +1,15 @@
using Content.Shared._CP14.LockKey;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.LockKey;
[RegisterComponent]
public sealed partial class CP14AbstractKeyComponent : Component
{
[DataField(required: true)]
public ProtoId<CP14LockGroupPrototype> Group = default;
[DataField]
public bool DeleteOnFailure = true;
}

View File

@@ -0,0 +1,67 @@
using Content.Server.Station.Events;
using Content.Shared._CP14.LockKey;
using Content.Shared._CP14.LockKey.Components;
using Content.Shared.Station.Components;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Utility;
namespace Content.Server._CP14.LockKey;
public sealed partial class CP14KeyDistributionSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly CP14KeyholeGenerationSystem _keyGeneration = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14AbstractKeyComponent, MapInitEvent>(OnMapInit);
}
private void OnMapInit(Entity<CP14AbstractKeyComponent> ent, ref MapInitEvent args)
{
if (!TrySetShape(ent) && ent.Comp.DeleteOnFailure)
QueueDel(ent);
}
private bool TrySetShape(Entity<CP14AbstractKeyComponent> ent)
{
var grid = Transform(ent).GridUid;
if (grid is null)
return false;
if (!TryComp<CP14KeyComponent>(ent, out var key))
return false;
if (!TryComp<StationMemberComponent>(grid.Value, out var member))
return false;
if (!TryComp<CP14StationKeyDistributionComponent>(member.Station, out var distribution))
return false;
var keysList = new List<ProtoId<CP14LockTypePrototype>>(distribution.Keys);
while (keysList.Count > 0)
{
var randomIndex = _random.Next(keysList.Count);
var keyA = keysList[randomIndex];
var indexedKey = _proto.Index(keyA);
if (indexedKey.Group != ent.Comp.Group)
{
keysList.RemoveAt(randomIndex);
continue;
}
_keyGeneration.SetShape((ent, key), indexedKey);
distribution.Keys.Remove(indexedKey);
return true;
}
return false;
}
}

View File

@@ -1,4 +1,5 @@
using System.Linq;
using Content.Server.Labels;
using Content.Shared._CP14.LockKey;
using Content.Shared._CP14.LockKey.Components;
using Content.Shared.Examine;
@@ -12,8 +13,9 @@ public sealed partial class CP14KeyholeGenerationSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly LabelSystem _label = default!;
private Dictionary<ProtoId<CP14LockCategoryPrototype>, List<int>> _roundKeyData = new();
private Dictionary<ProtoId<CP14LockTypePrototype>, List<int>> _roundKeyData = new();
public override void Initialize()
{
@@ -37,7 +39,7 @@ public sealed partial class CP14KeyholeGenerationSystem : EntitySystem
{
if (keyEnt.Comp.AutoGenerateShape != null)
{
keyEnt.Comp.LockShape = GetKeyLockData(keyEnt.Comp.AutoGenerateShape.Value);
SetShape(keyEnt, keyEnt.Comp.AutoGenerateShape.Value);
}
}
@@ -45,7 +47,7 @@ public sealed partial class CP14KeyholeGenerationSystem : EntitySystem
{
if (lockEnt.Comp.AutoGenerateShape != null)
{
lockEnt.Comp.LockShape = GetKeyLockData(lockEnt.Comp.AutoGenerateShape.Value);
SetShape(lockEnt, lockEnt.Comp.AutoGenerateShape.Value);
}
}
#endregion
@@ -69,7 +71,7 @@ public sealed partial class CP14KeyholeGenerationSystem : EntitySystem
args.PushMarkup(markup);
}
private List<int> GetKeyLockData(ProtoId<CP14LockCategoryPrototype> category)
private List<int> GetKeyLockData(ProtoId<CP14LockTypePrototype> category)
{
if (_roundKeyData.ContainsKey(category))
return _roundKeyData[category];
@@ -79,7 +81,25 @@ public sealed partial class CP14KeyholeGenerationSystem : EntitySystem
return newData;
}
private List<int> GenerateNewUniqueLockData(ProtoId<CP14LockCategoryPrototype> category)
public void SetShape(Entity<CP14KeyComponent> keyEnt, ProtoId<CP14LockTypePrototype> type)
{
keyEnt.Comp.LockShape = GetKeyLockData(type);
var indexedType = _proto.Index(type);
if (indexedType.Name is not null)
_label.Label(keyEnt, Loc.GetString(indexedType.Name.Value));
}
public void SetShape(Entity<CP14LockComponent> lockEnt, ProtoId<CP14LockTypePrototype> type)
{
lockEnt.Comp.LockShape = GetKeyLockData(type);
var indexedType = _proto.Index(type);
if (indexedType.Name is not null)
_label.Label(lockEnt, Loc.GetString(indexedType.Name.Value));
}
private List<int> GenerateNewUniqueLockData(ProtoId<CP14LockTypePrototype> category)
{
List<int> newKeyData = new();
var categoryData = _proto.Index(category);

View File

@@ -0,0 +1,175 @@
using Content.Server.Item;
using Content.Shared._CP14.ModularCraft;
using Content.Shared._CP14.ModularCraft.Components;
using Content.Shared._CP14.ModularCraft.Prototypes;
using Content.Shared.Throwing;
using Robust.Server.GameObjects;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
namespace Content.Server._CP14.ModularCraft;
public sealed class CP14ModularCraftSystem : CP14SharedModularCraftSystem
{
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly ThrowingSystem _throwing = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly ItemSystem _item = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14ModularCraftStartPointComponent, MapInitEvent>(OnStartPointMapInit);
SubscribeLocalEvent<CP14ModularCraftStartPointComponent, CP14ModularCraftAddPartDoAfter>(OnAddedPart);
}
private void OnAddedPart(Entity<CP14ModularCraftStartPointComponent> ent, ref CP14ModularCraftAddPartDoAfter args)
{
if (args.Cancelled || args.Handled)
return;
if (!TryComp<CP14ModularCraftPartComponent>(args.Used, out var partComp))
return;
if (!TryAddPartToFirstSlot(ent, (args.Used.Value, partComp)))
return;
//TODO: Sound
args.Handled = true;
}
private void OnStartPointMapInit(Entity<CP14ModularCraftStartPointComponent> ent, ref MapInitEvent args)
{
foreach (var startSlot in ent.Comp.StartSlots)
{
ent.Comp.FreeSlots.Add(startSlot);
}
if (TryComp<CP14ModularCraftAutoAssembleComponent>(ent, out var autoAssemble))
{
foreach (var detail in autoAssemble.Details)
{
TryAddPartToFirstSlot(ent, detail, false); // we want auto assemble when spawned in crates
}
}
}
private bool TryAddPartToFirstSlot(Entity<CP14ModularCraftStartPointComponent> start,
Entity<CP14ModularCraftPartComponent> part)
{
foreach (var partProto in part.Comp.PossibleParts)
{
if (!_proto.TryIndex(partProto, out var partIndexed))
continue;
if (partIndexed.TargetSlot is null)
continue;
if (!start.Comp.FreeSlots.Contains(partIndexed.TargetSlot.Value))
continue;
if (TryAddPartToSlot(start, part, partProto, partIndexed.TargetSlot.Value))
{
QueueDel(part);
return true;
}
}
return false;
}
private bool TryAddPartToFirstSlot(Entity<CP14ModularCraftStartPointComponent> start,
ProtoId<CP14ModularCraftPartPrototype> partProto,
bool blockStorage = true)
{
if (!_proto.TryIndex(partProto, out var partIndexed))
return false;
if (partIndexed.TargetSlot is null)
return false;
if (!start.Comp.FreeSlots.Contains(partIndexed.TargetSlot.Value))
return false;
return TryAddPartToSlot(start, null, partProto, partIndexed.TargetSlot.Value, blockStorage);
}
private bool TryAddPartToSlot(Entity<CP14ModularCraftStartPointComponent> start,
Entity<CP14ModularCraftPartComponent>? part,
ProtoId<CP14ModularCraftPartPrototype> partProto,
ProtoId<CP14ModularCraftSlotPrototype> slot,
bool blockStorage = true)
{
if (!start.Comp.FreeSlots.Contains(slot))
return false;
if (blockStorage)
{
var xform = Transform(start);
if (xform.GridUid != xform.ParentUid)
return false;
}
AddPartToSlot(start, part, partProto, slot);
return true;
}
private void AddPartToSlot(Entity<CP14ModularCraftStartPointComponent> start,
Entity<CP14ModularCraftPartComponent>? part,
ProtoId<CP14ModularCraftPartPrototype> partProto,
ProtoId<CP14ModularCraftSlotPrototype> slot)
{
start.Comp.FreeSlots.Remove(slot);
start.Comp.InstalledParts.Add(partProto);
var indexedPart = _proto.Index(partProto);
foreach (var modifier in indexedPart.Modifiers)
{
modifier.Effect(EntityManager, start, part);
}
_item.VisualsChanged(start);
Dirty(start);
}
public void DisassembleModular(EntityUid target)
{
if (!TryComp<CP14ModularCraftStartPointComponent>(target, out var modular))
return;
var sourceCoord = _transform.GetMapCoordinates(target);
//Spawn start part
if (modular.StartProtoPart is not null)
{
if (_random.Prob(0.5f)) //TODO: Dehardcode
{
var spawned = Spawn(modular.StartProtoPart, sourceCoord);
_throwing.TryThrow(spawned, _random.NextAngle().ToWorldVec(), 1f);
}
}
//Spawn parts
foreach (var part in modular.InstalledParts)
{
if (!_proto.TryIndex(part, out var indexedPart))
continue;
if (_random.Prob(indexedPart.DestroyProb))
continue;
if (indexedPart.SourcePart is null)
continue;
var spawned = Spawn(indexedPart.SourcePart, sourceCoord);
_throwing.TryThrow(spawned, _random.NextAngle().ToWorldVec(), 1f);
}
//Delete
QueueDel(target);
}
}

View File

@@ -0,0 +1,15 @@
using Content.Server.Destructible;
using Content.Server.Destructible.Thresholds.Behaviors;
namespace Content.Server._CP14.ModularCraft;
[Serializable]
[DataDefinition]
public sealed partial class CP14ModularDisassembleBehavior : IThresholdBehavior
{
public void Execute(EntityUid owner, DestructibleSystem system, EntityUid? cause = null)
{
var modular = system.EntityManager.System<CP14ModularCraftSystem>();
modular.DisassembleModular(owner);
}
}

View File

@@ -0,0 +1,20 @@
using Content.Shared._CP14.ModularCraft;
using Content.Shared._CP14.ModularCraft.Components;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.ModularCraft.Modifiers;
public sealed partial class AddComponents : CP14ModularCraftModifier
{
[DataField]
public ComponentRegistry? Components;
[DataField]
public bool Override = false;
public override void Effect(EntityManager entManager, Entity<CP14ModularCraftStartPointComponent> start, Entity<CP14ModularCraftPartComponent>? part)
{
if (Components is not null)
entManager.AddComponents(start, Components, Override);
}
}

View File

@@ -0,0 +1,19 @@
using Content.Shared._CP14.Damageable;
using Content.Shared._CP14.ModularCraft;
using Content.Shared._CP14.ModularCraft.Components;
namespace Content.Server._CP14.ModularCraft.Modifiers;
public sealed partial class EditDamageableModifier : CP14ModularCraftModifier
{
[DataField(required: true)]
public float Multiplier = 1f;
public override void Effect(EntityManager entManager, Entity<CP14ModularCraftStartPointComponent> start, Entity<CP14ModularCraftPartComponent>? part)
{
var damageable = entManager.EnsureComponent<CP14DamageableModifierComponent>(start);
damageable.Modifier *= Multiplier;
entManager.Dirty(start);
}
}

View File

@@ -0,0 +1,28 @@
using Content.Shared._CP14.ModularCraft;
using Content.Shared._CP14.ModularCraft.Components;
using Content.Shared.Damage;
using Content.Shared.Wieldable.Components;
namespace Content.Server._CP14.ModularCraft.Modifiers;
public sealed partial class EditIncreaseDamageOnWield : CP14ModularCraftModifier
{
[DataField]
public DamageSpecifier? BonusDamage;
[DataField]
public float? DamageMultiplier;
public override void Effect(EntityManager entManager, Entity<CP14ModularCraftStartPointComponent> start, Entity<CP14ModularCraftPartComponent>? part)
{
if (!entManager.TryGetComponent<IncreaseDamageOnWieldComponent>(start, out var wield))
return;
if (BonusDamage is not null)
wield.BonusDamage += BonusDamage;
if (DamageMultiplier is not null)
wield.BonusDamage *= DamageMultiplier.Value;
}
}

View File

@@ -0,0 +1,48 @@
using System.Linq;
using Content.Shared._CP14.ModularCraft;
using Content.Shared._CP14.ModularCraft.Components;
using Content.Shared.Item;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.ModularCraft.Modifiers;
public sealed partial class EditItem : CP14ModularCraftModifier
{
[DataField]
public ProtoId<ItemSizePrototype>? NewSize;
/// <summary>
/// Only works if the item has 1 shape. Increases or decreases it size.
/// </summary>
[DataField]
public Vector2i? AdjustShape;
[DataField]
public Vector2i? StoredOffsetBonus;
public override void Effect(EntityManager entManager, Entity<CP14ModularCraftStartPointComponent> start, Entity<CP14ModularCraftPartComponent>? part)
{
if (!entManager.TryGetComponent<ItemComponent>(start, out var itemComp) || itemComp.Shape is null)
return;
var itemSystem = entManager.System<SharedItemSystem>();
if (NewSize is not null)
itemSystem.SetSize(start, NewSize.Value);
var itemShape = itemSystem.GetItemShape((start, itemComp));
if (AdjustShape is not null && itemShape.Count == 1)
{
var box = itemComp.Shape.First();
box.Right += AdjustShape.Value.X;
box.Top += AdjustShape.Value.Y;
itemSystem.SetShape(start, new List<Box2i>{box});
}
if (StoredOffsetBonus is not null)
{
var newOffset = itemComp.StoredOffset + StoredOffsetBonus.Value;
itemSystem.SetStoredOffset(start, newOffset, itemComp);
}
}
}

View File

@@ -0,0 +1,64 @@
using Content.Shared._CP14.ModularCraft;
using Content.Shared._CP14.ModularCraft.Components;
using Content.Shared.Damage;
using Content.Shared.Weapons.Melee;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.ModularCraft.Modifiers;
public sealed partial class EditMeleeWeapon : CP14ModularCraftModifier
{
[DataField]
public EntProtoId? NewAnimation;
[DataField]
public EntProtoId? NewWideAnimation;
[DataField]
public float? AngleMultiplier;
[DataField]
public DamageSpecifier? BonusDamage;
[DataField]
public float? DamageMultiplier;
[DataField]
public float? AttackRateMultiplier;
[DataField]
public float? BonusRange;
[DataField]
public bool? ResetOnHandSelected;
public override void Effect(EntityManager entManager, Entity<CP14ModularCraftStartPointComponent> start, Entity<CP14ModularCraftPartComponent>? part)
{
if (!entManager.TryGetComponent<MeleeWeaponComponent>(start, out var melee))
return;
if (NewAnimation is not null)
melee.Animation = NewAnimation.Value;
if (NewWideAnimation is not null)
melee.WideAnimation = NewWideAnimation.Value;
if (AngleMultiplier is not null)
melee.Angle = Angle.FromDegrees(melee.Angle.Degrees * AngleMultiplier.Value);
if (BonusDamage is not null)
melee.Damage += BonusDamage;
if (DamageMultiplier is not null)
melee.Damage *= DamageMultiplier.Value;
if (AttackRateMultiplier is not null)
melee.AttackRate *= AttackRateMultiplier.Value;
if (BonusRange is not null)
melee.Range += BonusRange.Value;
if (ResetOnHandSelected is not null)
melee.ResetOnHandSelected = ResetOnHandSelected.Value;
}
}

View File

@@ -0,0 +1,25 @@
using Content.Shared._CP14.ModularCraft;
using Content.Shared._CP14.ModularCraft.Components;
using Content.Shared._CP14.ModularCraft.Prototypes;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.ModularCraft.Modifiers;
public sealed partial class EditModularSlots : CP14ModularCraftModifier
{
[DataField]
public HashSet<ProtoId<CP14ModularCraftSlotPrototype>> AddSlots = new();
[DataField]
public HashSet<ProtoId<CP14ModularCraftSlotPrototype>> RemoveSlots = new();
public override void Effect(EntityManager entManager, Entity<CP14ModularCraftStartPointComponent> start, Entity<CP14ModularCraftPartComponent>? part)
{
start.Comp.FreeSlots.AddRange(AddSlots);
foreach (var slot in RemoveSlots)
{
if (start.Comp.FreeSlots.Contains(slot))
start.Comp.FreeSlots.Remove(slot);
}
}
}

View File

@@ -0,0 +1,18 @@
using Content.Shared._CP14.MeleeWeapon.Components;
using Content.Shared._CP14.ModularCraft;
using Content.Shared._CP14.ModularCraft.Components;
namespace Content.Server._CP14.ModularCraft.Modifiers;
public sealed partial class EditSharpened : CP14ModularCraftModifier
{
[DataField]
public float SharpnessDamageMultiplier = 1f;
public override void Effect(EntityManager entManager, Entity<CP14ModularCraftStartPointComponent> start, Entity<CP14ModularCraftPartComponent>? part)
{
if (!entManager.TryGetComponent<CP14SharpenedComponent>(start, out var sharpened))
return;
sharpened.SharpnessDamageBy1Damage *= SharpnessDamageMultiplier;
}
}

View File

@@ -0,0 +1,25 @@
using Content.Shared._CP14.ModularCraft;
using Content.Shared._CP14.ModularCraft.Components;
using Content.Shared._CP14.ModularCraft.Prototypes;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.ModularCraft.Modifiers;
public sealed partial class Inherit : CP14ModularCraftModifier
{
[DataField(required: true)]
public List<ProtoId<CP14ModularCraftPartPrototype>> CopyFrom = new();
public override void Effect(EntityManager entManager, Entity<CP14ModularCraftStartPointComponent> start, Entity<CP14ModularCraftPartComponent>? part)
{
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
foreach (var copy in CopyFrom)
{
foreach (var modifier in prototypeManager.Index(copy).Modifiers)
{
modifier.Effect(entManager, start, part);
}
}
}
}

View File

@@ -1,16 +0,0 @@
using Robust.Shared.Map;
namespace Content.Server._CP14.PortalAutoLink;
/// <summary>
/// allows you to automatically link entities to each other, through key matching searches
/// </summary>
[RegisterComponent, Access(typeof(CP14AutoLinkSystem))]
public sealed partial class CP14AutoLinkComponent : Component
{
/// <summary>
/// a key that is used to search for another autolinked entity installed in the worlds
/// </summary>
[DataField]
public string? AutoLinkKey = "Hello";
}

View File

@@ -1,44 +0,0 @@
using Content.Shared.Interaction;
using Content.Shared.Teleportation.Systems;
namespace Content.Server._CP14.PortalAutoLink;
public sealed partial class CP14AutoLinkSystem : EntitySystem
{
[Dependency] private readonly LinkedEntitySystem _link = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14AutoLinkComponent, MapInitEvent>(OnMapInit);
}
private void OnMapInit(Entity<CP14AutoLinkComponent> autolink, ref MapInitEvent args)
{
TryAutoLink(autolink, out var otherLink);
}
public bool TryAutoLink(Entity<CP14AutoLinkComponent> autolink, out EntityUid? linkedEnt)
{
linkedEnt = null;
var query = EntityQueryEnumerator<CP14AutoLinkComponent>();
while (query.MoveNext(out var uid, out var otherAutolink))
{
if (autolink.Comp == otherAutolink)
continue;
if (autolink.Comp.AutoLinkKey == otherAutolink.AutoLinkKey)
{
if (_link.TryLink(autolink, uid, false))
{
RemComp<CP14AutoLinkComponent>(uid);
RemComp<CP14AutoLinkComponent>(autolink);
return true;
}
}
}
return false;
}
}

View File

@@ -0,0 +1,6 @@
namespace Content.Server._CP14.RoleSalary;
[RegisterComponent, Access(typeof(CP14SalarySystem))]
public sealed partial class CP14SalarySpawnerComponent : Component
{
}

View File

@@ -0,0 +1,123 @@
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;
namespace Content.Server._CP14.RoleSalary;
/// <summary>
/// A system that periodically sends paychecks to certain roles through the cargo ship system
/// </summary>
public sealed partial class CP14SalarySystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly CP14CargoSystem _cargo = default!;
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly PaperSystem _paper = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly CP14CurrencySystem _currency = default!;
[Dependency] private readonly SharedStorageSystem _storage = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14StationSalaryComponent, StationPostInitEvent>(OnStationPostInit);
SubscribeLocalEvent<CP14SalarySpawnerComponent, MapInitEvent>(OnSalaryInit);
}
public override void Update(float frameTime)
{
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});
}
}
private void OnSalaryInit(Entity<CP14SalarySpawnerComponent> ent, ref MapInitEvent args)
{
GenerateSalary(ent);
QueueDel(ent);
}
private void GenerateSalary(Entity<CP14SalarySpawnerComponent> ent)
{
//Hardcode warning! ^-^
var xform = Transform(ent);
//First we need found a station
if (!TryComp<StationMemberComponent>(xform.GridUid, out var member))
return;
if (!TryComp<CP14StationSalaryComponent>(member.Station, out var stationSalaryComponent))
return;
var paper = Spawn("CP14Paper"); //TODO Special named paper
_transform.PlaceNextTo(paper, (ent, xform));
if (TryComp<PaperComponent>(paper, out var paperComp))
{
paperComp.Content = GenerateSalaryText((member.Station, stationSalaryComponent)) ?? "";
_paper.TryStamp((paper, paperComp),
new StampDisplayInfo
{
StampedColor = Color.Red,
StampedName = Loc.GetString("cp14-stamp-salary"),
},
"red_on_paper");
}
var wallet = Spawn("CP14Wallet");
_transform.PlaceNextTo(wallet, (ent, xform));
foreach (var salary in stationSalaryComponent.Salary)
{
var coins = _currency.GenerateMoney(salary.Value, xform.Coordinates);
foreach (var coin in coins)
{
_storage.Insert(wallet, coin, out _);
}
}
}
private string? GenerateSalaryText(Entity<CP14StationSalaryComponent> station)
{
var sb = new StringBuilder();
sb.Append(Loc.GetString("cp14-salary-title") + "\n");
foreach (var salary in station.Comp.Salary)
{
sb.Append("\n");
if (!_proto.TryIndex(salary.Key, out var indexedDep))
continue;
var name = Loc.GetString(indexedDep.Name);
sb.Append(Loc.GetString("cp14-salary-entry",
("dep", name),
("total", _currency.GetCurrencyPrettyString(salary.Value))));
}
return sb.ToString();
}
private void OnStationPostInit(Entity<CP14StationSalaryComponent> ent, ref StationPostInitEvent args)
{
ent.Comp.NextSalaryTime = _timing.CurTime + ent.Comp.SalaryFrequency;
}
}

View File

@@ -0,0 +1,23 @@
using Content.Shared.Roles;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.RoleSalary;
[RegisterComponent, Access(typeof(CP14SalarySystem)), AutoGenerateComponentPause]
public sealed partial class CP14StationSalaryComponent : Component
{
/// <summary>
/// listing all the departments and their salaries
/// </summary>
[DataField]
public Dictionary<ProtoId<DepartmentPrototype>, int> Salary = new();
[DataField, AutoPausedField]
public TimeSpan NextSalaryTime = TimeSpan.Zero;
[DataField]
public TimeSpan SalaryFrequency = TimeSpan.FromMinutes(18);
[DataField]
public EntProtoId SalaryProto = "CP14SalarySpawner";
}

View File

@@ -0,0 +1,8 @@
namespace Content.Server._CP14.RoundRemoveShuttle;
[RegisterComponent]
public sealed partial class CP14RoundRemoveShuttleComponent : Component
{
[DataField]
public EntityUid Station;
}

View File

@@ -0,0 +1,95 @@
using System.Globalization;
using System.Linq;
using Content.Server.Chat.Systems;
using Content.Server.Mind;
using Content.Server.Shuttles.Events;
using Content.Server.Station.Systems;
using Content.Shared.Administration.Logs;
using Content.Shared.Database;
using Content.Shared.IdentityManagement.Components;
using Content.Shared.Mind.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.Roles;
using Content.Shared.Roles.Jobs;
using Robust.Shared.Network;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.RoundRemoveShuttle;
public sealed partial class CP14RoundRemoveShuttleSystem : EntitySystem
{
[Dependency] private readonly ISharedAdminLogManager _adminLog = default!;
[Dependency] private readonly ChatSystem _chatSystem = default!;
[Dependency] private readonly MindSystem _mind = default!;
[Dependency] private readonly StationJobsSystem _stationJobs = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14RoundRemoveShuttleComponent, FTLCompletedEvent>(OnFTLComplete);
}
private void OnFTLComplete(Entity<CP14RoundRemoveShuttleComponent> ent, ref FTLCompletedEvent args)
{
var childrens = Transform(ent).ChildEnumerator;
HashSet<EntityUid> toDelete = new();
while (childrens.MoveNext(out var uid))
{
if (!_mind.TryGetMind(uid, out _, out var mindComp))
continue;
//Trying return all jobs roles
var userId = mindComp.UserId;
ProtoId<JobPrototype>? playerJob = null;
string? jobName = null;
if (userId is not null)
{
RestoreJobs(ent.Comp.Station, userId.Value, out playerJob);
if (_proto.TryIndex(playerJob, out var indexedJob))
{
jobName = Loc.GetString(indexedJob.Name);
}
}
_adminLog.Add(LogType.Action,
LogImpact.High,
$"{ToPrettyString(uid):player} was leave the round on traveling merchant ship");
_chatSystem.DispatchStationAnnouncement(ent.Comp.Station,
Loc.GetString(
_mobState.IsDead(uid) ? "cp14-earlyleave-ship-announcement-dead" : "cp14-earlyleave-ship-announcement",
("character", mindComp.CharacterName ?? "Unknown"),
("job", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(jobName ?? "Unknown"))
),
Loc.GetString("cp14-ship-sender"),
playDefaultSound: false
);
toDelete.Add(uid);
}
while (toDelete.Count > 0)
{
var r = toDelete.First();
toDelete.Remove(r);
QueueDel(r);
}
}
private void RestoreJobs(EntityUid station, NetUserId userId, out ProtoId<JobPrototype>? outJob)
{
outJob = null;
if (!_stationJobs.TryGetPlayerJobs(station, userId, out var jobs))
return;
foreach (var job in jobs)
{
_stationJobs.TryAdjustJobSlot(station, job, 1, clamp: true);
outJob = job;
}
_stationJobs.TryRemovePlayerJobs(station, userId);
}
}

View File

@@ -0,0 +1,94 @@
using System.Linq;
using Content.Server._CP14.ZLevels.Components;
using Content.Server.Administration;
using Content.Shared.Administration;
using Robust.Shared.Console;
using Robust.Shared.Map;
namespace Content.Server._CP14.ZLevels.Commands;
[AdminCommand(AdminFlags.VarEdit)]
public sealed class CP14CombineMapsIntoZLevelsCommand : LocalizedCommands
{
[Dependency] private readonly IEntityManager _entities = default!;
[Dependency] private readonly IMapManager _map = default!;
private const string Name = "cp14-combineMapsIntoZLevels";
public override string Command => Name;
public override string Description => "Connects a number of maps into a common network of z-levels. Does not work if one of the maps is already in the z-level network";
public override string Help => $"{Name} <MapId 1> <MapId 2> ... <MapId X> (from ground to sky)";
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length == 1)
{
shell.WriteError("Not enough maps to form a network of levels");
return;
}
List<MapId> maps = new();
foreach (var arg in args)
{
if (!int.TryParse(arg, out var mapIdInt))
{
shell.WriteError($"Cannot parse `{arg}` into mapId");
return;
}
var mapId = new MapId(mapIdInt);
if (mapId == MapId.Nullspace)
{
shell.WriteError($"Cannot parse NullSpace");
return;
}
if (!_map.MapExists(mapId))
{
shell.WriteError($"Map {mapId} dont exist");
return;
}
//if (!_mapSystem.TryGetMap(mapId, out var mapUid))
//{
// shell.WriteError($"Map {mapId} dont exist");
// return;
//}
if (maps.Contains(mapId))
{
shell.WriteError($"Duplication maps: {mapId}");
return;
}
maps.Add(mapId);
}
//Check maps already in zLevel links
var query = _entities.EntityQueryEnumerator<CP14StationZLevelsComponent>();
while (query.MoveNext(out var uid, out var zLevelComp))
{
foreach (var findMap in maps)
{
if (zLevelComp.LevelEntities.ContainsKey(findMap))
{
shell.WriteError($"{findMap} already in z-level network! Z-Network Entity: {uid}");
return;
}
}
}
//Ok, all check passed, we create new z-level network
var zLevelEnt = _entities.Spawn();
_entities.EnsureComponent<CP14StationZLevelsComponent>(zLevelEnt, out var newZLevelComp);
var count = 0;
foreach (var map in maps)
{
newZLevelComp.LevelEntities.Add(map, count);
count++;
}
shell.WriteLine($"Successfully created z-level network! Z-Network entity: {zLevelEnt}");
}
}

View File

@@ -1,13 +1,14 @@
using Content.Server._CP14.StationDungeonMap.EntitySystems;
using Content.Server._CP14.ZLevels.Commands;
using Content.Server._CP14.ZLevels.EntitySystems;
using Robust.Shared.Map;
using Robust.Shared.Utility;
namespace Content.Server._CP14.StationDungeonMap.Components;
namespace Content.Server._CP14.ZLevels.Components;
/// <summary>
/// Initializes the z-level system by creating a series of linked maps
/// </summary>
[RegisterComponent, Access(typeof(CP14StationZLevelsSystem))]
[RegisterComponent, Access(typeof(CP14StationZLevelsSystem), typeof(CP14CombineMapsIntoZLevelsCommand))]
public sealed partial class CP14StationZLevelsComponent : Component
{
[DataField(required: true)]

View File

@@ -1,7 +1,7 @@
using Content.Server._CP14.StationDungeonMap.EntitySystems;
using Content.Server._CP14.ZLevels.EntitySystems;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.StationDungeonMap.Components;
namespace Content.Server._CP14.ZLevels.Components;
/// <summary>
/// automatically creates a linked portal at a different relative z-level, and then the component is removed

View File

@@ -0,0 +1,41 @@
using System.Numerics;
using Content.Shared._CP14.ZLevel;
using Content.Shared.Ghost;
using Robust.Shared.Map;
namespace Content.Server._CP14.ZLevels.EntitySystems;
public sealed partial class CP14StationZLevelsSystem
{
private void InitActions()
{
SubscribeLocalEvent<GhostComponent, CP14ZLevelActionUp>(OnZLevelUp);
SubscribeLocalEvent<GhostComponent, CP14ZLevelActionDown>(OnZLevelDown);
}
private void OnZLevelDown(Entity<GhostComponent> ent, ref CP14ZLevelActionDown args)
{
ZLevelMove(ent, -1);
}
private void OnZLevelUp(Entity<GhostComponent> ent, ref CP14ZLevelActionUp args)
{
ZLevelMove(ent, 1);
}
private void ZLevelMove(EntityUid ent, int offset)
{
var xform = Transform(ent);
var map = xform.MapUid;
if (map is null)
return;
var targetMap = GetMapOffset(map.Value, offset);
if (targetMap is null)
return;
_transform.SetMapCoordinates(ent, new MapCoordinates(_transform.GetWorldPosition(ent), targetMap.Value));
}
}

View File

@@ -0,0 +1,50 @@
using Content.Server._CP14.ZLevels.Components;
using Content.Server.GameTicking.Events;
using Content.Shared.Teleportation.Systems;
using Robust.Shared.Map;
namespace Content.Server._CP14.ZLevels.EntitySystems;
public sealed partial class CP14StationZLevelsSystem
{
[Dependency] private readonly LinkedEntitySystem _linkedEntity = default!;
private void InitializePortals()
{
SubscribeLocalEvent<RoundStartingEvent>(OnRoundStart);
SubscribeLocalEvent<CP14ZLevelAutoPortalComponent, MapInitEvent>(OnPortalMapInit);
}
private void OnRoundStart(RoundStartingEvent ev)
{
var query = EntityQueryEnumerator<CP14ZLevelAutoPortalComponent>();
while (query.MoveNext(out var uid, out var portal))
{
InitPortal((uid, portal));
}
}
private void OnPortalMapInit(Entity<CP14ZLevelAutoPortalComponent> autoPortal, ref MapInitEvent args)
{
InitPortal(autoPortal);
}
private void InitPortal(Entity<CP14ZLevelAutoPortalComponent> autoPortal)
{
var mapId = Transform(autoPortal).MapUid;
if (mapId is null)
return;
var offsetMap = GetMapOffset(mapId.Value, autoPortal.Comp.ZLevelOffset);
if (offsetMap is null)
return;
var currentWorldPos = _transform.GetWorldPosition(autoPortal);
var targetMapPos = new MapCoordinates(currentWorldPos, offsetMap.Value);
var otherSidePortal = Spawn(autoPortal.Comp.OtherSideProto, targetMapPos);
if (_linkedEntity.TryLink(autoPortal, otherSidePortal, true))
RemComp<CP14ZLevelAutoPortalComponent>(autoPortal);
}
}

View File

@@ -1,17 +1,14 @@
using Content.Server._CP14.StationDungeonMap.Components;
using Content.Server.GameTicking.Events;
using Content.Server._CP14.ZLevels.Components;
using Content.Server.Station.Components;
using Content.Server.Station.Events;
using Content.Server.Station.Systems;
using Content.Shared.Maps;
using Content.Shared.Station.Components;
using Content.Shared.Teleportation.Systems;
using Robust.Server.GameObjects;
using Robust.Server.Maps;
using Robust.Shared.Map;
using Robust.Shared.Random;
namespace Content.Server._CP14.StationDungeonMap.EntitySystems;
namespace Content.Server._CP14.ZLevels.EntitySystems;
public sealed partial class CP14StationZLevelsSystem : EntitySystem
{
@@ -20,29 +17,18 @@ public sealed partial class CP14StationZLevelsSystem : EntitySystem
[Dependency] private readonly MapLoaderSystem _mapLoader = default!;
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly ITileDefinitionManager _tileDefManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly TileSystem _tile = default!;
[Dependency] private readonly SharedMapSystem _maps = default!;
[Dependency] private readonly LinkedEntitySystem _linkedEntity = default!;
public override void Initialize()
{
base.Initialize();
InitializePortals();
InitActions();
SubscribeLocalEvent<CP14ZLevelAutoPortalComponent, MapInitEvent>(OnPortalMapInit);
SubscribeLocalEvent<RoundStartingEvent>(OnRoundStart);
SubscribeLocalEvent<CP14StationZLevelsComponent, StationPostInitEvent>(OnStationPostInit);
}
private void OnRoundStart(RoundStartingEvent ev)
{
var query = EntityQueryEnumerator<CP14ZLevelAutoPortalComponent>();
while (query.MoveNext(out var uid, out var portal))
{
InitPortal((uid, portal));
}
}
private void OnStationPostInit(Entity<CP14StationZLevelsComponent> ent, ref StationPostInitEvent args)
{
if (ent.Comp.Initialized)
@@ -98,35 +84,10 @@ public sealed partial class CP14StationZLevelsSystem : EntitySystem
}
}
private void OnPortalMapInit(Entity<CP14ZLevelAutoPortalComponent> autoPortal, ref MapInitEvent args)
{
InitPortal(autoPortal);
}
private void InitPortal(Entity<CP14ZLevelAutoPortalComponent> autoPortal)
{
var mapId = Transform(autoPortal).MapUid;
if (mapId is null)
return;
var offsetMap = GetMapOffset(mapId.Value, autoPortal.Comp.ZLevelOffset);
if (offsetMap is null)
return;
var currentWorldPos = _transform.GetWorldPosition(autoPortal);
var targetMapPos = new MapCoordinates(currentWorldPos, offsetMap.Value);
var otherSidePortal = Spawn(autoPortal.Comp.OtherSideProto, targetMapPos);
if (_linkedEntity.TryLink(autoPortal, otherSidePortal, true))
RemComp<CP14ZLevelAutoPortalComponent>(autoPortal);
}
public MapId? GetMapOffset(EntityUid mapUid, int offset)
{
var query = EntityQueryEnumerator<CP14StationZLevelsComponent, StationDataComponent>();
while (query.MoveNext(out var uid, out var zLevel, out _))
var query = EntityQueryEnumerator<CP14StationZLevelsComponent>();
while (query.MoveNext(out var uid, out var zLevel))
{
if (!zLevel.LevelEntities.TryGetValue(Transform(mapUid).MapID, out var currentLevel))
continue;

View File

@@ -39,6 +39,20 @@ public sealed partial class GhostComponent : Component
[DataField, AutoNetworkedField]
public EntityUid? BooActionEntity;
//CP14 Ghost abilities
[DataField]
public EntProtoId CP14ZLevelUpAction = "CP14ActionZLevelUp";
[DataField, AutoNetworkedField]
public EntityUid? CP14ZLevelUpActionEntity;
[DataField]
public EntProtoId CP14ZLevelDownAction = "CP14ActionZLevelDown";
[DataField, AutoNetworkedField]
public EntityUid? CP14ZLevelDownActionEntity;
//CP14 Ghost entities end
// End actions
[ViewVariables(VVAccess.ReadWrite), DataField]

View File

@@ -55,6 +55,15 @@ public abstract class SharedItemSystem : EntitySystem
Dirty(uid, component);
}
public void SetStoredOffset(EntityUid uid, Vector2i newOffset, ItemComponent? component = null)
{
if (!Resolve(uid, ref component, false))
return;
component.StoredOffset = newOffset;
Dirty(uid, component);
}
public void SetHeldPrefix(EntityUid uid, string? heldPrefix, bool force = false, ItemComponent? component = null)
{
if (!Resolve(uid, ref component, false))

View File

@@ -18,7 +18,7 @@ public sealed partial class FTLMapComponent : Component
/// What parallax to use for the background, immediately gets deffered to ParallaxComponent.
/// </summary>
[DataField]
public string Parallax = "Sky"; //CP14 parallax replacement
public string Parallax = "CP14Ocean"; //CP14 parallax replacement
/// <summary>
/// CP14 FTL map ambient color

View File

@@ -76,9 +76,12 @@ namespace Content.Shared.Verbs
public static readonly VerbCategory InstrumentStyle =
new("verb-categories-instrument-style", null);
public static readonly VerbCategory Lockpick =
public static readonly VerbCategory CP14LockPick =
new("verb-categories-lock-pick", "/Textures/Interface/VerbIcons/lock.svg.192dpi.png");
public static readonly VerbCategory CP14ModularCraft =
new("verb-categories-modular-craft", "/Textures/Interface/AdminActions/unbolt.png");
public static readonly VerbCategory ChannelSelect = new("verb-categories-channel-select", null);
public static readonly VerbCategory SetSensor = new("verb-categories-set-sensor", null);

View File

@@ -39,7 +39,7 @@ public sealed partial class MeleeWeaponComponent : Component
/// <summary>
/// Starts attack cooldown when equipped if true.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField]
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField] //CP14 AutoNetworked
public bool ResetOnHandSelected = true;
/*

View File

@@ -2,7 +2,7 @@ using Content.Shared.Damage;
namespace Content.Shared.Wieldable.Components;
[RegisterComponent, Access(typeof(WieldableSystem))]
[RegisterComponent/*, Access(typeof(WieldableSystem))*/] //CP14 Public access
public sealed partial class IncreaseDamageOnWieldComponent : Component
{
[DataField("damage", required: true)]

View File

@@ -32,6 +32,21 @@ public sealed partial class CP14StationTravelingStoreShipTargetComponent : Compo
[DataField]
public TimeSpan TradePostWaitTime = TimeSpan.FromMinutes(4);
/// <summary>
/// Available to random selecting and pusharing
/// </summary>
[DataField]
public HashSet<CP14StoreBuyPositionPrototype> AvailableBuyPosition = new();
/// <summary>
/// Available to random selecting and pusharing
/// </summary>
[DataField]
public HashSet<CP14StoreSellPositionPrototype> AvailableSellPosition = new();
/// <summary>
/// Fixed prices and positions of the current flight
/// </summary>
[DataField]
public Dictionary<CP14StoreBuyPositionPrototype, int> CurrentBuyPositions = new(); //Proto, price

View File

@@ -8,7 +8,7 @@ public sealed partial class CP14BuyItemsService : CP14StoreBuyService
[DataField(required: true)]
public Dictionary<EntProtoId, int> Product = new();
public override void Buy(EntityManager entManager, Entity<CP14StationTravelingStoreShipTargetComponent> station)
public override void Buy(EntityManager entManager, IPrototypeManager prototype, Entity<CP14StationTravelingStoreShipTargetComponent> station)
{
foreach (var (protoId, count) in Product)
{
@@ -21,15 +21,6 @@ public sealed partial class CP14BuyItemsService : CP14StoreBuyService
public override string? GetDescription(IPrototypeManager prototype, IEntityManager entSys)
{
var sb = new StringBuilder();
sb.Append(Loc.GetString("cp14-store-service-buy-items") + " \n");
foreach (var (protoId, count) in Product)
{
if (!prototype.TryIndex(protoId, out var indexedProto))
continue;
sb.Append($"{indexedProto.Name} x{count} \n");
}
return sb.ToString();
return null;
}
}

View File

@@ -0,0 +1,76 @@
using System.Text;
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.Cargo.Prototype.BuyServices;
public sealed partial class CP14UnlockPositionsService : CP14StoreBuyService
{
[DataField]
public HashSet<ProtoId<CP14StoreBuyPositionPrototype>> AddBuyPositions = new();
[DataField]
public HashSet<ProtoId<CP14StoreSellPositionPrototype>> AddSellPositions = new();
[DataField]
public HashSet<ProtoId<CP14StoreBuyPositionPrototype>> RemoveBuyPositions = new();
public override void Buy(EntityManager entManager, IPrototypeManager prototype, Entity<CP14StationTravelingStoreShipTargetComponent> station)
{
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);
}
foreach (var sell in AddSellPositions)
{
if (!prototype.TryIndex(sell, out var indexedSell))
continue;
if (station.Comp.AvailableSellPosition.Contains(indexedSell))
continue;
station.Comp.AvailableSellPosition.Add(indexedSell);
}
foreach (var rBuy in RemoveBuyPositions)
{
if (!prototype.TryIndex(rBuy, out var indexedBuy))
continue;
if (!station.Comp.AvailableBuyPosition.Contains(indexedBuy))
continue;
station.Comp.AvailableBuyPosition.Remove(indexedBuy);
}
}
public override string? GetDescription(IPrototypeManager prototype, IEntityManager entSys)
{
var sb = new StringBuilder();
if (AddBuyPositions.Count > 0)
sb.Append(Loc.GetString("cp14-store-service-unlock-buy") + "\n");
foreach (var buy in AddBuyPositions)
{
if (!prototype.TryIndex(buy, out var indexedBuy))
continue;
sb.Append(Loc.GetString(indexedBuy.Name) + "\n");
}
if (AddSellPositions.Count > 0)
sb.Append(Loc.GetString("cp14-store-service-unlock-sell") + "\n");
foreach (var sell in AddSellPositions)
{
if (!prototype.TryIndex(sell, out var indexedSell))
continue;
sb.Append(Loc.GetString("cp14-store-service-unlock-sell") + " " + Loc.GetString(indexedSell.Name) + "\n");
}
return sb.ToString();
}
}

View File

@@ -40,13 +40,16 @@ public sealed partial class CP14StoreBuyPositionPrototype : IPrototype
[DataField(required: true)]
public List<CP14StoreBuyService> Services = new();
[DataField]
public bool RoundstartAvailable = true;
}
[ImplicitDataDefinitionForInheritors]
[MeansImplicitUse]
public abstract partial class CP14StoreBuyService
{
public abstract void Buy(EntityManager entManager, Entity<CP14StationTravelingStoreShipTargetComponent> station);
public abstract void Buy(EntityManager entManager, IPrototypeManager prototype, Entity<CP14StationTravelingStoreShipTargetComponent> station);
public abstract string? GetDescription(IPrototypeManager prototype, IEntityManager entSys);
}

View File

@@ -34,6 +34,9 @@ public sealed partial class CP14StoreSellPositionPrototype : IPrototype
[DataField(required: true)]
public CP14StoreSellService Service = default!;
[DataField]
public bool RoundstartAvailable = true;
}
[ImplicitDataDefinitionForInheritors]

View File

@@ -0,0 +1,14 @@
using Robust.Shared.GameStates;
namespace Content.Shared._CP14.Damageable;
/// <summary>
/// Increases or decreases incoming damage, regardless of the damage type.
/// Unlike standard Damageable modifiers, this value can be changed during the game.
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class CP14DamageableModifierComponent : Component
{
[DataField, AutoNetworkedField]
public float Modifier = 1f;
}

View File

@@ -0,0 +1,18 @@
using Content.Shared.Damage;
namespace Content.Shared._CP14.Damageable;
public sealed class CP14DamageableModifierSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14DamageableModifierComponent, DamageModifyEvent>(OnDamageModify);
}
private void OnDamageModify(Entity<CP14DamageableModifierComponent> ent, ref DamageModifyEvent args)
{
args.Damage *= ent.Comp.Modifier;
}
}

View File

@@ -16,7 +16,7 @@ public sealed partial class CP14DoorInteractionPopupComponent : Component
public string InteractString = "cp14-closed-door-interact-popup";
[DataField("interactSound")]
public SoundSpecifier InteractSound;
public SoundSpecifier? InteractSound;
[ViewVariables(VVAccess.ReadWrite)]
public TimeSpan LastInteractTime = TimeSpan.Zero;

View File

@@ -1,19 +0,0 @@
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.LockKey;
/// <summary>
/// A prototype of the lock category. Need a roundstart mapping to ensure that keys and locks will fit together despite randomization.
/// </summary>
[Prototype("CP14LockCategory")]
public sealed partial class CP14LockCategoryPrototype : IPrototype
{
[ViewVariables]
[IdDataField]
public string ID { get; private set; } = default!;
/// <summary>
/// The number of elements that will be generated for the category.
/// </summary>
[DataField] public int Complexity = 3;
}

View File

@@ -0,0 +1,15 @@
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.LockKey;
/// <summary>
/// Group Affiliation. Used for “abstract key” mechanics,
/// where the key takes one of the free forms from identical rooms (10 different kinds of tavern rooms for example).
/// </summary>
[Prototype("CP14LockGroup")]
public sealed partial class CP14LockGroupPrototype : IPrototype
{
[ViewVariables]
[IdDataField]
public string ID { get; private set; } = default!;
}

View File

@@ -0,0 +1,32 @@
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.LockKey;
/// <summary>
/// A lock or key shape, pre-generated at the start of the round.
/// Allows a group of doors and keys to have the same shape within the same round and fit together,
/// but is randomized from round to round
/// </summary>
[Prototype("CP14LockType")]
public sealed partial class CP14LockTypePrototype : IPrototype
{
[ViewVariables]
[IdDataField]
public string ID { get; private set; } = default!;
/// <summary>
/// The number of elements that will be generated for the category.
/// </summary>
[DataField]
public int Complexity = 3;
/// <summary>
/// Group Affiliation. Used for “abstract key” mechanics,
/// where the key takes one of the free forms from identical rooms (10 different kinds of tavern rooms for example).
/// </summary>
[DataField]
public ProtoId<CP14LockGroupPrototype>? Group;
[DataField]
public LocId? Name;
}

View File

@@ -15,5 +15,5 @@ public sealed partial class CP14KeyComponent : Component
/// If not null, automatically generates a key for the specified category on initialization. This ensures that the lock will be opened with a key of the same category.
/// </summary>
[DataField]
public ProtoId<CP14LockCategoryPrototype>? AutoGenerateShape = null;
public ProtoId<CP14LockTypePrototype>? AutoGenerateShape = null;
}

View File

@@ -5,10 +5,10 @@ namespace Content.Shared._CP14.LockKey.Components;
/// <summary>
/// A component of a lock that stores its keyhole shape, complexity, and current state.
/// </summary>
[RegisterComponent]
[RegisterComponent, AutoGenerateComponentState]
public sealed partial class CP14LockComponent : Component
{
[DataField]
[DataField, AutoNetworkedField]
public List<int>? LockShape = null;
[DataField]
@@ -30,5 +30,5 @@ public sealed partial class CP14LockComponent : Component
/// If not null, automatically generates a lock for the specified category on initialization. This ensures that the lock will be opened with a key of the same category.
/// </summary>
[DataField]
public ProtoId<CP14LockCategoryPrototype>? AutoGenerateShape = null;
public ProtoId<CP14LockTypePrototype>? AutoGenerateShape = null;
}

View File

@@ -0,0 +1,13 @@
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.LockKey.Components;
/// <summary>
///
/// </summary>
[RegisterComponent]
public sealed partial class CP14StationKeyDistributionComponent : Component
{
[DataField]
public List<ProtoId<CP14LockTypePrototype>> Keys = new();
}

View File

@@ -129,7 +129,7 @@ public sealed class SharedCP14LockKeySystem : EntitySystem
},
Text = Loc.GetString("cp14-lock-verb-lock-pick-use-text") + $" {height}",
Message = Loc.GetString("cp14-lock-verb-lock-pick-use-message"),
Category = VerbCategory.Lockpick,
Category = VerbCategory.CP14LockPick,
Priority = height,
CloseMenu = false,
};

View File

@@ -135,7 +135,7 @@ public partial class SharedCP14MagicEnergySystem : EntitySystem
if (ent.Comp.MagicAlert == null)
return;
var level = ContentHelpers.RoundToLevels(MathF.Max(0f, (float) ent.Comp.Energy), (float) ent.Comp.MaxEnergy, 10);
var level = ContentHelpers.RoundToLevels(MathF.Max(0f, (float) ent.Comp.Energy), (float) ent.Comp.MaxEnergy, 6);
_alerts.ShowAlert(ent, ent.Comp.MagicAlert.Value, (short)level);
}
}

View File

@@ -1,16 +1,17 @@
using Content.Shared._CP14.MeleeWeapon.EntitySystems;
using Robust.Shared.GameStates;
namespace Content.Shared._CP14.MeleeWeapon.Components;
/// <summary>
/// allows the object to become blunt with use
/// </summary>
[RegisterComponent, Access(typeof(CP14SharpeningSystem))]
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class CP14SharpenedComponent : Component
{
[DataField]
[DataField, AutoNetworkedField]
public float Sharpness = 1f;
[DataField]
public float SharpnessDamageBy1Damage = 0.002f; //500 damage
public float SharpnessDamageBy1Damage = 0.001f; //1000 damage
}

View File

@@ -2,7 +2,6 @@ using Content.Shared._CP14.MeleeWeapon.Components;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Popups;
using Content.Shared.Throwing;
using Content.Shared.Weapons.Melee;
using Content.Shared.Weapons.Melee.Events;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Random;

View File

@@ -0,0 +1,11 @@
using Content.Shared._CP14.ModularCraft.Components;
using JetBrains.Annotations;
namespace Content.Shared._CP14.ModularCraft;
[ImplicitDataDefinitionForInheritors]
[MeansImplicitUse]
public abstract partial class CP14ModularCraftModifier
{
public abstract void Effect(EntityManager entManager, Entity<CP14ModularCraftStartPointComponent> start, Entity<CP14ModularCraftPartComponent>? part);
}

View File

@@ -0,0 +1,51 @@
using Content.Shared._CP14.ModularCraft.Components;
using Content.Shared.DoAfter;
using Content.Shared.Interaction;
using Robust.Shared.Serialization;
namespace Content.Shared._CP14.ModularCraft;
public abstract class CP14SharedModularCraftSystem : EntitySystem
{
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14ModularCraftPartComponent, AfterInteractEvent>(OnAfterInteractPart);
}
private void OnAfterInteractPart(Entity<CP14ModularCraftPartComponent> start, ref AfterInteractEvent args)
{
if (args.Handled || args.Target is null)
return;
if (!HasComp<CP14ModularCraftStartPointComponent>(args.Target))
return;
var xform = Transform(args.Target.Value);
if (xform.GridUid != xform.ParentUid)
return;
_doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager,
args.User,
start.Comp.DoAfter,
new CP14ModularCraftAddPartDoAfter(),
args.Target,
args.Target,
start)
{
BreakOnDamage = true,
BreakOnMove = true,
BreakOnDropItem = true,
});
args.Handled = true;
}
}
[Serializable, NetSerializable]
public sealed partial class CP14ModularCraftAddPartDoAfter : SimpleDoAfterEvent
{
}

View File

@@ -0,0 +1,14 @@
using Content.Shared._CP14.ModularCraft.Prototypes;
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.ModularCraft.Components;
/// <summary>
/// Adds all details to the item when initializing. This is useful for spawning modular items directly when mapping or as loot in demiplanes.
/// </summary>
[RegisterComponent, Access(typeof(CP14SharedModularCraftSystem))]
public sealed partial class CP14ModularCraftAutoAssembleComponent : Component
{
[DataField]
public List<ProtoId<CP14ModularCraftPartPrototype>> Details = new();
}

View File

@@ -0,0 +1,16 @@
using Content.Shared._CP14.ModularCraft.Prototypes;
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.ModularCraft.Components;
[RegisterComponent, Access(typeof(CP14SharedModularCraftSystem))]
public sealed partial class CP14ModularCraftPartComponent : Component
{
[DataField(required: true)]
public HashSet<ProtoId<CP14ModularCraftPartPrototype>> PossibleParts = new();
[DataField]
public float DoAfter = 1f;
//TODO: Sound
}

View File

@@ -0,0 +1,38 @@
using Content.Shared._CP14.ModularCraft.Prototypes;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.ModularCraft.Components;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
public sealed partial class CP14ModularCraftStartPointComponent : Component
{
/// <summary>
/// Starting free slots
/// </summary>
[DataField]
public List<ProtoId<CP14ModularCraftSlotPrototype>> StartSlots = new();
/// <summary>
/// Current free slots. May vary depending on the modules delivered
/// </summary>
[DataField]
public List<ProtoId<CP14ModularCraftSlotPrototype>> FreeSlots = new();
/// <summary>
/// A list of all installed parts.
/// </summary>
[DataField, AutoNetworkedField]
public List<ProtoId<CP14ModularCraftPartPrototype>> InstalledParts = new();
/// <summary>
/// Spawned on disassembling
/// </summary>
[DataField]
public EntProtoId? StartProtoPart;
/// <summary>
/// Clentside visual layers from installedParts
/// </summary>
public HashSet<string> RevealedLayers = new();
}

View File

@@ -0,0 +1,42 @@
using Content.Shared.Hands.Components;
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.ModularCraft.Prototypes;
[Prototype("modularPart")]
public sealed partial class CP14ModularCraftPartPrototype : IPrototype
{
[IdDataField]
public string ID { get; private set; } = default!;
[DataField]
public ProtoId<CP14ModularCraftSlotPrototype>? TargetSlot;
/// <summary>
/// An entity that can drop out of the final modular item when destroyed.
/// By design, the original item with this prototype from which the weapon was assembled.
/// </summary>
[DataField]
public EntProtoId? SourcePart;
[DataField]
public float DestroyProb = 0.25f;
[DataField(serverOnly: true)]
public List<CP14ModularCraftModifier> Modifiers = new();
[DataField]
public string? RsiPath;
[DataField]
public List<PrototypeLayerData>? IconSprite;
[DataField]
public Dictionary<HandLocation, List<PrototypeLayerData>>? InhandVisuals;
[DataField]
public Dictionary<HandLocation, List<PrototypeLayerData>>? WieldedInhandVisuals;
[DataField]
public Dictionary<string, List<PrototypeLayerData>>? ClothingVisuals;
}

View File

@@ -0,0 +1,13 @@
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.ModularCraft.Prototypes;
[Prototype("modularSlot")]
public sealed partial class CP14ModularCraftSlotPrototype : IPrototype
{
[IdDataField]
public string ID { get; private set; } = default!;
[DataField(required: true)]
public LocId Name = string.Empty;
}

View File

@@ -68,7 +68,7 @@ public abstract partial class CP14SharedFireSpreadSystem : EntitySystem
new CP14IgnitionDoAfter(),
args.Target,
args.Target,
args.Used)
ent)
{
BreakOnDamage = true,
BreakOnMove = true,

View File

@@ -0,0 +1,17 @@
using Content.Shared.Actions;
namespace Content.Shared._CP14.ZLevel;
/// <summary>
/// Should be relayed upon using the action.
/// </summary>
public sealed partial class CP14ZLevelActionUp : InstantActionEvent
{
}
/// <summary>
/// Should be relayed upon using the action.
/// </summary>
public sealed partial class CP14ZLevelActionDown : InstantActionEvent
{
}

View File

@@ -11,6 +11,7 @@ cp14-loadout-general-shoes = Shoes
cp14-loadout-general-back = Back
cp14-loadout-general-trinkets = Trinkets
cp14-loadout-general-spells = Spells
cp14-loadout-general-keys = Keys
# Alchemist
@@ -31,6 +32,7 @@ cp14-loadout-guard-cloak = Guard's cloak
cp14-loadout-guard-head = Guard's head
cp14-loadout-guard-pants = Guard's pants
cp14-loadout-guard-shirt = Guard's shirt
cp14-loadout-guard-spells = Guard's spells
# Bank
@@ -39,4 +41,4 @@ cp14-loadout-commandant-head = Commandant's hat
cp14-loadout-commandant-cloak = Commandant's cloak
cp14-loadout-bank-shirt = Bank Employee shirt
cp14-loadout-bank-pants = Bank Employee pants
cp14-loadout-bank-shoes = Bank Employee shoes
cp14-loadout-bank-shoes = Bank Employee shoes

View File

@@ -0,0 +1,40 @@
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
cp14-lock-shape-tavern-dorm2 = tavern room №2
cp14-lock-shape-tavern-dorm3 = tavern room №3
cp14-lock-shape-tavern-dorm4 = tavern room №4
cp14-lock-shape-tavern-dorm5 = tavern room №5
cp14-lock-shape-alchemist1 = alchemist's lab №1
cp14-lock-shape-alchemist2 = alchemist's lab №2
cp14-lock-shape-blacksmith1 = forge №1
cp14-lock-shape-blacksmith2 = forge №2
cp14-lock-shape-personalhouse1 = house №1
cp14-lock-shape-personalhouse2 = house №2
cp14-lock-shape-personalhouse3 = house №3
cp14-lock-shape-personalhouse4 = house №4
cp14-lock-shape-personalhouse5 = house №5
cp14-lock-shape-personalhouse6 = house №6
cp14-lock-shape-personalhouse7 = house №7
cp14-lock-shape-personalhouse8 = house №8
cp14-lock-shape-personalhouse9 = house №9
cp14-lock-shape-personalhouse10 = house №10
cp14-lock-shape-personalhouse11 = house №11
cp14-lock-shape-personalhouse12 = house №12
cp14-lock-shape-personalhouse13 = house №13
cp14-lock-shape-personalhouse14 = house №14
cp14-lock-shape-personalhouse15 = house №15
cp14-lock-shaper-guard-entrance = barracks, entrance
cp14-lock-shaper-guard-staff = barracks
cp14-lock-shaper-guard-commander = guardhouse
cp14-lock-shaper-guard-weapon-storage = weapons storage

View File

@@ -0,0 +1,3 @@
verb-categories-modular-craft = Forging
cp14-modular-craft-add-part-verb-text = Attach as {$slot}

View File

@@ -0,0 +1,2 @@
cp14-modular-slot-blade = blade
cp14-modular-slot-garde = garde

View File

@@ -0,0 +1,3 @@
cp14-ship-sender = Empire
cp14-earlyleave-ship-announcement = {$character} ({$job}) leaves the settlement on a merchant ship.
cp14-earlyleave-ship-announcement-dead = body {$character} ({$job}) leaves the settlement posthumously on a merchant ship.

View File

@@ -0,0 +1,3 @@
cp14-salary-title = [head=3] Sponsorship order [/head]
cp14-salary-entry = {$dep} receives funding in the amount of {$total}. Give these funds to the department head, he/she has the right to distribute them as he/she sees fit.

View File

@@ -1,3 +1,6 @@
cp14-stamp-salary = Intendant of the Guard
cp14-stamp-denied = Denied
cp14-stamp-approved = Approved
cp14-stamp-bank = Commandant
cp14-stamp-bank = Commandant
cp14-stamp-guard-commander = Guard commander

View File

@@ -65,4 +65,5 @@ cp14-tiles-stonebricks-small-carved1 = carved brick floor
cp14-tiles-stonebricks-small-carved2 = carved brick floor
cp14-tiles-stonebricks-square-carved = carved brick floor
cp14-tiles-stonebricks = stonebrick floor
cp14-tiles-stonebricks-weather = street stonebrick floor
cp14-tiles-stonebricks-marble = marble floor

View File

@@ -6,9 +6,12 @@ cp14-tips-5 = As an alchemist, if you mix some reagents together, you can no lon
cp14-tips-6 = As an alchemist, remember to keep your cauldron off the stove or fire. Your potion may boil over, releasing a reagent cloud.
cp14-tips-7 = You can use shields to parry enemy attacks! Hit the enemy with a shield strike immediately after his attack and you can knock the weapon out of his hands.
cp14-tips-8 = If you run out of magic energy, you can still use spells and spend mana, but it will damage you and potentially render you unconscious!
cp14-tips-9 = There are places in the world with positive or negative magical polarity. In these places, mana regenerates faster, or conversely, can be passively spent. To find such places, use the Aura Scanner.
cp14-tips-9 = Don't go on the demiplanes alone, kids! The demiplanes are designed to be difficult for a group of 4 people.
cp14-tips-10 = Tall bushes are good for hiding your character! But they slow you down a lot and make a lot of noise if you move in them.
cp14-tips-11 = Don't forget to lock your doors if you don't want anyone to get in!
cp14-tips-12 = DEBUG: Be careful with fire! Until we add ways to comfortably put out fires!
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 = To pierce the dish, try combining different ingredients on a plate.
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.

View File

@@ -1,4 +1,7 @@
cp14-store-buy-hint = If you want to buy {$name}, leave your money and order in the trade box: Any paper that says {$code} on it will do.
cp14-store-buy-hint = To purchase "{$name}", leave your money and order in the trade box: Any paper that says {$code} on it will do.
cp14-store-buy-alchemy-unlock-t1-name = Trade Alliance: Alchemists
cp14-store-buy-alchemy-unlock-t1-desc = The Alchemists Guild, in return for an offer of cooperation and small gifts, agrees to provide their trade services to your settlement.
cp14-store-buy-alchemy-normalizer-name = Solution normalizer
cp14-store-buy-alchemy-normalizer-desc = Are your alchemists making poor quality potions? Fix it with a modern technological device made by Dwarf! “Alchemical Normalizer” - will remove any residue from your potions!
@@ -12,5 +15,17 @@ cp14-store-buy-alchemy-bureaucracy-desc = Feather pens, inkwells and a big stack
cp14-store-buy-alchemy-farm-seeds-name = Seeds for farming
cp14-store-buy-alchemy-farm-seeds-desc = A set of different seeds, for farming of all kinds! Don't limit yourself, buy several boxes at once, just in case the farmers eat everything and don't have any food left to process into seeds.
cp14-store-buy-alchemy-demiplan-name = 10 demiplane Keys
cp14-store-buy-alchemy-demiplan-desc = Unstable pocket dimensions where doom or riches may await you? What could be better for your adventurers? Buy from us for a couple of gold pieces - resell to them for more, or bail them out.
cp14-store-buy-alchemy-demiplan-name = 5 demiplane Keys
cp14-store-buy-alchemy-demiplan-desc = Unstable pocket dimensions where doom or riches may await you? What could be better for your adventurers? Buy from us for a couple of gold pieces - resell to them for more, or bail them out.
cp14-store-buy-wood-name = Wood stockpile
cp14-store-buy-wood-desc = Fresh wood delivered to your settlement! Do you live in a land where trees don't grow? Or you just don't have the manpower to go out and chop them yourself? We are ready to do it for you! Or rather, for your money.
cp14-store-buy-fabric-name = Stock of textiles
cp14-store-buy-fabric-desc = Large stock of fabric and strings, for making exquisite outfits or other tools. Today only, now only, last years only.
cp14-store-buy-energy-name = Energy reserve
cp14-store-buy-energy-desc = Energy crystals in both medium and small sizes, and in addition, mana gloves. A complete set to supply your energy devices with energy.
cp14-store-buy-cheese-name = Cheese stockpile
cp14-store-buy-cheese-desc = Cheese. Lots of cheese, in case you don't have cheese.

View File

@@ -10,4 +10,10 @@ cp14-store-sell-copperbar-name = 10 copper bars
cp14-store-sell-copperbar-desc = We're waiting for a description from the lorekeepers.
cp14-store-sell-wheat-name = 10 sheaves of wheat
cp14-store-sell-wheat-desc = Stockpile food for winter for livestock.
cp14-store-sell-wheat-desc = We're waiting for a description from the lorekeepers.
cp14-store-sell-dye-name = 10 dyes
cp14-store-sell-dye-desc = We're waiting for a description from the lorekeepers.
cp14-store-sell-wood-name = 30 wooden planks
cp14-store-sell-wood-desc = We're waiting for a description from the lorekeepers.

View File

@@ -1,7 +1,9 @@
# Buy
cp14-store-service-buy-items = Purchase of goods:
cp14-store-service-unlock-sell = Unlocks the ability to sell:
cp14-store-service-unlock-buy = Unlocks the ability to buy:
# Sell

File diff suppressed because it is too large Load Diff

View File

@@ -11,6 +11,7 @@ cp14-loadout-general-shoes = Обувь
cp14-loadout-general-back = Спина
cp14-loadout-general-trinkets = Безделушки
cp14-loadout-general-spells = Заклинания
cp14-loadout-general-keys = Ключи
# Alchemist
@@ -32,6 +33,7 @@ cp14-loadout-guard-cloak = Накидка стражи
cp14-loadout-guard-head = Шляпа стражи
cp14-loadout-guard-pants = Штаны стражи
cp14-loadout-guard-shirt = Рубашка стражи
cp14-loadout-guard-spells = Заклинания стражи
# Bank
@@ -40,4 +42,4 @@ cp14-loadout-commandant-head = Шляпа коменданта
cp14-loadout-commandant-cloak = Накидка коменданта
cp14-loadout-bank-shirt = Рубашка работника банка
cp14-loadout-bank-pants = Штаны работника банка
cp14-loadout-bank-shoes = Ботинки работника банка
cp14-loadout-bank-shoes = Ботинки работника банка

View File

@@ -0,0 +1,40 @@
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
cp14-lock-shape-tavern-dorm2 = комната таверны №2
cp14-lock-shape-tavern-dorm3 = комната таверны №3
cp14-lock-shape-tavern-dorm4 = комната таверны №4
cp14-lock-shape-tavern-dorm5 = комната таверны №5
cp14-lock-shape-alchemist1 = лаборатория алхимика №1
cp14-lock-shape-alchemist2 = лаборатория алхимика №2
cp14-lock-shape-blacksmith1 = кузня №1
cp14-lock-shape-blacksmith2 = кузня №2
cp14-lock-shape-personalhouse1 = дом №1
cp14-lock-shape-personalhouse2 = дом №2
cp14-lock-shape-personalhouse3 = дом №3
cp14-lock-shape-personalhouse4 = дом №4
cp14-lock-shape-personalhouse5 = дом №5
cp14-lock-shape-personalhouse6 = дом №6
cp14-lock-shape-personalhouse7 = дом №7
cp14-lock-shape-personalhouse8 = дом №8
cp14-lock-shape-personalhouse9 = дом №9
cp14-lock-shape-personalhouse10 = дом №10
cp14-lock-shape-personalhouse11 = дом №11
cp14-lock-shape-personalhouse12 = дом №12
cp14-lock-shape-personalhouse13 = дом №13
cp14-lock-shape-personalhouse14 = дом №14
cp14-lock-shape-personalhouse15 = дом №15
cp14-lock-shaper-guard-entrance = казармы, вход
cp14-lock-shaper-guard-staff = казармы
cp14-lock-shaper-guard-commander = дом главы стражи
cp14-lock-shaper-guard-weapon-storage = хранилище оружия

View File

@@ -0,0 +1,3 @@
verb-categories-modular-craft = Ковка
cp14-modular-craft-add-part-verb-text = Прикрепить как {$slot}

View File

@@ -0,0 +1,2 @@
cp14-modular-slot-blade = лезвие
cp14-modular-slot-garde = гарда

View File

@@ -0,0 +1,3 @@
cp14-ship-sender = Империя
cp14-earlyleave-ship-announcement = {$character} ({$job}) покидает поселение на торговом корабле.
cp14-earlyleave-ship-announcement-dead = тело {$character} ({$job}) посмертно покидает поселение на торговом корабле.

Some files were not shown because too many files have changed in this diff Show More