use parts crates for rewards, show rewards in ui (#17374)

Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
deltanedas
2023-06-17 02:00:54 +00:00
committed by GitHub
parent eb114677ad
commit a3c37edd69
11 changed files with 94 additions and 216 deletions

View File

@@ -4,7 +4,6 @@ using Content.Client.Stylesheets;
using Content.Client.UserInterface.Controls;
using Content.Shared.CCVar;
using Content.Shared.Parallax.Biomes;
using Content.Shared.Procedural.Loot;
using Content.Shared.Salvage;
using Content.Shared.Salvage.Expeditions.Modifiers;
using Content.Shared.Shuttles.BUIStates;
@@ -191,29 +190,17 @@ public sealed partial class SalvageExpeditionWindow : FancyWindow,
lBox.AddChild(new Label()
{
Text = Loc.GetString("salvage-expedition-window-loot")
Text = Loc.GetString("salvage-expedition-window-rewards")
});
if (mission.Loot.Count == 0)
// there will always be 3 rewards so no need for 0 check
lBox.AddChild(new Label()
{
lBox.AddChild(new Label()
{
Text = Loc.GetString("salvage-expedition-window-none"),
FontColorOverride = StyleNano.ConcerningOrangeFore,
HorizontalAlignment = HAlignment.Left,
Margin = new Thickness(0f, 0f, 0f, 5f),
});
}
else
{
lBox.AddChild(new Label()
{
Text = string.Join("\n", mission.Loot.Select(o => "- " + _prototype.Index<SalvageLootPrototype>(o.Key).Description + (o.Value > 1 ? $" x {o.Value}" : ""))).TrimEnd(),
FontColorOverride = StyleNano.ConcerningOrangeFore,
HorizontalAlignment = HAlignment.Left,
Margin = new Thickness(0f, 0f, 0f, 5f),
});
}
Text = string.Join("\n", mission.Rewards.Select(id => "- " + _prototype.Index<EntityPrototype>(id).Name)),
FontColorOverride = StyleNano.ConcerningOrangeFore,
HorizontalAlignment = HAlignment.Left,
Margin = new Thickness(0f, 0f, 0f, 5f)
});
// Claim
var claimButton = new Button()

View File

@@ -1,8 +1,10 @@
using Content.Shared.Random;
using Content.Shared.Salvage;
using Robust.Shared.Audio;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
namespace Content.Server.Salvage.Expeditions;
@@ -56,6 +58,12 @@ public sealed class SalvageExpeditionComponent : Component
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("difficulty")]
public DifficultyRating Difficulty;
/// <summary>
/// List of items to order on mission completion
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("rewards", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
public List<string> Rewards = default!;
}
public enum ExpeditionStage : byte

View File

@@ -286,42 +286,12 @@ public sealed partial class SalvageSystem
return;
}
var ids = RewardsForDifficulty(comp.Difficulty);
foreach (var id in ids)
foreach (var reward in comp.Rewards)
{
// pick a random reward to give
var rewards = _prototypeManager.Index<WeightedRandomPrototype>(id);
var reward = rewards.Pick(_random);
var sender = Loc.GetString("cargo-gift-default-sender");
var desc = Loc.GetString("salvage-expedition-reward-description");
var dest = Loc.GetString("cargo-gift-default-dest");
_cargo.AddAndApproveOrder(cargoDb, reward, 0, 1, sender, desc, dest);
}
}
/// <summary>
/// Get a list of WeightedRandomPrototype IDs with the rewards for a certain difficulty.
/// </summary>
private string[] RewardsForDifficulty(DifficultyRating rating)
{
var common = "SalvageRewardCommon";
var rare = "SalvageRewardRare";
var epic = "SalvageRewardEpic";
switch (rating)
{
case DifficultyRating.Minimal:
return new string[] { common, common, common };
case DifficultyRating.Minor:
return new string[] { common, common, rare };
case DifficultyRating.Moderate:
return new string[] { common, rare, rare };
case DifficultyRating.Hazardous:
return new string[] { rare, rare, epic };
case DifficultyRating.Extreme:
return new string[] { rare, epic, epic };
default:
throw new NotImplementedException();
}
}
}

View File

@@ -135,6 +135,7 @@ public sealed class SpawnSalvageMissionJob : Job<bool>
expedition.EndTime = _timing.CurTime + mission.Duration;
expedition.MissionParams = _missionParams;
expedition.Difficulty = _missionParams.Difficulty;
expedition.Rewards = mission.Rewards;
// Don't want consoles to have the incorrect name until refreshed.
var ftlUid = _entManager.CreateEntityUninitialized("FTLPoint", new EntityCoordinates(mapUid, Vector2.Zero));
@@ -216,14 +217,6 @@ public sealed class SpawnSalvageMissionJob : Job<bool>
await SpawnDungeonLoot(dungeon, lootProto, mapUid, grid, random, reservedTiles);
}
foreach (var (loot, count) in mission.Loot)
{
for (var i = 0; i < count; i++)
{
var lootProto = _prototypeManager.Index<SalvageLootPrototype>(loot);
await SpawnDungeonLoot(dungeon, lootProto, mapUid, grid, random, reservedTiles);
}
}
return true;
}
@@ -251,62 +244,10 @@ public sealed class SpawnSalvageMissionJob : Job<bool>
}
}
break;
// Spawns a cluster (like an ore vein) nearby.
case DungeonClusterLoot clusterLoot:
await SpawnDungeonClusterLoot(dungeon!, clusterLoot, grid, random, reservedTiles);
break;
}
}
}
#region Loot
private async Task SpawnDungeonClusterLoot(
Dungeon dungeon,
DungeonClusterLoot loot,
MapGridComponent grid,
Random random,
List<Vector2i> reservedTiles)
{
var spawnTiles = new HashSet<Vector2i>();
for (var i = 0; i < loot.Points; i++)
{
var room = dungeon.Rooms[random.Next(dungeon.Rooms.Count)];
var clusterAmount = loot.ClusterAmount;
var spots = room.Tiles.ToList();
random.Shuffle(spots);
foreach (var spot in spots)
{
if (reservedTiles.Contains(spot))
continue;
var anchored = grid.GetAnchoredEntitiesEnumerator(spot);
if (anchored.MoveNext(out _))
{
continue;
}
clusterAmount--;
spawnTiles.Add(spot);
if (clusterAmount == 0)
break;
}
}
foreach (var tile in spawnTiles)
{
await SuspendIfOutOfTime();
var proto = _prototypeManager.Index<WeightedRandomPrototype>(loot.Prototype).Pick(random);
_entManager.SpawnEntity(proto, grid.GridTileToLocal(tile));
}
}
#endregion
#region Mission Specific
private async Task SetupMining(

View File

@@ -1,24 +0,0 @@
using Content.Shared.Random;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.Procedural.Loot;
/// <summary>
/// Spawns loot at points in the specified area inside of a dungeon room.
/// </summary>
public sealed class DungeonClusterLoot : IDungeonLoot
{
/// <summary>
/// Spawns in a cluster.
/// </summary>
[DataField("clusterAmount")]
public int ClusterAmount = 1;
/// <summary>
/// Number of clusters to spawn.
/// </summary>
[DataField("clusters")] public int Points = 1;
[DataField("lootTable", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<WeightedRandomPrototype>))]
public string Prototype { get; } = string.Empty;
}

View File

@@ -103,7 +103,7 @@ public sealed record SalvageMission(
string Air,
Color? Color,
TimeSpan Duration,
Dictionary<string, int> Loot,
List<string> Rewards,
List<string> Modifiers)
{
/// <summary>
@@ -151,7 +151,10 @@ public sealed record SalvageMission(
/// </summary>
public TimeSpan Duration = Duration;
public Dictionary<string, int> Loot = Loot;
/// <summary>
/// The list of items to order on mission completion.
/// </summary>
public List<string> Rewards = Rewards;
/// <summary>
/// Modifiers (outside of the above) applied to the mission.

View File

@@ -1,6 +1,5 @@
using System.Linq;
using Content.Shared.Dataset;
using Content.Shared.Procedural.Loot;
using Content.Shared.Random;
using Content.Shared.Random.Helpers;
using Content.Shared.Salvage.Expeditions;
@@ -124,8 +123,8 @@ public abstract class SharedSalvageSystem : EntitySystem
mods.Add(time.Description);
}
var loots = GetLoot(config, _proto.EnumeratePrototypes<SalvageLootPrototype>().Where(o => !o.Guaranteed).ToList(), GetDifficulty(difficulty), seed);
return new SalvageMission(seed, difficulty, dungeon.ID, faction.ID, config, biome.ID, air.ID, light.Color, duration, loots, mods);
var rewards = GetRewards(difficulty, rand);
return new SalvageMission(seed, difficulty, dungeon.ID, faction.ID, config, biome.ID, air.ID, light.Color, duration, rewards, mods);
}
// TODO: probably worth putting the biome whitelist thing in a common thing then having a getmod overload for it
@@ -208,28 +207,43 @@ public abstract class SharedSalvageSystem : EntitySystem
throw new InvalidOperationException();
}
private Dictionary<string, int> GetLoot(SalvageMissionType mission, List<SalvageLootPrototype> loots, int count, int seed)
private List<string> GetRewards(DifficultyRating difficulty, System.Random rand)
{
var results = new Dictionary<string, int>();
var adjustedSeed = new System.Random(seed + 2);
for (var i = 0; i < count; i++)
var rewards = new List<string>(3);
var ids = RewardsForDifficulty(difficulty);
foreach (var id in ids)
{
adjustedSeed.Shuffle(loots);
foreach (var loot in loots)
{
if (loot.Blacklist.Contains(mission))
continue;
var weh = results.GetOrNew(loot.ID);
weh++;
results[loot.ID] = weh;
break;
}
// pick a random reward to give
var weights = _proto.Index<WeightedRandomPrototype>(id);
rewards.Add(weights.Pick(rand));
}
return results;
return rewards;
}
/// <summary>
/// Get a list of WeightedRandomPrototype IDs with the rewards for a certain difficulty.
/// </summary>
private string[] RewardsForDifficulty(DifficultyRating rating)
{
var common = "SalvageRewardCommon";
var rare = "SalvageRewardRare";
var epic = "SalvageRewardEpic";
switch (rating)
{
case DifficultyRating.Minimal:
return new string[] { common, common, common };
case DifficultyRating.Minor:
return new string[] { common, common, rare };
case DifficultyRating.Moderate:
return new string[] { common, rare, rare };
case DifficultyRating.Hazardous:
return new string[] { rare, rare, epic };
case DifficultyRating.Extreme:
return new string[] { rare, epic, epic };
default:
throw new NotImplementedException();
}
}
}

View File

@@ -13,8 +13,7 @@ salvage-expedition-window-hostiles = Hostiles:
salvage-expedition-window-duration = Duration:
salvage-expedition-window-biome = Biome:
salvage-expedition-window-modifiers = Modifiers:
salvage-expedition-window-loot = Loot:
salvage-expedition-window-none = N/A
salvage-expedition-window-rewards = Rewards:
salvage-expedition-window-claimed = Claimed
salvage-expedition-window-claim = Claim

View File

@@ -114,3 +114,35 @@
- id: WeaponRevolverMateba
prob: 0.0001
- type: entity
parent: CrateGenericSteel
id: CratePartsT3
name: tier 3 parts crate
description: Contains 5 random tier 3 parts for upgrading machines.
components:
- type: StorageFill
contents:
- id: SalvagePartsT3Spawner
amount: 5
- type: entity
parent: CrateGenericSteel
id: CratePartsT3T4
name: tier 3/4 parts crate
description: Contains 5 random tier 3 or 4 parts for upgrading machines.
components:
- type: StorageFill
contents:
- id: SalvagePartsT3T4Spawner
amount: 5
- type: entity
parent: CrateGenericSteel
id: CratePartsT4
name: tier 4 parts crate
description: Contains 5 random tier 4 parts for upgrading machines.
components:
- type: StorageFill
contents:
- id: SalvagePartsT4Spawner
amount: 5

View File

@@ -1,55 +1,3 @@
# Loot tables
#- type: weightedRandom
# id: SalvageLowValue
# weights:
# Common
# CrateSalvageAssortedGoodies: 1.0
# Uncommon
# TODO:
# Rare
- type: weightedRandom
id: SalvageHighValue
weights:
# Common
CrateMaterialPlasteel: 1.0
CrateMaterialWood: 1.0
CrateMaterialPlastic: 1.0
CrateSalvageEquipment: 1.0
CrateMaterialSteel: 1.0
CrateMaterialGlass: 1.0
# Uncommon
SuperCapacitorStockPart: 0.25
PicoManipulatorStockPart: 0.25
SuperMatterBinStockPart: 0.25
# Rare
QuadraticCapacitorStockPart: 0.10
FemtoManipulatorStockPart: 0.10
BluespaceMatterBinStockPart: 0.10
# Crates
#- type: salvageLoot
# id: LowValue
# desc: Commodities
# blacklist:
# - Mining
# loots:
# - !type:DungeonClusterLoot
# lootTable: SalvageLowValue
# clusters: 3
# clusterAmount: 3
- type: salvageLoot
id: HighValue
desc: High-value commodities
blacklist:
- Mining
loots:
- !type:DungeonClusterLoot
lootTable: SalvageHighValue
clusters: 5
clusterAmount: 1
# Ores
# - Low value
- type: salvageLoot

View File

@@ -25,8 +25,8 @@
IngotSilver: 1.0
SheetPlasma: 1.0
SheetUranium: 1.0
SalvagePartsT3Spawner: 1.0
SalvagePartsT3T4Spawner: 1.0
CratePartsT3: 1.0
CratePartsT3T4: 0.5
# things the expedition team might want
CrateEmergencyBruteKit: 0.5
CrateMedicalSupplies: 0.5
@@ -48,7 +48,7 @@
# rare machinery
SecurityTechFabCircuitboard: 1.0
ResearchAndDevelopmentServerMachineCircuitboard: 1.0
SalvagePartsT4Spawner: 1.0
CratePartsT4: 1.0
# rare weapons
WeaponAdvancedLaser: 1.0
WeaponLaserCannon: 1.0