StoryGeneratorSystem.cs 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. using System.Diagnostics.CodeAnalysis;
  2. using Robust.Shared.Collections;
  3. using Robust.Shared.Prototypes;
  4. using Robust.Shared.Random;
  5. namespace Content.Shared.StoryGen;
  6. /// <summary>
  7. /// Provides functionality to generate a story from a <see cref="StoryTemplatePrototype"/>.
  8. /// </summary>
  9. public sealed partial class StoryGeneratorSystem : EntitySystem
  10. {
  11. [Dependency] private readonly IPrototypeManager _protoMan = default!;
  12. [Dependency] private readonly IRobustRandom _random = default!;
  13. /// <summary>
  14. /// Tries to generate a random story using the given template, picking a random word from the referenced
  15. /// datasets for each variable and passing them into the localization system with template.
  16. /// If <paramref name="seed"/> is specified, the randomizer will be seeded with it for consistent story generation;
  17. /// otherwise the variables will be randomized.
  18. /// Fails if the template prototype cannot be loaded.
  19. /// </summary>
  20. /// <returns>true if the template was loaded, otherwise false.</returns>
  21. public bool TryGenerateStoryFromTemplate(ProtoId<StoryTemplatePrototype> template, [NotNullWhen(true)] out string? story, int? seed = null)
  22. {
  23. // Get the story template prototype from the ID
  24. if (!_protoMan.TryIndex(template, out var templateProto))
  25. {
  26. story = null;
  27. return false;
  28. }
  29. // If given a seed, use it
  30. if (seed != null)
  31. _random.SetSeed(seed.Value);
  32. // Pick values for all of the variables in the template
  33. var variables = new ValueList<(string, object)>(templateProto.Variables.Count);
  34. foreach (var (name, list) in templateProto.Variables)
  35. {
  36. // Get the prototype for the world list dataset
  37. if (!_protoMan.TryIndex(list, out var listProto))
  38. continue; // Missed one, but keep going with the rest of the story
  39. // Pick a random word from the dataset and localize it
  40. var chosenWord = Loc.GetString(_random.Pick(listProto.Values));
  41. variables.Add((name, chosenWord));
  42. }
  43. // Pass the variables to the localization system and build the story
  44. story = Loc.GetString(templateProto.LocId, variables.ToArray());
  45. return true;
  46. }
  47. }