Skip to content

Commit 4ae82ec

Browse files
Tech disk resprite and pricing changes (space-wizards#37719)
* init new disks are in. can be spawned or printed. no weights or correctly bound techs yet. * tweak textures and naming * make tech disks respect their tier and discipline * make tech console respect tier weight * yml fixes (forgo a million things) * meow :3 reworked to use GenericVisualizer * moved staticPrice comp to shared to support different pricing per tier * unhardcoded prices; tweaked log messages * cleanup * a few fixes * updated pricing to match weights * lowering prices I forgor how many of them science can print * what * t3 texture, logger, factory * move PriceCalculationEvent & EstimatedPriceCalculationEvent to shared * remove static price comp; use EntProtoId for disk proto * moved staticPrice comp back to server * cleanup: price event, visualizer enums & yml * ummove PriceCalculationEvent * ummove PriceCalculationEvent attempt #2 * more unmoving * fixes * predict onExamine * review changes * small cleanup --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
1 parent f63d2fd commit 4ae82ec

10 files changed

Lines changed: 244 additions & 28 deletions

File tree

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using Robust.Shared.Audio;
22
using Robust.Shared.Prototypes;
3-
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
43

54
namespace Content.Server.Research.TechnologyDisk.Components;
65

@@ -10,24 +9,24 @@ public sealed partial class DiskConsoleComponent : Component
109
/// <summary>
1110
/// How much it costs to print a disk
1211
/// </summary>
13-
[DataField("pricePerDisk"), ViewVariables(VVAccess.ReadWrite)]
12+
[DataField]
1413
public int PricePerDisk = 1000;
1514

1615
/// <summary>
1716
/// The prototype of what's being printed
1817
/// </summary>
19-
[DataField("diskPrototype", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>)), ViewVariables(VVAccess.ReadWrite)]
20-
public string DiskPrototype = "TechnologyDisk";
18+
[DataField]
19+
public EntProtoId DiskPrototype = "TechnologyDisk";
2120

2221
/// <summary>
2322
/// How long it takes to print <see cref="DiskPrototype"/>
2423
/// </summary>
25-
[DataField("printDuration"), ViewVariables(VVAccess.ReadWrite)]
24+
[DataField]
2625
public TimeSpan PrintDuration = TimeSpan.FromSeconds(1);
2726

2827
/// <summary>
2928
/// The sound made when printing occurs
3029
/// </summary>
31-
[DataField("printSound")]
30+
[DataField]
3231
public SoundSpecifier PrintSound = new SoundPathSpecifier("/Audio/Machines/printer.ogg");
3332
}

Content.Shared/Research/TechnologyDisk/Components/TechnologyDiskComponent.cs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,38 @@ namespace Content.Shared.Research.TechnologyDisk.Components;
99
[AutoGenerateComponentState]
1010
public sealed partial class TechnologyDiskComponent : Component
1111
{
12+
/// <summary>
13+
/// A discipline to constrain the disk to.
14+
/// </summary>
15+
[DataField, AutoNetworkedField]
16+
public ProtoId<TechDisciplinePrototype>? Discipline;
17+
18+
/// <summary>
19+
/// A tier to constrain the disk to.
20+
/// </summary>
21+
[DataField, AutoNetworkedField]
22+
public int? Tier;
23+
1224
/// <summary>
1325
/// The recipe that will be added. If null, one will be randomly generated
1426
/// </summary>
15-
[DataField]
16-
[AutoNetworkedField]
27+
[DataField, AutoNetworkedField]
1728
public List<ProtoId<LatheRecipePrototype>>? Recipes;
1829

1930
/// <summary>
2031
/// A weighted random prototype for how rare each tier should be.
2132
/// </summary>
2233
[DataField]
2334
public ProtoId<WeightedRandomPrototype> TierWeightPrototype = "TechDiskTierWeights";
35+
36+
/// <summary>
37+
/// Mapping of disk tiers to disk prices.
38+
/// </summary>
39+
[DataField]
40+
public Dictionary<int, int> DiskPricePerTier = new()
41+
{
42+
[1] = 100,
43+
[2] = 500,
44+
[3] = 1500
45+
};
2446
}

Content.Shared/Research/TechnologyDisk/Systems/TechnologyDiskSystem.cs

Lines changed: 106 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using Content.Shared.Cargo;
12
using Content.Shared.Examine;
23
using Content.Shared.Interaction;
34
using Content.Shared.Lathe;
@@ -8,9 +9,9 @@
89
using Content.Shared.Research.Prototypes;
910
using Content.Shared.Research.Systems;
1011
using Content.Shared.Research.TechnologyDisk.Components;
11-
using Robust.Shared.Network;
1212
using Robust.Shared.Prototypes;
1313
using Robust.Shared.Random;
14+
using Robust.Shared.Serialization;
1415

1516
namespace Content.Shared.Research.TechnologyDisk.Systems;
1617

@@ -21,6 +22,7 @@ public sealed class TechnologyDiskSystem : EntitySystem
2122
[Dependency] private readonly SharedPopupSystem _popup = default!;
2223
[Dependency] private readonly SharedResearchSystem _research = default!;
2324
[Dependency] private readonly SharedLatheSystem _lathe = default!;
25+
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
2426
[Dependency] private readonly NameModifierSystem _nameModifier = default!;
2527

2628
public override void Initialize()
@@ -30,37 +32,98 @@ public override void Initialize()
3032
SubscribeLocalEvent<TechnologyDiskComponent, MapInitEvent>(OnMapInit);
3133
SubscribeLocalEvent<TechnologyDiskComponent, AfterInteractEvent>(OnAfterInteract);
3234
SubscribeLocalEvent<TechnologyDiskComponent, ExaminedEvent>(OnExamine);
35+
SubscribeLocalEvent<TechnologyDiskComponent, PriceCalculationEvent>(OnPriceCalculation);
3336
SubscribeLocalEvent<TechnologyDiskComponent, RefreshNameModifiersEvent>(OnRefreshNameModifiers);
3437
}
3538

3639
private void OnMapInit(Entity<TechnologyDiskComponent> ent, ref MapInitEvent args)
40+
{
41+
TryPickAndSetRecipe(ent);
42+
TrySetVisuals(ent);
43+
}
44+
45+
/// <summary>
46+
/// Attempts to pick and set a random recipe as the chosen one.
47+
/// If the disk already has recipes, does nothing.
48+
/// </summary>
49+
private void TryPickAndSetRecipe(Entity<TechnologyDiskComponent> ent)
3750
{
3851
if (ent.Comp.Recipes != null)
3952
return;
4053

41-
var weightedRandom = _protoMan.Index(ent.Comp.TierWeightPrototype);
42-
var tier = int.Parse(weightedRandom.Pick(_random));
54+
int tier;
55+
if (ent.Comp.Tier.HasValue)
56+
{
57+
tier = ent.Comp.Tier.Value;
58+
}
59+
else
60+
{
61+
var weightedRandom = _protoMan.Index(ent.Comp.TierWeightPrototype);
62+
tier = int.Parse(weightedRandom.Pick(_random));
63+
ent.Comp.Tier = tier;
64+
}
4365

44-
//get a list of every distinct recipe in all the technologies.
45-
var techs = new HashSet<ProtoId<LatheRecipePrototype>>();
66+
// get a list of every distinct recipe in all the technologies.
67+
var bundles = new HashSet<(ProtoId<LatheRecipePrototype> recipe, ProtoId<TechDisciplinePrototype> discipline)>();
4668
foreach (var tech in _protoMan.EnumeratePrototypes<TechnologyPrototype>())
4769
{
4870
if (tech.Tier != tier)
4971
continue;
72+
if (ent.Comp.Discipline != null && tech.Discipline != ent.Comp.Discipline.Value)
73+
continue;
5074

51-
techs.UnionWith(tech.RecipeUnlocks);
75+
foreach (var recipe in tech.RecipeUnlocks)
76+
{
77+
bundles.Add((recipe, tech.Discipline));
78+
}
5279
}
5380

54-
if (techs.Count == 0)
81+
if (bundles.Count == 0)
82+
{
83+
Log.Error($"Failed to pick recipe for a tech disk: no suitable recipes were found");
5584
return;
85+
}
5686

57-
//pick one
87+
// pick one
88+
var bundle = _random.Pick(bundles);
89+
ent.Comp.Discipline = bundle.discipline;
5890
ent.Comp.Recipes = [];
59-
ent.Comp.Recipes.Add(_random.Pick(techs));
91+
ent.Comp.Recipes.Add(bundle.recipe);
6092
Dirty(ent);
6193
_nameModifier.RefreshNameModifiers(ent.Owner);
6294
}
6395

96+
/// <summary>
97+
/// Attempts to set tier and discipline visuals based on chosen tier and discipline.
98+
/// </summary>
99+
private void TrySetVisuals(Entity<TechnologyDiskComponent> ent)
100+
{
101+
TrySetTierVisuals(ent);
102+
TrySetDisciplineVisuals(ent);
103+
}
104+
105+
/// <summary>
106+
/// Attempts to set tier visuals based on chosen tier.
107+
/// </summary>
108+
private void TrySetTierVisuals(Entity<TechnologyDiskComponent> ent)
109+
{
110+
if (ent.Comp.Tier is not { } tier)
111+
return;
112+
113+
_appearance.SetData(ent.Owner, TechDiskVisuals.Tier, tier);
114+
}
115+
116+
/// <summary>
117+
/// Attempts to set discipline visuals based on chosen discipline.
118+
/// </summary>
119+
private void TrySetDisciplineVisuals(Entity<TechnologyDiskComponent> ent)
120+
{
121+
if (!_protoMan.Resolve(ent.Comp.Discipline, out var discipline))
122+
return;
123+
124+
_appearance.SetData(ent.Owner, TechDiskVisuals.Discipline, discipline.ID);
125+
}
126+
64127
private void OnAfterInteract(Entity<TechnologyDiskComponent> ent, ref AfterInteractEvent args)
65128
{
66129
if (args.Handled || !args.CanReach || args.Target is not { } target)
@@ -83,6 +146,21 @@ private void OnAfterInteract(Entity<TechnologyDiskComponent> ent, ref AfterInter
83146

84147
private void OnExamine(Entity<TechnologyDiskComponent> ent, ref ExaminedEvent args)
85148
{
149+
if (ent.Comp is { Tier: not null, Discipline: not null }
150+
&& _protoMan.Resolve(ent.Comp.Discipline, out var disciplineProto))
151+
{
152+
var desc = Loc.GetString("tech-disk-examine-desc",
153+
("tier", ent.Comp.Tier),
154+
("branch", Loc.GetString(disciplineProto.Name))
155+
);
156+
157+
args.PushMarkup(desc);
158+
}
159+
else
160+
{
161+
args.PushMarkup(Loc.GetString("tech-disk-examine-desc-unknown"));
162+
}
163+
86164
var message = Loc.GetString("tech-disk-examine-none");
87165
if (ent.Comp.Recipes != null && ent.Comp.Recipes.Count > 0)
88166
{
@@ -95,6 +173,18 @@ private void OnExamine(Entity<TechnologyDiskComponent> ent, ref ExaminedEvent ar
95173
args.PushMarkup(message);
96174
}
97175

176+
private void OnPriceCalculation(Entity<TechnologyDiskComponent> ent, ref PriceCalculationEvent args)
177+
{
178+
if (ent.Comp.Tier is not { } tier)
179+
return;
180+
181+
if (!ent.Comp.DiskPricePerTier.TryGetValue(tier, out var price))
182+
return;
183+
184+
args.Price = price;
185+
args.Handled = true;
186+
}
187+
98188
private void OnRefreshNameModifiers(Entity<TechnologyDiskComponent> entity, ref RefreshNameModifiersEvent args)
99189
{
100190
if (entity.Comp.Recipes != null)
@@ -107,3 +197,10 @@ private void OnRefreshNameModifiers(Entity<TechnologyDiskComponent> entity, ref
107197
}
108198
}
109199
}
200+
201+
[Serializable, NetSerializable]
202+
public enum TechDiskVisuals : byte
203+
{
204+
Tier,
205+
Discipline
206+
}

Resources/Locale/en-US/research/components/technology-disk.ftl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
tech-disk-inserted = You insert the disk, adding a new recipe to the server.
22
tech-disk-examine-none = The label is blank.
3-
tech-disk-examine = The label has a small dot matrix printed image depicting a {$result}.
3+
tech-disk-examine = The label has a small dot matrix printed image depicting a [bold]{$result}[/bold].
44
tech-disk-examine-more = There are more images printed, but they're too small to discern.
5+
tech-disk-examine-desc = [color=lightGray]A disk for the R&D server containing a [bold]Tier {$tier} {$branch}[/bold] branch research technology.[/color]
6+
tech-disk-examine-desc-unknown = [color=lightGray]A disk for the R&D server containing research technology.[/color]
57
tech-disk-name-format = {$baseName} ({$technology})
68
79
tech-disk-ui-name = technology disk terminal

Resources/Prototypes/Entities/Objects/Specific/Research/disk.yml

Lines changed: 93 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,107 @@
4545
parent: BaseItem
4646
id: TechnologyDisk
4747
name: technology disk
48-
description: A disk for the R&D server containing research technology.
4948
components:
5049
- type: Sprite
5150
sprite: Objects/Misc/module.rsi
5251
layers:
5352
- state: datadisk_base
54-
map: ["enum.DamageStateVisualLayers.Base"]
53+
map: [ "base" ]
5554
- state: datadisk_label
56-
- type: RandomSprite
57-
available:
58-
- enum.DamageStateVisualLayers.Base:
59-
datadisk_base: Sixteen
60-
- type: TechnologyDisk
61-
- type: StaticPrice
62-
price: 100
55+
- state: datadisk_t2_marks
56+
shader: unshaded
57+
map: [ "t2_marks" ]
58+
visible: false
59+
- state: datadisk_t2_border
60+
map: [ "t2_border" ]
61+
visible: false
62+
- state: datadisk_t3_marks
63+
map: [ "t3_marks" ]
64+
shader: unshaded
65+
visible: false
66+
- state: datadisk_t3_border
67+
map: [ "t3_border" ]
68+
visible: false
69+
- type: Appearance
70+
- type: GenericVisualizer
71+
visuals:
72+
enum.TechDiskVisuals.Discipline:
73+
base:
74+
Industrial: { color: "#eeac34" }
75+
Arsenal: { color: "#dc373b" }
76+
Experimental: { color: "#9a6ef0" }
77+
CivilianServices: { color: "#7ecd48" }
78+
79+
enum.TechDiskVisuals.Tier:
80+
t2_marks:
81+
2: { visible: true }
82+
t2_border:
83+
2: { visible: true }
84+
t3_marks:
85+
3: { visible: true }
86+
t3_border:
87+
3: { visible: true }
6388
- type: StealTarget
6489
stealGroup: TechnologyDisk
90+
- type: TechnologyDisk
91+
92+
# random tech disks by tier
93+
- type: entity
94+
parent: TechnologyDisk
95+
id: TechnologyDiskT1
96+
suffix: Tier 1
97+
components:
98+
- type: TechnologyDisk
99+
tier: 1
100+
101+
- type: entity
102+
parent: TechnologyDisk
103+
id: TechnologyDiskT2
104+
suffix: Tier 2
105+
components:
106+
- type: TechnologyDisk
107+
tier: 2
108+
109+
- type: entity
110+
parent: TechnologyDisk
111+
id: TechnologyDiskT3
112+
suffix: Tier 3
113+
components:
114+
- type: TechnologyDisk
115+
tier: 3
116+
117+
# random tech disks by discipline
118+
- type: entity
119+
parent: TechnologyDisk
120+
id: TechnologyDiskIndustrial
121+
suffix: Industrial
122+
components:
123+
- type: TechnologyDisk
124+
discipline: Industrial
125+
126+
- type: entity
127+
parent: TechnologyDisk
128+
id: TechnologyDiskArsenal
129+
suffix: Arsenal
130+
components:
131+
- type: TechnologyDisk
132+
discipline: Arsenal
133+
134+
- type: entity
135+
parent: TechnologyDisk
136+
id: TechnologyDiskExperimental
137+
suffix: Experimental
138+
components:
139+
- type: TechnologyDisk
140+
discipline: Experimental
141+
142+
- type: entity
143+
parent: TechnologyDisk
144+
id: TechnologyDiskCivilianServices
145+
suffix: Civilian Services
146+
components:
147+
- type: TechnologyDisk
148+
discipline: CivilianServices
65149

66150
- type: entity
67151
parent: TechnologyDisk
108 Bytes
Loading
111 Bytes
Loading
168 Bytes
Loading
115 Bytes
Loading

0 commit comments

Comments
 (0)