Client LuaCsForBarotrauma
BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs
2 using Microsoft.Xna.Framework;
3 using System;
4 using System.Collections.Generic;
5 using System.Collections.Immutable;
6 using System.Linq;
7 using System.Xml.Linq;
8 
9 namespace Barotrauma
10 {
11  public class AutonomousObjective
12  {
13  public readonly Identifier Identifier;
14  public readonly Identifier Option;
15  public readonly float PriorityModifier;
19  public readonly bool IgnoreAtOutpost;
23  public readonly bool IgnoreAtNonOutpost;
24 
25  public AutonomousObjective(XElement element)
26  {
27  Identifier = element.GetAttributeIdentifier("identifier", Identifier.Empty);
28 
29  //backwards compatibility
30  if (Identifier == Identifier.Empty)
31  {
32  Identifier = element.GetAttributeIdentifier("aitag", Identifier.Empty);
33  }
34 
35  Option = element.GetAttributeIdentifier("option", Identifier.Empty);
36  PriorityModifier = element.GetAttributeFloat("prioritymodifier", 1);
37  PriorityModifier = MathHelper.Max(PriorityModifier, 0);
38  IgnoreAtOutpost = element.GetAttributeBool("ignoreatoutpost", false);
39  IgnoreAtNonOutpost = element.GetAttributeBool("ignoreatnonoutpost", false);
40  }
41  }
42 
44  {
46 
47  public readonly float Priority;
48 
49  public ItemRepairPriority(XElement element, JobsFile file) : base(file, element.GetAttributeIdentifier("tag", Identifier.Empty))
50  {
51  Priority = element.GetAttributeFloat("priority", -1f);
52  if (Priority < 0)
53  {
54  DebugConsole.AddWarning($"The 'priority' attribute is missing from the the item repair priorities definition in {element} of {file.Path}.",
56  }
57  }
58 
59  public override void Dispose() { }
60  }
61 
62  internal class JobVariant
63  {
64  public JobPrefab Prefab;
65  public int Variant;
66  public JobVariant(JobPrefab prefab, int variant)
67  {
68  Prefab = prefab;
69  Variant = variant;
70  }
71  }
72 
74  {
76 
77  public override void Dispose() { }
78 
79  private static readonly Dictionary<Identifier, float> _itemRepairPriorities = new Dictionary<Identifier, float>();
83  public static IReadOnlyDictionary<Identifier, float> ItemRepairPriorities => _itemRepairPriorities;
84 
85  public static JobPrefab Get(Identifier identifier)
86  {
87  if (Prefabs.ContainsKey(identifier))
88  {
89  return Prefabs[identifier];
90  }
91  else
92  {
93  DebugConsole.ThrowError("Couldn't find a job prefab with the given identifier: " + identifier);
94  return null;
95  }
96  }
97 
98  public class PreviewItem
99  {
100  public readonly Identifier ItemIdentifier;
101  public readonly bool ShowPreview;
102 
103  public PreviewItem(Identifier itemIdentifier, bool showPreview)
104  {
105  ItemIdentifier = itemIdentifier;
106  ShowPreview = showPreview;
107  }
108  }
109 
110  public readonly Dictionary<int, ContentXElement> ItemSets = new Dictionary<int, ContentXElement>();
111  public readonly ImmutableDictionary<int, ImmutableArray<PreviewItem>> PreviewItems;
112  public readonly List<SkillPrefab> Skills = new List<SkillPrefab>();
113  public readonly List<AutonomousObjective> AutonomousObjectives = new List<AutonomousObjective>();
114  public readonly List<Identifier> AppropriateOrders = new List<Identifier>();
115 
116  [Serialize("1,1,1,1", IsPropertySaveable.No)]
117  public Color UIColor
118  {
119  get;
120  private set;
121  }
122 
123  public readonly LocalizedString Name;
124 
125  [Serialize(AIObjectiveIdle.BehaviorType.Passive, IsPropertySaveable.No, description: "How should the character behave when idling (not doing any particular task)?")]
127  {
128  get;
129  private set;
130  }
131 
132  public readonly LocalizedString Description;
133 
134  [Serialize(false, IsPropertySaveable.No, description: "Can the character speak any random lines, or just ones specifically meant for the job?")]
136  {
137  get;
138  private set;
139  }
140 
141  [Serialize(0, IsPropertySaveable.No, description: "The number of these characters in the crew the player starts with in the single player campaign.")]
142  public int InitialCount
143  {
144  get;
145  private set;
146  }
147 
148  [Serialize(false, IsPropertySaveable.No, description: "If set to true, a client that has chosen this as their preferred job will get it regardless of the maximum number or the amount of spawnpoints in the sub.")]
149  public bool AllowAlways
150  {
151  get;
152  private set;
153  }
154 
155  [Serialize(100, IsPropertySaveable.No, description: "How many crew members can have the job (e.g. only one captain etc).")]
156  public int MaxNumber
157  {
158  get;
159  private set;
160  }
161 
162  [Serialize(0, IsPropertySaveable.No, description: "How many crew members are required to have the job. I.e. if one captain is required, one captain is chosen even if all the players have set captain to lowest preference.")]
163  public int MinNumber
164  {
165  get;
166  private set;
167  }
168 
169  [Serialize(0.0f, IsPropertySaveable.No, description: "Minimum amount of karma a player must have to get assigned this job.")]
170  public float MinKarma
171  {
172  get;
173  private set;
174  }
175 
176  [Serialize(1.0f, IsPropertySaveable.No, description: "Multiplier on the base hiring cost when hiring the character from an outpost.")]
177  public float PriceMultiplier
178  {
179  get;
180  private set;
181  }
182 
183  [Serialize(0.0f, IsPropertySaveable.No, description: "How much the vitality of the character is increased/reduced from the default value (e.g. 10 = 110 total vitality if the default vitality is 100.).")]
184  public float VitalityModifier
185  {
186  get;
187  private set;
188  }
189 
190  [Serialize(false, IsPropertySaveable.No, description: "Hidden jobs are not selectable by players, but can be used by e.g. outpost NPCs.")]
191  public bool HiddenJob
192  {
193  get;
194  private set;
195  }
196 
197  public Sprite Icon;
199 
200  public SkillPrefab PrimarySkill => Skills?.FirstOrDefault(s => s.IsPrimarySkill);
201 
202  public ContentXElement Element { get; private set; }
203 
204  public int Variants { get; private set; }
205 
206  public JobPrefab(ContentXElement element, JobsFile file) : base(file, element.GetAttributeIdentifier("identifier", ""))
207  {
209 
210  Name = TextManager.Get("JobName." + Identifier);
211  Description = TextManager.Get("JobDescription." + Identifier);
212  Element = element;
213 
214  var previewItems = new Dictionary<int, List<PreviewItem>>();
215 
216  int variant = 0;
217  foreach (var subElement in element.Elements())
218  {
219  switch (subElement.Name.ToString().ToLowerInvariant())
220  {
221  case "itemset":
222  ItemSets.Add(variant, subElement);
223  previewItems[variant] = new List<PreviewItem>();
224  loadItemIdentifiers(subElement, variant);
225  variant++;
226  break;
227  case "skills":
228  foreach (var skillElement in subElement.Elements())
229  {
230  Skills.Add(new SkillPrefab(skillElement));
231  }
232  break;
233  case "autonomousobjectives":
234  subElement.Elements().ForEach(order => AutonomousObjectives.Add(new AutonomousObjective(order)));
235  break;
236  case "appropriateobjectives":
237  case "appropriateorders":
238  subElement.Elements().ForEach(order => AppropriateOrders.Add(order.GetAttributeIdentifier("identifier", "")));
239  break;
240  case "jobicon":
241  Icon = new Sprite(subElement.FirstElement());
242  break;
243  case "jobiconsmall":
244  IconSmall = new Sprite(subElement.FirstElement());
245  break;
246  }
247  }
248 
249  void loadItemIdentifiers(XElement parentElement, int variant)
250  {
251  foreach (XElement itemElement in parentElement.GetChildElements("Item"))
252  {
253  if (itemElement.Element("name") != null)
254  {
255  DebugConsole.ThrowErrorLocalized("Error in job config \"" + Name + "\" - use identifiers instead of names to configure the items.");
256  continue;
257  }
258 
259  Identifier itemIdentifier = itemElement.GetAttributeIdentifier("identifier", Identifier.Empty);
260  if (itemIdentifier.IsEmpty)
261  {
262  DebugConsole.ThrowErrorLocalized("Error in job config \"" + Name + "\" - item with no identifier.");
263  }
264  else
265  {
266  previewItems[variant].Add(new PreviewItem(itemIdentifier, itemElement.GetAttributeBool("showpreview", true)));
267  }
268  loadItemIdentifiers(itemElement, variant);
269  }
270  }
271 
272  PreviewItems = previewItems.Select(kvp => (kvp.Key, kvp.Value.ToImmutableArray()))
273  .ToImmutableDictionary();
274 
275  Variants = variant;
276 
277  Skills.Sort((x,y) => y.LevelRange.Start.CompareTo(x.LevelRange.Start));
278  }
279 
280  public static JobPrefab Random(Rand.RandSync sync, Func<JobPrefab, bool> predicate = null) => Prefabs.GetRandom(p => !p.HiddenJob && (predicate == null || predicate(p)), sync);
281  }
282 }
readonly bool IgnoreAtNonOutpost
The order is ignored in "normal" non-outpost levels
readonly bool IgnoreAtOutpost
The order is ignored in outpost levels. Doesn't apply to outpost NPCs.
static readonly PrefabCollection< ItemRepairPriority > Prefabs
readonly Dictionary< int, ContentXElement > ItemSets
readonly List< AutonomousObjective > AutonomousObjectives
static IReadOnlyDictionary< Identifier, float > ItemRepairPriorities
Tag -> priority.
static JobPrefab Random(Rand.RandSync sync, Func< JobPrefab, bool > predicate=null)
static readonly PrefabCollection< JobPrefab > Prefabs
readonly ImmutableDictionary< int, ImmutableArray< PreviewItem > > PreviewItems
readonly Identifier Identifier
Definition: Prefab.cs:34
Prefab that has a property serves as a deterministic hash of a prefab's identifier....
static Dictionary< Identifier, SerializableProperty > DeserializeProperties(object obj, XElement element=null)