Dayz Build 1.29.163047, Scripts Rev. 123548
Dayz Code Explorer by Zeroy
Loading...
Searching...
No Matches
cfgplayerspawnhandler.c
Go to the documentation of this file.
2{
3 private static bool m_Initialized;
4 static ref PlayerSpawnJsonData m_Data = new PlayerSpawnJsonData();
5
6 static bool LoadData()
7 {
9 if (!spawnGearPresetFiles || (spawnGearPresetFiles && spawnGearPresetFiles.Count() == 0))
10 return false;
11
12 m_Data.presets = {};
13
14 foreach (string spawnPresetFile : spawnGearPresetFiles)
15 {
16 PlayerSpawnPreset preset;
17 string path = "$mission:" + spawnPresetFile;
18
19 string errorMessage;
20 if (!JsonFileLoader<PlayerSpawnPreset>.LoadFile(path, preset, errorMessage))
21 {
22 ErrorEx(errorMessage);
23 return false;
24 }
25
26 if (preset != null)
27 m_Data.presets.Insert(preset);
28 }
29
30 m_Initialized = m_Data.presets.Count() > 0;
31
32 return true;
33 }
34
35 static bool IsInitialized()
36 {
37 return m_Initialized;
38 }
39
41 {
42 array<int> weightedPresetIndexes = new array<int>();
43 int count = m_Data.presets.Count();
45 for (int i = 0; i < count; i++)
46 {
47 p = m_Data.presets[i];
48 if (p.IsValid())
49 {
50 for (int j = 0; j < p.spawnWeight; j++)
51 {
52 weightedPresetIndexes.Insert(i);
53 }
54 }
55 }
56
57 return m_Data.presets.Get(weightedPresetIndexes.GetRandomElement());
58 }
59
61 {
62 foreach (PlayerSpawnPreset preset : m_Data.presets)
63 {
64 if (preset.IsValid() && preset.name == presetName)
65 return preset;
66 }
67
68 return null;
69 }
70
73 {
74 if (data.IsValid())
75 {
76 ProcessSlotsEquipment(player, data);
77 ProcessCargoEquipment(player, data);
78 }
79
80 return true;
81 }
82
84 private static void ProcessSlotsEquipment(PlayerBase player, PlayerSpawnPreset data)
85 {
87 {
88 Debug.Log("No non-empty 'attachmentSlotItemSets' array found. Skipping slot spawns","n/a","n/a","ProcessSlotsEquipment");
89 return;
90 }
91
92 foreach (PlayerSpawnPresetSlotData slotData : data.attachmentSlotItemSets)
93 {
94 SelectAndSpawnSlotEquipment(player,slotData);
95 }
96 }
97
99 private static bool SelectAndSpawnSlotEquipment(PlayerBase player, PlayerSpawnPresetSlotData slotData)
100 {
101 int slotID;
102 if (!slotData.TranslateAndValidateSlot(player,slotID))
103 return false;
104
105 if (!slotData.IsValid())
106 return false;
107
108 array<int> weightedDiscreteSetIndexes = new array<int>();
109 int count = slotData.discreteItemSets.Count();
111 for (int i = 0; i < count; i++)
112 {
113 dis = slotData.discreteItemSets[i];
114
115 if (dis.IsValid()) //only when the type exists and spawnWeight is set
116 {
117 for (int j = 0; j < dis.spawnWeight; j++)
118 {
119 weightedDiscreteSetIndexes.Insert(i);
120 }
121 }
122 }
123
124 dis = null;
125 if (weightedDiscreteSetIndexes.Count() > 0)
126 dis = slotData.discreteItemSets.Get(weightedDiscreteSetIndexes.GetRandomElement());
127 return SpawnDiscreteSlotItemSet(player,dis,slotID);
128 }
129
131 private static void ProcessCargoEquipment(PlayerBase player, PlayerSpawnPreset data)
132 {
134 {
135 Debug.Log("No non-empty 'discreteUnsortedItemSets' array found. Skipping cargo spawns","n/a","n/a","ProcessCargoEquipment");
136 return;
137 }
138
139 SelectAndSpawnCargoSet(player,data);
140 }
141
142 private static bool SelectAndSpawnCargoSet(PlayerBase player, PlayerSpawnPreset data)
143 {
144 array<int> weightedDiscreteSetIndexes = new array<int>();
145 int count = data.discreteUnsortedItemSets.Count();
146 PlayerSpawnPresetDiscreteCargoSetData csd;
147 for (int i = 0; i < count; i++)
148 {
149 csd = data.discreteUnsortedItemSets[i];
150
151 if (csd.IsValid()) //only when the spawnWeight is set
152 {
153 for (int j = 0; j < csd.spawnWeight; j++)
154 {
155 weightedDiscreteSetIndexes.Insert(i);
156 }
157 }
158 }
159
160 csd = null;
161 if (weightedDiscreteSetIndexes.Count() > 0)
162 csd = data.discreteUnsortedItemSets.Get(weightedDiscreteSetIndexes.GetRandomElement());
163 return SpawnDiscreteCargoItemSet(player,csd);
164 }
165
166 private static bool SpawnDiscreteCargoItemSet(PlayerBase player, PlayerSpawnPresetDiscreteCargoSetData csd)
167 {
168 SpawnComplexChildrenItems(player,csd);
169 SpawnSimpleChildrenItems(player,csd);
170 return true;
171 }
172
174 {
175 if (!dis)
176 {
177 Debug.Log("No PlayerSpawnPresetDiscreteItemSet found. Skipping spawn for slot: " + InventorySlots.GetSlotName(slotID),"n/a","n/a","SpawnDiscreteSlotItemSet");
178 return false;
179 }
180
181 ItemBase item;
182 if (slotID == InventorySlots.HANDS) //hands exception
183 item = ItemBase.Cast(player.GetHumanInventory().CreateInHands(dis.itemType));
184 else
185 item = ItemBase.Cast(player.GetInventory().CreateAttachmentEx(dis.itemType,slotID));
186
187 if (item)
188 {
189 HandleNewItem(item,dis);
190 }
191 else if (dis.itemType != string.Empty)
192 {
193 Debug.Log("FAILED spawning item type: " + dis.itemType + " into slot: " + InventorySlots.GetSlotName(slotID) + " of parent: " + player,"n/a","n/a","SpawnDiscreteSlotItemSet");
194 return false;
195 }
196
197 return item != null;
198 }
199
201 private static bool SpawnComplexChildrenItems(EntityAI parent, notnull PlayerSpawnPresetItemSetBase data)
202 {
203 if (!data.complexChildrenTypes || data.complexChildrenTypes.Count() < 1) //no children defined, still valid!
204 {
205 return false;
206 }
207
209 {
210 if (cct.itemType == string.Empty)
211 {
212 Debug.Log("Empty item type found in 'complexChildrenTypes' of parent : " + parent,"n/a","n/a","SpawnSimpleChildrenItems");
213 continue;
214 }
215
216 ItemBase item;
217 Class.CastTo(item,CreateChildItem(parent,cct.itemType));
218
219 if (item)
220 {
221 HandleNewItem(item,cct);
222 }
223 else
224 {
225 Weapon_Base wep;
226 if (!Class.CastTo(wep,parent) || !IsWeaponAndMagazineType(parent,cct.itemType) || !wep.HasInternalMagazine(-1))
227 Debug.Log("FAILED spawning item: " + cct.itemType + " of parent: " + parent,"n/a","n/a","SpawnComplexChildrenItems");
228 }
229 }
230
231 return true;
232 }
233
235 {
236 if (!data || !data.simpleChildrenTypes || data.simpleChildrenTypes.Count() < 1) //no children defined, still valid!
237 {
238 return false;
239 }
240
241 int count = data.simpleChildrenTypes.Count();
242 string itemType;
243 for (int i = 0; i < count; i++)
244 {
245 itemType = data.simpleChildrenTypes[i];
246 if (itemType == string.Empty)
247 {
248 Debug.Log("Empty item type found at idx: " + i.ToString() + " of 'simpleChildrenTypes' array. Skipping","n/a","n/a","SpawnSimpleChildrenItems");
249 continue;
250 }
251
252 ItemBase item;
253 Class.CastTo(item,CreateChildItem(parent,itemType));
254
255 if (item)
256 {
258 ApplyAttributes(item,data.attributes);
259 }
260 else
261 {
262 Weapon_Base wep;
263 if (!Class.CastTo(wep,parent) || !IsWeaponAndMagazineType(parent,itemType) || !wep.HasInternalMagazine(-1))
264 Debug.Log("FAILED spawning item type: " + itemType + " to parent: " + parent,"n/a","n/a","SpawnSimpleChildrenItems");
265 }
266 }
267 return true;
268 }
269
270 private static void HandleNewItem(notnull ItemBase item, PlayerSpawnPresetItemSetBase data)
271 {
272 ApplyAttributes(item,data.attributes);
273
274 PlayerBase player;
275 if (Class.CastTo(player,item.GetHierarchyRootPlayer()) && data.GetQuickbarIdx() > -1)
276 player.SetQuickBarEntityShortcut(item,data.GetQuickbarIdx());
277
278 SpawnComplexChildrenItems(item,data);
279 SpawnSimpleChildrenItems(item,data);
280 }
281
282 private static EntityAI CreateChildItem(EntityAI parent, string type)
283 {
284 PlayerBase player;
285 ItemBase newItem;
286 if (Class.CastTo(player,parent)) //special behavior
287 {
288 if (Class.CastTo(newItem,player.GetInventory().CreateInInventory(type)))
289 return newItem;
290
291 Debug.Log("FAILED spawning item: " + type + ", it fits in no cargo or attachment on any worn item","n/a","n/a","CreateChildItem");
292 return null;
293 }
294
295 //weapon magazine exception
296 if (g_Game.ConfigIsExisting(CFG_MAGAZINESPATH + " " + type) && parent.IsWeapon())
297 {
298 Weapon_Base wep
299 if (Class.CastTo(wep,parent) && wep.SpawnAmmo(type) && !wep.HasInternalMagazine(-1)) //assuming weps with internal magazine don't attach external magazines
300 {
301 Magazine mag;
302 int muzzleCount = wep.GetMuzzleCount();
303 for (int i = 0; i < muzzleCount; i++)
304 {
305 if (Class.CastTo(mag,wep.GetMagazine(i)) && mag.GetType() == type)
306 return mag;
307 }
308 }
309
310 return null;
311 }
312
313 return parent.GetInventory().CreateInInventory(type);
314 }
315
316 private static void ApplyAttributes(ItemBase item, PlayerSpawnAttributesData attributes)
317 {
318 if (!attributes)
319 return;
320
321 float health01 = Math.RandomFloatInclusive(attributes.healthMin,attributes.healthMax);
322 item.SetHealth01("","Health",health01);
323
324 float quantity01 = Math.RandomFloatInclusive(attributes.quantityMin,attributes.quantityMax);
325 if (item.IsMagazine())
326 {
327 Magazine mag = Magazine.Cast(item);
328 /*if (attributes.magazineAmmoOrdered && attributes.magazineAmmoOrdered.Count() > 0)
329 {
330 mag.ServerSetAmmoCount(0);
331 foreach (string bulletType : attributes.magazineAmmoOrdered)
332 {
333 mag.ServerStoreCartridge(health01,bulletType);
334 }
335 mag.SetSynchDirty();
336 }
337 else*/
338 {
339 int ammoQuantity = (int)Math.Lerp(0,mag.GetAmmoMax(),quantity01);
340 mag.ServerSetAmmoCount(ammoQuantity);
341 }
342 }
343 else //'varQuantityDestroyOnMin' quantity safeguard
344 {
345 float quantityAbsolute = Math.Lerp(item.GetQuantityMin(),item.GetQuantityMax(),quantity01);
346 quantityAbsolute = Math.Round(quantityAbsolute); //avoids weird floats
347 if (quantityAbsolute <= item.GetQuantityMin() && item.ConfigGetBool("varQuantityDestroyOnMin"))
348 quantityAbsolute++;
349 item.SetQuantity(quantityAbsolute);
350 }
351 }
352
354 private static bool IsWeaponAndMagazineType(EntityAI parent, string type)
355 {
356 return (g_Game.ConfigIsExisting(CFG_MAGAZINESPATH + " " + type) && parent.IsWeapon());
357 }
358}
Param3 int
static TStringArray GetPlayerSpawnGearPresetFiles()
Super root of all classes in Enforce script.
Definition enscript.c:11
Definition debug.c:2
static void Log(string message=LOG_DEFAULT, string plugin=LOG_DEFAULT, string author=LOG_DEFAULT, string label=LOG_DEFAULT, string entity=LOG_DEFAULT)
Prints debug message with normal prio.
Definition debug.c:182
provides access to slot configuration
static proto native owned string GetSlotName(int id)
override bool SetQuantity(float value, bool destroy_config=true, bool destroy_forced=false, bool allow_client=false, bool clamp_to_stack_max=true)
Definition enmath.c:7
static PlayerSpawnPreset GetRandomCharacterPreset()
static bool SpawnDiscreteCargoItemSet(PlayerBase player, PlayerSpawnPresetDiscreteCargoSetData csd)
static EntityAI CreateChildItem(EntityAI parent, string type)
static void ProcessCargoEquipment(PlayerBase player, PlayerSpawnPreset data)
chooses one object from the array
static PlayerSpawnPreset GetCharacterPresetByName(string presetName)
static bool ProcessEquipmentData(PlayerBase player, PlayerSpawnPreset data)
equips character with the chosen preset
static bool SpawnComplexChildrenItems(EntityAI parent, notnull PlayerSpawnPresetItemSetBase data)
could spawn other items recursively. Parent item is guaranteed here.
static bool SpawnDiscreteSlotItemSet(PlayerBase player, PlayerSpawnPresetDiscreteItemSetSlotData dis, int slotID)
static void HandleNewItem(notnull ItemBase item, PlayerSpawnPresetItemSetBase data)
static ref PlayerSpawnJsonData m_Data
static bool SpawnSimpleChildrenItems(EntityAI parent, PlayerSpawnPresetItemSetBase data)
static bool SelectAndSpawnSlotEquipment(PlayerBase player, PlayerSpawnPresetSlotData slotData)
selects weighted slot equipment variant
static void ProcessSlotsEquipment(PlayerBase player, PlayerSpawnPreset data)
iterates over each object and spawns alternatives
static bool SelectAndSpawnCargoSet(PlayerBase player, PlayerSpawnPreset data)
static void ApplyAttributes(ItemBase item, PlayerSpawnAttributesData attributes)
static bool IsWeaponAndMagazineType(EntityAI parent, string type)
Used for exceptions in the system.
used for specific hierarchical child spawning
bool HasAttachmentSlotSetsDefined()
preset might be valid even with no attachmentSlotItemSets configured, checked separately
ref array< ref PlayerSpawnPresetSlotData > attachmentSlotItemSets
ref array< ref PlayerSpawnPresetDiscreteCargoSetData > discreteUnsortedItemSets
bool HasDiscreteUnsortedItemSetsDefined()
preset might be valid even with no unsorted item sets configured, checked separately
ref PlayerSpawnAttributesData attributes
ref array< ref PlayerSpawnPresetComplexChildrenType > complexChildrenTypes
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
DayZGame g_Game
Definition dayzgame.c:3942
enum ShapeType ErrorEx
static proto bool CastTo(out Class to, Class from)
Try to safely down-cast base class to child class.
static proto float Round(float f)
Returns mathematical round of value.
static float RandomFloatInclusive(float min, float max)
Returns a random float number between and min [inclusive] and max [inclusive].
Definition enmath.c:106
static proto float Lerp(float a, float b, float time)
Linearly interpolates between 'a' and 'b' given 'time'.
const string CFG_MAGAZINESPATH
Definition constants.c:222
static const string Empty
Definition enstring.c:7
Empty
Definition hand_states.c:14