Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_ArsenalManagerComponent.c
Go to the documentation of this file.
2 {
3  string loadout;
4  ref SCR_PlayerLoadoutData loadoutData;
5  float suppliesCost = 0.0;
6 }
7 
8 //~ Scriptinvokers
9 void SCR_ArsenalManagerComponent_OnPlayerLoadoutChanged(int playerId, bool hasValidLoadout);
11 
12 [ComponentEditorProps(category: "GameScripted/GameMode", description: "")]
14 {
15  //------------------------------------------------------------------------------------------------
16  static override array<typename> Requires(IEntityComponentSource src)
17  {
18  array<typename> requires = {};
19 
20  requires.Insert(SerializerInventoryStorageManagerComponent);
21 
22  return requires;
23  }
24 }
25 
26 class SCR_ArsenalManagerComponent : SCR_BaseGameModeComponent
27 {
28  protected static SCR_ArsenalManagerComponent s_Instance;
29 
30  protected static const ref array<string> ARSENALLOADOUT_COMPONENTS_TO_CHECK = {
31  "SCR_CharacterInventoryStorageComponent",
32  "SCR_UniversalInventoryStorageComponent",
33  "EquipedWeaponStorageComponent",
34  "ClothNodeStorageComponent"
35  };
36 
37  [Attribute("{27F28CF7C6698FF8}Configs/Arsenal/ArsenalSaveTypeInfoHolder.conf", desc: "Holds a list of save types than can be used for arsenals. Any new arsenal save type should be added to the config to allow it to be set by Editor", params: "conf class=SCR_ArsenalSaveTypeInfoHolder")]
38  protected ResourceName m_sArsenalSaveTypeInfoHolder;
39 
40  [Attribute("{183361B6DA2C304F}Configs/Arsenal/ArsenalLoadoutSaveBlacklists.conf", desc: "This is server only, A blacklist of entities that are not allowed to be saved at arsenals if the blacklist the item is in is enabled. Can be null.",params: "conf class=SCR_LoadoutSaveBlackListHolder")]
41  protected ResourceName m_sLoadoutSaveBlackListHolder;
42 
43  [Attribute()]
44  protected bool m_bDisable
45 
46  //=== Authority
47  protected ref map<string, ref SCR_ArsenalPlayerLoadout> m_aPlayerLoadouts = new map<string, ref SCR_ArsenalPlayerLoadout>();
48 
49  //=== Broadcast
50  protected ref ScriptInvokerBase<SCR_ArsenalManagerComponent_OnPlayerLoadoutChanged> m_OnPlayerLoadoutUpdated = new ScriptInvokerBase<SCR_ArsenalManagerComponent_OnPlayerLoadoutChanged>();
51 
54 
57 
58  [Attribute("0", desc: "Cost multiplier for supplies on spawning. 0 means the cost is free. Only used in gamemodes that support supply cost on spawning", params: "-1 inf")]//, RplProp(onRplName: "OnLoadoutSpawnSupplyCostMultiplierChanged")]
60 
61  //------------------------------------------------------------------------------------------------
64  static bool GetArsenalManager(out SCR_ArsenalManagerComponent arsenalManager)
65  {
66  arsenalManager = s_Instance;
67  return s_Instance != null;
68  }
69 
70  //------------------------------------------------------------------------------------------------
73  {
75  }
76 
77  //------------------------------------------------------------------------------------------------
80  {
82  }
83 
84  //------------------------------------------------------------------------------------------------
85  protected void OnPlayerChangedFaction(int playerId, SCR_PlayerFactionAffiliationComponent playerFactionAffiliation, Faction faction)
86  {
87  string playerUID = GetGame().GetBackendApi().GetPlayerIdentityId(playerId);
88  if (!m_aPlayerLoadouts.Contains(playerUID))
89  return;
90 
91  /*Faction playerFaction = playerFactionAffiliation.GetAffiliatedFaction();
92 
93  //~ Remove loadout from map on server and inform players
95  if (playerFaction && faction)
96  {
97  m_aPlayerLoadouts.Remove(playerUID);
98  DoPlayerClearHasLoadout(playerId);
99  Rpc(DoPlayerClearHasLoadout, playerId);
100  }*/
101  }
102 
103  //------------------------------------------------------------------------------------------------
108  void SetLoadoutBlackListActiveStates(notnull array<bool> orderedActiveStates, bool clearExistingLoadouts, int editorPlayerIdClearedLoadout = -1)
109  {
111  return;
112 
113  if (editorPlayerIdClearedLoadout > 0)
114  SCR_NotificationsComponent.SendToEveryone(ENotification.EDITOR_CHANGED_LOADOUT_SAVE_BLACKLIST, editorPlayerIdClearedLoadout);
115 
116  m_LoadoutSaveBlackListHolder.SetOrderedBlackListsActive(orderedActiveStates);
117 
118  //~ Clear existing loadouts
119  if (clearExistingLoadouts)
120  {
121  //~ Clear local loadout
122  Rpc(RPC_OnPlayerLoadoutCleared, editorPlayerIdClearedLoadout);
123  RPC_OnPlayerLoadoutCleared(editorPlayerIdClearedLoadout);
124 
125  //~ Clear existing loadouts on server
126  m_aPlayerLoadouts.Clear();
127  }
128  }
129 
130  //------------------------------------------------------------------------------------------------
131  [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
132  protected void RPC_OnPlayerLoadoutCleared(int playerIdClearedLoadout)
133  {
135  return;
136 
137  //~ No local loadout availible anymore
139 
140  //~ Player loadout was cleared. This can happen when respawn menu is open and needs to be refreshed
141  m_OnPlayerLoadoutUpdated.Invoke(SCR_PlayerController.GetLocalPlayerId(), false);
142 
143  //~ Send notification to player to inform them their loadout was cleared
144  if (playerIdClearedLoadout > 0)
145  SCR_NotificationsComponent.SendLocal(ENotification.PLAYER_LOADOUT_CLEARED_BY_EDITOR);
146  else
147  SCR_NotificationsComponent.SendLocal(ENotification.PLAYER_LOADOUT_CLEARED);
148  }
149 
150  //------------------------------------------------------------------------------------------------
153  {
155  }
156 
157  //------------------------------------------------------------------------------------------------
159  ScriptInvokerBase<SCR_ArsenalManagerComponent_OnPlayerLoadoutChanged> GetOnLoadoutUpdated()
160  {
162  }
163 
164  //------------------------------------------------------------------------------------------------
169  bool GetPlayerArsenalLoadout(string playerUID, out SCR_ArsenalPlayerLoadout playerLoadout)
170  {
171  return m_aPlayerLoadouts.Find(playerUID, playerLoadout) && playerLoadout.loadout != string.Empty;
172  }
173 
174  //------------------------------------------------------------------------------------------------
175  //~ TODO: Add ability to set Cost multiplier in run time
176  /*void SetLoadoutSpawnCostMultiplier(float multiplier, int playerID)
177  {
178  //~ Same or invalid values
179  if (m_fLoadoutSpawnSupplyCostMultiplier == multiplier || multiplier < 0)
180  return;
181 
182  m_fLoadoutSpawnSupplyCostMultiplier = multiplier;
183  Replication.BumpMe();
184 
185  //~ Notification
186  if (playerID > 0)
187  SCR_NotificationsComponent.SendToEveryone(ENotification.EDITOR_ATTRIBUTES_CHANGED_SPAWN_SUPPLYCOST_MULTIPLIER, playerID, m_fLoadoutSpawnSupplyCostMultiplier * 1000);
188 
189  SCR_BaseGameMode gameMode = SCR_BaseGameMode.Cast(GetGame().GetGameMode());
190  if ((gameMode && gameMode.IsMaster()) || (!gameMode && Replication.IsServer()))
191  OnLoadoutSupplyCostMultiplierChanged();
192  }*/
193 
194  //------------------------------------------------------------------------------------------------
197  {
198  if (!SCR_ResourceSystemHelper.IsGlobalResourceTypeEnabled())
199  return 0;
200 
202  }
203 
204  //------------------------------------------------------------------------------------------------
205  /*protected void OnLoadoutSpawnSupplyCostMultiplierChanged()
206  {
207 
208  }*/
209 
210  //------------------------------------------------------------------------------------------------
211  /*static int GetLoadoutCalculatedSupplyCost_S(SCR_BasePlayerLoadout playerLoadout, int playerID, SCR_CampaignMilitaryBaseComponent base, SCR_ResourceComponent resourceComponent)
212  {
213  GetLoadoutCalculatedSupplyCost(playerLoadout, playerID, null, base, resourceComponent);
214  }
215 
216  //------------------------------------------------------------------------------------------------
217  static int GetLoadoutCalculatedSupplyCost_C(SCR_BasePlayerLoadout playerLoadout, SCR_Faction playerFaction, SCR_CampaignMilitaryBaseComponent base, SCR_ResourceComponent resourceComponent)
218  {
219  GetLoadoutCalculatedSupplyCost(playerLoadout, playerID, playerFaction, base, resourceComponent);
220  }*/
221 
222  //------------------------------------------------------------------------------------------------
223  //~ TODO: Make sure that this function takes the resourceComponent from SpawnPoint alternativly if it does not try to spawn at base
232  static float GetLoadoutCalculatedSupplyCost(notnull SCR_BasePlayerLoadout playerLoadout, bool getLocalPlayer, int playerID, SCR_Faction playerFaction, SCR_CampaignMilitaryBaseComponent base, SCR_ResourceComponent resourceComponent)
233  {
234  float multiplier = 1;
235  SCR_ArsenalManagerComponent arsenalManager;
236  if (!GetArsenalManager(arsenalManager))
237  return 0;
238 
239  multiplier = arsenalManager.GetLoadoutSpawnSupplyCostMultiplier();
240 
241  //~ Spawn multiplier is 0
242  if (multiplier <= 0)
243  return 0;
244 
245  //~ Supplies are disabled
246  if (resourceComponent && !resourceComponent.IsResourceTypeEnabled())
247  return 0;
248  else if (!resourceComponent && !SCR_ResourceSystemHelper.IsGlobalResourceTypeEnabled())
249  return 0;
250 
251  float baseMultiplier = 0;
252 
253  //~ TODO: Deploy menu does not know which base (Or Spawnpoint Resource Component) the player is trying to spawn at
254  if (base)
255  {
256  if (!base.CostSuppliesToSpawn())
257  return 0;
258 
259  baseMultiplier = base.GetBaseSpawnCostFactor();
260  }
261 
262  SCR_PlayerArsenalLoadout playerArsenalLoadout = SCR_PlayerArsenalLoadout.Cast(playerLoadout);
263 
264  if (playerArsenalLoadout)
265  {
267 
268  //~ Local
269  if (getLocalPlayer && arsenalManager.m_bLocalPlayerLoadoutData)
270  {
271  if (baseMultiplier > 0)
272  return Math.Clamp(arsenalManager.m_bLocalPlayerLoadoutData.LoadoutCost * baseMultiplier, 0, float.MAX);
273  else
274  return Math.Clamp(arsenalManager.m_bLocalPlayerLoadoutData.LoadoutCost, 0, float.MAX);
275  }
276  //~ Server
277  else if ((gameMode && gameMode.IsMaster()) || (!gameMode && Replication.IsServer()))
278  {
279  if (baseMultiplier > 0)
280  return Math.Clamp(playerArsenalLoadout.GetLoadoutSuppliesCost(playerID) * baseMultiplier, 0, float.MAX);
281  else
282  return Math.Clamp(playerArsenalLoadout.GetLoadoutSuppliesCost(playerID), 0, float.MAX);
283  }
284 
285  //~ No custom loadout found so spawn cost is base cost or 0 if no base is given
286  if (base)
287  return Math.Clamp(base.GetBaseSpawnCost(), 0, float.MAX);
288 
289  return 0;
290  }
291  //~ Not an arsenal loadout so take cost from catalog
292  else
293  {
294  SCR_EntityCatalogManagerComponent entityCatalogManager = SCR_EntityCatalogManagerComponent.GetInstance();
295  if (!entityCatalogManager)
296  return 0;
297 
298  ResourceName loadoutResource = playerLoadout.GetLoadoutResource();
299  if (!loadoutResource)
300  return 0;
301 
302  Resource resource = Resource.Load(loadoutResource);
303  if (!resource)
304  return 0;
305 
306  SCR_EntityCatalogEntry entry = entityCatalogManager.GetEntryWithPrefabFromAnyCatalog(EEntityCatalogType.CHARACTER, resource.GetResource().GetResourceName(), playerFaction);
307  if (!entry)
308  {
309  Print("Loadout: '" + resource.GetResource().GetResourceName() + "' is not in catalog so supply cost is 0!", LogLevel.WARNING);
310  return 0;
311  }
312 
314  float supplyCost;
315 
316  if (data)
317  {
318  supplyCost = data.GetLoadoutSpawnCost();
319  }
320  //~ No data so try to get Campaign budget for supply cost
321  else
322  {
323  Print("Loadout: '" + resource.GetResource().GetResourceName() + "' has no 'SCR_EntityCatalogLoadoutData' assigned in catalog so supply cost is taken from Campaign budget on prefab!", LogLevel.WARNING);
324 
325  SCR_EditableEntityUIInfo editableUIInfo = SCR_EditableEntityUIInfo.Cast(entry.GetEntityUiInfo());
326  if (!editableUIInfo)
327  return 0;
328 
329  array<ref SCR_EntityBudgetValue> budgets = {};
330 
331  if (!editableUIInfo.GetEntityBudgetCost(budgets))
332  return 0;
333 
334  //~ Get campaign budget
335  foreach (SCR_EntityBudgetValue budget : budgets)
336  {
337  if (budget.GetBudgetType() == EEditableEntityBudget.CAMPAIGN)
338  {
339  supplyCost = budget.GetBudgetValue();
340  break;
341  }
342  }
343 
344  //~ No campaign budget assigned
345  if (supplyCost <= 0)
346  return 0;
347  }
348 
349  //~ Add multipliers to the supply cost
350  if (baseMultiplier > 0)
351  return Math.Clamp((supplyCost * multiplier) * baseMultiplier, 0, float.MAX);
352  else
353  return Math.Clamp(supplyCost * multiplier, 0, float.MAX);
354  }
355 
356  //~ If all fails set supply cost 0
357  return 0;
358  }
359 
360  //------------------------------------------------------------------------------------------------
361  protected bool CanSaveLoadout(int playerId, notnull GameEntity characterEntity, FactionAffiliationComponent playerFactionAffiliation, SCR_ArsenalComponent arsenalComponent, bool sendNotificationOnFailed)
362  {
363  //~ Always allow saving if no arsenal component or no restrictions
364  if (!arsenalComponent || (arsenalComponent.GetArsenalSaveType() == SCR_EArsenalSaveType.NO_RESTRICTIONS && (!m_LoadoutSaveBlackListHolder || m_LoadoutSaveBlackListHolder.GetBlackListsCount() == 0)))
365  return true;
366 
367  SCR_InventoryStorageManagerComponent characterInventory = SCR_InventoryStorageManagerComponent.Cast(characterEntity.FindComponent(SCR_InventoryStorageManagerComponent));
368  if (!characterInventory)
369  {
370  Print("'SCR_ArsenalManagerComponent' is checking 'CanSaveArsenal()' but character has no inventory manager!", LogLevel.ERROR);
371 
372  if (sendNotificationOnFailed)
373  SCR_NotificationsComponent.SendToPlayer(playerId, ENotification.PLAYER_LOADOUT_NOT_SAVED);
374 
375  return false;
376  }
377 
378  SCR_EntityCatalog itemCatalog;
379  SCR_ArsenalInventoryStorageManagerComponent arsenalInventory;
380 
381  //~ Check either faction or arsenal inventory if item is in it
382  if (arsenalComponent.GetArsenalSaveType() == SCR_EArsenalSaveType.FACTION_ITEMS_ONLY || arsenalComponent.GetArsenalSaveType() == SCR_EArsenalSaveType.IN_ARSENAL_ITEMS_ONLY)
383  {
384  if (arsenalComponent.GetArsenalSaveType() == SCR_EArsenalSaveType.FACTION_ITEMS_ONLY)
385  {
386  //~ Player has no faction affiliation comp
387  if (!playerFactionAffiliation)
388  {
389  Print("'SCR_ArsenalManagerComponent' is checking 'CanSaveArsenal()' but player has no faction affiliation component, arsenal saving will simply be allowed", LogLevel.WARNING);
390  return true;
391  }
392 
393  SCR_Faction playerFaction = SCR_Faction.Cast(playerFactionAffiliation.GetAffiliatedFaction());
394  //~ Player has no faction
395  if (!playerFaction)
396  {
397  Print("'SCR_ArsenalManagerComponent' is checking 'CanSaveArsenal()' but player has no SCR_Faction, arsenal saving will simply be allowed", LogLevel.WARNING);
398  return true;
399  }
400 
401  itemCatalog = playerFaction.GetFactionEntityCatalogOfType(EEntityCatalogType.ITEM);
402  if (!itemCatalog)
403  {
404  Print(string.Format("'SCR_ArsenalManagerComponent' is checking 'CanSaveArsenal()' but player faction '%1' has no ITEM catalog!", playerFaction.GetFactionKey()), LogLevel.ERROR);
405 
406  if (sendNotificationOnFailed)
407  SCR_NotificationsComponent.SendToPlayer(playerId, ENotification.PLAYER_LOADOUT_NOT_SAVED);
408 
409  return false;
410  }
411  }
412  else
413  {
414  arsenalInventory = SCR_ArsenalInventoryStorageManagerComponent.Cast(arsenalComponent.GetArsenalInventoryComponent());
415  if (!arsenalInventory)
416  {
417  Print("'SCR_ArsenalManagerComponent' is checking 'CanSaveArsenal()' and arsenal check type is 'IN_ARSENAL_ITEMS_ONLY' but arsenal has no SCR_ArsenalInventoryStorageManagerComponent, so saving is simply allowed", LogLevel.WARNING);
418  return true;
419  }
420  }
421  }
422 
423  set<string> checkedEntities = new set<string>();
424  array<IEntity> allPlayerItems = {};
425  characterInventory.GetAllRootItems(allPlayerItems);
426 
427  EntityPrefabData prefabData;
428  RplComponent itemRplComponent;
429  string resourceName;
430 
431  int invalidItemCount = 0;
432 
433  foreach (IEntity item : allPlayerItems)
434  {
435  prefabData = item.GetPrefabData();
436 
437  //~ Ignore if no prefab data
438  if (!prefabData)
439  continue;
440 
441  //~ Ignore if no prefab resource name
442  resourceName = prefabData.GetPrefabName();
443  if (resourceName.IsEmpty())
444  continue;
445 
446  //~ Do not check the same item twice
447  if (checkedEntities.Contains(resourceName))
448  continue;
449 
450  checkedEntities.Insert(resourceName);
451 
452  //~ Check if item is blacklisted if there is a blacklist
453  if (m_LoadoutSaveBlackListHolder && m_LoadoutSaveBlackListHolder.GetBlackListsCount() != 0)
454  {
455  //~ Item is blackListed so do not allow saving
456  if (m_LoadoutSaveBlackListHolder.IsPrefabBlacklisted(resourceName))
457  {
458  if (sendNotificationOnFailed)
459  {
460  itemRplComponent = RplComponent.Cast(item.FindComponent(RplComponent));
461  if (itemRplComponent)
462  SCR_NotificationsComponent.SendToPlayer(playerId, ENotification.PLAYER_LOADOUT_ITEM_FAILED_ITEM_BLACKLISTED, itemRplComponent.Id());
463  }
464 
465  invalidItemCount++;
466  continue;
467  }
468  }
469 
470  //~ Check arsenal inventory
471  if (arsenalInventory)
472  {
473  //~ Not in inventory of arsenal so cannot save
474  if (!arsenalInventory.IsPrefabInArsenalStorage(resourceName))
475  {
476  if (sendNotificationOnFailed)
477  {
478  itemRplComponent = RplComponent.Cast(item.FindComponent(RplComponent));
479  if (itemRplComponent)
480  SCR_NotificationsComponent.SendToPlayer(playerId, ENotification.PLAYER_LOADOUT_ITEM_FAILED_NOT_IN_ARSENAL, itemRplComponent.Id());
481  }
482 
483  invalidItemCount++;
484  continue;
485  }
486  }
487  //~ Check item catalog
488  else if (itemCatalog)
489  {
490  //~ Item not in faction catalog so cannot save
491  if (!itemCatalog.GetEntryWithPrefab(resourceName))
492  {
493  if (sendNotificationOnFailed)
494  {
495  itemRplComponent = RplComponent.Cast(item.FindComponent(RplComponent));
496  if (itemRplComponent)
497  SCR_NotificationsComponent.SendToPlayer(playerId, ENotification.PLAYER_LOADOUT_ITEM_FAILED_NOT_FACTION, itemRplComponent.Id());
498  }
499 
500  invalidItemCount++;
501  continue;
502  }
503  }
504  }
505 
506  //~ Saving failed because of invalid items
507  if (invalidItemCount > 0 && sendNotificationOnFailed)
508  SCR_NotificationsComponent.SendToPlayer(playerId, ENotification.PLAYER_LOADOUT_NOT_SAVED_INVALID_ITEMS, invalidItemCount);
509 
510  return invalidItemCount == 0;
511  }
512 
513  //------------------------------------------------------------------------------------------------
519  void SetPlayerArsenalLoadout(int playerId, GameEntity characterEntity, SCR_ArsenalComponent arsenalComponent, SCR_EArsenalSupplyCostType arsenalSupplyType)
520  {
521  //~ If Not Authority return
522  if (!GetGameMode().IsMaster())
523  return;
524 
525  string playerUID = GetGame().GetBackendApi().GetPlayerIdentityId(playerId);
526  if (!characterEntity)
527  {
528  DoSetPlayerLoadout(playerId, string.Empty, characterEntity, arsenalSupplyType);
529  return;
530  }
531 
532  SCR_PlayerController clientPlayerController = SCR_PlayerController.Cast(GetGame().GetPlayerManager().GetPlayerController(playerId));
533  if (!clientPlayerController || clientPlayerController.IsPossessing())
534  return;
535 
536  string factionKey = SCR_PlayerArsenalLoadout.ARSENALLOADOUT_FACTIONKEY_NONE;
537  FactionAffiliationComponent factionAffiliation = FactionAffiliationComponent.Cast(characterEntity.FindComponent(FactionAffiliationComponent));
538  if (factionAffiliation)
539  factionKey = factionAffiliation.GetAffiliatedFaction().GetFactionKey();
540 
541  if (!CanSaveLoadout(playerId, characterEntity, factionAffiliation, arsenalComponent, true))
542  return;
543 
544  SCR_JsonSaveContext context = new SCR_JsonSaveContext();
545  if (!context.WriteValue(SCR_PlayerArsenalLoadout.ARSENALLOADOUT_FACTION_KEY, factionKey) || !context.WriteValue(SCR_PlayerArsenalLoadout.ARSENALLOADOUT_KEY, characterEntity))
546  return;
547 
548  DoSetPlayerLoadout(playerId, context.ExportToString(), characterEntity, arsenalSupplyType);
549  }
550 
551  //------------------------------------------------------------------------------------------------
552  protected SCR_PlayerLoadoutData GetPlayerLoadoutData(GameEntity characterEntity)
553  {
555 
556  EquipedLoadoutStorageComponent loadoutStorage = EquipedLoadoutStorageComponent.Cast(characterEntity.FindComponent(EquipedLoadoutStorageComponent));
557  if (loadoutStorage)
558  {
559  int slotsCount = loadoutStorage.GetSlotsCount();
560  for (int i = 0; i < slotsCount; ++i)
561  {
562  InventoryStorageSlot slot = loadoutStorage.GetSlot(i);
563  if (!slot)
564  continue;
565 
566  IEntity attachedEntity = slot.GetAttachedEntity();
567  if (!attachedEntity)
568  continue;
569 
570  ResourceName prefabName;
571  BaseContainer prefab = attachedEntity.GetPrefabData().GetPrefab();
572  while (prefabName.IsEmpty() && prefab)
573  {
574  prefabName = prefab.GetResourceName();
575  prefab = prefab.GetAncestor();
576  }
577 
578  if (prefabName.IsEmpty())
579  continue;
580 
581  SCR_ClothingLoadoutData clothingData();
582  clothingData.SlotIdx = i;
583  clothingData.ClothingPrefab = prefabName;
584 
585  loadoutData.Clothings.Insert(clothingData);
586  }
587  }
588 
589  EquipedWeaponStorageComponent weaponStorage = EquipedWeaponStorageComponent.Cast(characterEntity.FindComponent(EquipedWeaponStorageComponent));
590  if (weaponStorage)
591  {
592  int slotsCount = weaponStorage.GetSlotsCount();
593  for (int i = 0; i < slotsCount; ++i)
594  {
595  InventoryStorageSlot slot = weaponStorage.GetSlot(i);
596  if (!slot)
597  continue;
598 
599  IEntity attachedEntity = slot.GetAttachedEntity();
600  if (!attachedEntity)
601  continue;
602 
603  ResourceName prefabName;
604  BaseContainer prefab = attachedEntity.GetPrefabData().GetPrefab();
605  while (prefabName.IsEmpty() && prefab)
606  {
607  prefabName = prefab.GetResourceName();
608  prefab = prefab.GetAncestor();
609  }
610 
611  if (prefabName.IsEmpty())
612  continue;
613 
614  SCR_WeaponLoadoutData weaponData();
615  weaponData.SlotIdx = i;
616  weaponData.WeaponPrefab = prefabName;
617 
618  loadoutData.Weapons.Insert(weaponData);
619  }
620  }
621 
622  return loadoutData;
623  }
624 
625  //------------------------------------------------------------------------------------------------
626  protected void ComputeSuppliesCost(notnull SCR_Faction faction, notnull SCR_ArsenalPlayerLoadout playerLoadout, SCR_EArsenalSupplyCostType arsenalSupplyType)
627  {
628  playerLoadout.suppliesCost = 0.0;
629 
630  SCR_JsonLoadContext context = new SCR_JsonLoadContext(false);
631  if (!context.ImportFromString(playerLoadout.loadout))
632  return;
633 
634  ComputeEntity(context, faction, playerLoadout, SCR_PlayerArsenalLoadout.ARSENALLOADOUT_KEY, arsenalSupplyType);
635  }
636 
637  //------------------------------------------------------------------------------------------------
638  protected void ComputeStorage(notnull SCR_JsonLoadContext context, notnull SCR_Faction faction, notnull SCR_ArsenalPlayerLoadout playerLoadout, string storageName, SCR_EArsenalSupplyCostType arsenalSupplyType)
639  {
640  if (!context.StartObject(storageName))
641  return;
642 
643  if (!context.StartObject("Native"))
644  {
645  context.EndObject();
646  return;
647  }
648 
649  if (!context.StartObject("slots"))
650  {
651  context.EndObject();
652  context.EndObject();
653  return;
654  }
655 
656  int itemsCount;
657  if (!context.ReadValue("itemsCount", itemsCount))
658  return;
659 
660  for (int i = 0; i < itemsCount; ++i)
661  {
662  bool valid = false;
663  if (!context.ReadValue("slot-" + i +"-valid", valid))
664  return;
665 
666  if (!valid)
667  continue;
668 
669  if (!context.StartObject("slot-" + i))
670  return;
671 
672  ComputeStorageEntity(context, faction, playerLoadout, "entity", arsenalSupplyType);
673 
674  if (!context.EndObject())
675  return;
676  }
677 
678  if (!context.EndObject())
679  return;
680 
681  if (!context.EndObject())
682  return;
683 
684  if (!context.EndObject())
685  return;
686  }
687 
688  //------------------------------------------------------------------------------------------------
689  protected void ComputeStorageEntity(notnull SCR_JsonLoadContext context, notnull SCR_Faction faction, notnull SCR_ArsenalPlayerLoadout playerLoadout, string entityName, SCR_EArsenalSupplyCostType arsenalSupplyType)
690  {
691  if (!context.StartObject("entity"))
692  return;
693 
694  ResourceName prefab;
695  if (!context.ReadValue("prefabGUID", prefab))
696  return;
697 
698  SCR_EntityCatalogManagerComponent entityCatalogManager = SCR_EntityCatalogManagerComponent.GetInstance();
699  SCR_EntityCatalogEntry entry = entityCatalogManager.GetEntryWithPrefabFromGeneralOrFactionCatalog(EEntityCatalogType.ITEM, prefab, faction);
700  if (entry)
701  {
702  SCR_ArsenalItem data = SCR_ArsenalItem.Cast(entry.GetEntityDataOfType(SCR_ArsenalItem));
703  if (data)
704  playerLoadout.suppliesCost += data.GetSupplyCost(arsenalSupplyType);
705  }
706 
707  ComputeEntity(context, faction, playerLoadout, "entity", arsenalSupplyType);
708 
709  if (!context.EndObject())
710  return;
711  }
712 
713  //------------------------------------------------------------------------------------------------
714  protected void ComputeEntity(notnull SCR_JsonLoadContext context, notnull SCR_Faction faction, notnull SCR_ArsenalPlayerLoadout playerLoadout, string entityName, SCR_EArsenalSupplyCostType arsenalSupplyType)
715  {
716  if (!context.StartObject(entityName))
717  return;
718 
719  if (!context.StartObject("Native"))
720  return;
721 
722  if (!context.StartObject("components"))
723  return;
724 
725  foreach (string componentName: ARSENALLOADOUT_COMPONENTS_TO_CHECK)
726  {
727  ComputeStorage(context, faction, playerLoadout, componentName, arsenalSupplyType);
728  }
729 
730  if (!context.EndObject())
731  return;
732 
733  if (!context.EndObject())
734  return;
735 
736  if (!context.EndObject())
737  return;
738  }
739 
740  //------------------------------------------------------------------------------------------------
741  protected void DoSetPlayerLoadout(int playerId, string loadoutString, GameEntity characterEntity, SCR_EArsenalSupplyCostType arsenalSupplyType)
742  {
743  bool loadoutValid = !loadoutString.IsEmpty();
744 
745  string playerUID = GetGame().GetBackendApi().GetPlayerIdentityId(playerId);
746  SCR_ArsenalPlayerLoadout playerLoadout = m_aPlayerLoadouts.Get(playerUID);
747  if (!playerLoadout)
748  playerLoadout = new SCR_ArsenalPlayerLoadout();
749 
750  bool loadoutChanged = loadoutValid && loadoutString != playerLoadout.loadout;
751 
752  playerLoadout.loadout = loadoutString;
753 
754  m_aPlayerLoadouts.Set(playerUID, playerLoadout);
755 
756  if (loadoutChanged)
757  {
758  FactionAffiliationComponent factionAffiliation = FactionAffiliationComponent.Cast(characterEntity.FindComponent(FactionAffiliationComponent));
759  if (factionAffiliation && factionAffiliation.GetAffiliatedFaction())
760  ComputeSuppliesCost(SCR_Faction.Cast(factionAffiliation.GetAffiliatedFaction()), playerLoadout, arsenalSupplyType);
761  }
762 
763  if (loadoutValid && loadoutChanged)
764  {
765  playerLoadout.loadoutData = GetPlayerLoadoutData(characterEntity);
766  playerLoadout.loadoutData.LoadoutCost = SCR_PlayerArsenalLoadout.GetLoadoutSuppliesCost(playerUID);
767  DoSendPlayerLoadout(playerId, playerLoadout.loadoutData);
768  Rpc(DoSendPlayerLoadout, playerId, playerLoadout.loadoutData);
769  }
770 
771  DoSetPlayerHasLoadout(playerId, loadoutValid, loadoutChanged, true);
772  Rpc(DoSetPlayerHasLoadout, playerId, loadoutValid, loadoutChanged, true);
773  }
774 
775  //------------------------------------------------------------------------------------------------
776  override protected void OnPlayerAuditSuccess(int playerId)
777  {
778  super.OnPlayerAuditSuccess(playerId);
779 
780  string playerUID = GetGame().GetBackendApi().GetPlayerIdentityId(playerId);
781  SCR_ArsenalPlayerLoadout playerLoadout = m_aPlayerLoadouts.Get(playerUID);
782  if (!playerLoadout)
783  return;
784 
785  bool loadoutValid = !playerLoadout.loadout.IsEmpty();
786  if (!loadoutValid)
787  return;
788 
789  DoSendPlayerLoadout(playerId, playerLoadout.loadoutData);
790  Rpc(DoSendPlayerLoadout, playerId, playerLoadout.loadoutData);
791 
792  DoSetPlayerHasLoadout(playerId, loadoutValid, false, false);
793  Rpc(DoSetPlayerHasLoadout, playerId, loadoutValid, false, false);
794  }
795 
796  //------------------------------------------------------------------------------------------------
797  [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
798  protected void DoSetPlayerHasLoadout(int playerId, bool loadoutValid, bool loadoutChanged, bool notification)
799  {
800  if (playerId == SCR_PlayerController.GetLocalPlayerId())
801  {
802  if (notification)
803  {
804  if (m_bLocalPlayerLoadoutAvailable != loadoutValid || loadoutChanged)
805  {
806  //~ Send notification with loadout cost
808  SCR_NotificationsComponent.SendLocal(ENotification.PLAYER_LOADOUT_SAVED_SUPPLY_COST, m_bLocalPlayerLoadoutData.LoadoutCost);
809  //~ Set notification without loadout cost
810  else
811  SCR_NotificationsComponent.SendLocal(ENotification.PLAYER_LOADOUT_SAVED);
812  }
813  else
814  {
815  SCR_NotificationsComponent.SendLocal(ENotification.PLAYER_LOADOUT_NOT_SAVED_UNCHANGED);
816  }
817  }
818 
819  m_bLocalPlayerLoadoutAvailable = loadoutValid;
820  }
821  m_OnPlayerLoadoutUpdated.Invoke(playerId, loadoutValid);
822  }
823 
824  //------------------------------------------------------------------------------------------------
825  [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
827  {
828  if (playerId == SCR_PlayerController.GetLocalPlayerId())
830  }
831 
832  //------------------------------------------------------------------------------------------------
833  [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
834  protected void DoPlayerClearHasLoadout(int playerId)
835  {
836  if (playerId == SCR_PlayerController.GetLocalPlayerId())
838 
839  m_OnPlayerLoadoutUpdated.Invoke(playerId, false);
840  }
841 
842  //------------------------------------------------------------------------------------------------
843  override void EOnInit(IEntity owner)
844  {
845  //~ Init item black list (Server only). Call one frame later to make sure catalogs are initalized
847  GetGame().GetCallqueue().CallLater(m_LoadoutSaveBlackListHolder.Init);
848 
849  if (!GetGameMode().IsMaster())
850  return;
851 
852  SCR_FactionManager factionManager = SCR_FactionManager.Cast(GetGame().GetFactionManager());
853  if (factionManager)
854  factionManager.GetOnPlayerFactionChanged_S().Insert(OnPlayerChangedFaction);
855  }
856 
857  //------------------------------------------------------------------------------------------------
858  override void OnPostInit(IEntity owner)
859  {
860  if (s_Instance || SCR_Global.IsEditMode())
861  return;
862 
863  s_Instance = SCR_ArsenalManagerComponent.Cast(GetGameMode().FindComponent(SCR_ArsenalManagerComponent));
864  SetEventMask(owner, EntityEvent.INIT);
865 
866  //~ Get config for saveType holder. This is used by arsenals in the world
869  Print("'SCR_ArsenalManagerComponent' failed to load Arsenal Save Type Holder config!", LogLevel.ERROR);
870 
871  //~ Get loadout save blacklist config, Can be null (Server Only)
872  if (GetGameMode().IsMaster())
874  }
875 
876  //------------------------------------------------------------------------------------------------
877  override void OnDelete(IEntity owner)
878  {
879  if (SCR_Global.IsEditMode() || !GetGameMode() || !GetGameMode().IsMaster())
880  return;
881 
882  SCR_FactionManager factionManager = SCR_FactionManager.Cast(GetGame().GetFactionManager());
883  if (factionManager)
884  factionManager.GetOnPlayerFactionChanged_S().Remove(OnPlayerChangedFaction);
885  }
886 }
ComponentEditorProps
SCR_FragmentEntityClass ComponentEditorProps
DoSendPlayerLoadout
protected void DoSendPlayerLoadout(int playerId, SCR_PlayerLoadoutData loadoutData)
Definition: SCR_ArsenalManagerComponent.c:826
SCR_BaseGameMode
Definition: SCR_BaseGameMode.c:137
SCR_PlayerLoadoutData
Definition: SCR_PlayerLoadoutData.c:13
IsMaster
protected bool IsMaster()
Definition: SCR_DataCollectorComponent.c:190
SCR_PlayerController
Definition: SCR_PlayerController.c:31
ComputeEntity
protected void ComputeEntity(notnull SCR_JsonLoadContext context, notnull SCR_Faction faction, notnull SCR_ArsenalPlayerLoadout playerLoadout, string entityName, SCR_EArsenalSupplyCostType arsenalSupplyType)
Definition: SCR_ArsenalManagerComponent.c:714
GetLocalPlayerLoadoutAvailable
bool GetLocalPlayerLoadoutAvailable()
Definition: SCR_ArsenalManagerComponent.c:152
GetLoadoutSpawnSupplyCostMultiplier
float GetLoadoutSpawnSupplyCostMultiplier()
Definition: SCR_ArsenalManagerComponent.c:196
SCR_ResourceSystemHelper
Definition: SCR_ResourceSystemHelper.c:1
DoSetPlayerHasLoadout
protected void DoSetPlayerHasLoadout(int playerId, bool loadoutValid, bool loadoutChanged, bool notification)
Definition: SCR_ArsenalManagerComponent.c:798
SCR_ArsenalSaveTypeInfoHolder
Definition: SCR_ArsenalSaveTypeInfoHolder.c:2
m_aPlayerLoadouts
protected bool m_bDisable protected ref map< string, ref SCR_ArsenalPlayerLoadout > m_aPlayerLoadouts
Definition: SCR_ArsenalManagerComponent.c:47
InventoryStorageSlot
Definition: InventoryStorageSlot.c:12
m_LoadoutSaveBlackListHolder
protected ref SCR_LoadoutSaveBlackListHolder m_LoadoutSaveBlackListHolder
Definition: SCR_ArsenalManagerComponent.c:53
ComputeSuppliesCost
protected void ComputeSuppliesCost(notnull SCR_Faction faction, notnull SCR_ArsenalPlayerLoadout playerLoadout, SCR_EArsenalSupplyCostType arsenalSupplyType)
Definition: SCR_ArsenalManagerComponent.c:626
SCR_ArsenalPlayerLoadout
Definition: SCR_ArsenalManagerComponent.c:1
m_sLoadoutSaveBlackListHolder
protected ResourceName m_sLoadoutSaveBlackListHolder
Definition: SCR_ArsenalManagerComponent.c:41
RPC_OnPlayerLoadoutCleared
protected void RPC_OnPlayerLoadoutCleared(int playerIdClearedLoadout)
Definition: SCR_ArsenalManagerComponent.c:132
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
EEntityCatalogType
EEntityCatalogType
Definition: EEntityCatalogType.c:4
GetLoadoutSaveBlackListHolder
SCR_LoadoutSaveBlackListHolder GetLoadoutSaveBlackListHolder()
Definition: SCR_ArsenalManagerComponent.c:79
OnDelete
override void OnDelete(IEntity owner)
Definition: SCR_ArsenalManagerComponent.c:877
OnPlayerChangedFaction
protected void OnPlayerChangedFaction(int playerId, SCR_PlayerFactionAffiliationComponent playerFactionAffiliation, Faction faction)
Definition: SCR_ArsenalManagerComponent.c:85
SCR_EditableEntityUIInfo
Definition: SCR_EditableEntityUIInfo.c:2
desc
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
Definition: SCR_RespawnBriefingComponent.c:17
DoSetPlayerLoadout
protected void DoSetPlayerLoadout(int playerId, string loadoutString, GameEntity characterEntity, SCR_EArsenalSupplyCostType arsenalSupplyType)
Definition: SCR_ArsenalManagerComponent.c:741
RplRpc
SCR_AchievementsHandlerClass ScriptComponentClass RplRpc(RplChannel.Reliable, RplRcver.Owner)] void UnlockOnClient(AchievementId achievement)
Definition: SCR_AchievementsHandler.c:11
func
func
Definition: SCR_AIThreatSystem.c:5
SCR_EntityCatalogLoadoutData
Definition: SCR_EntityCatalogLoadoutData.c:6
GetPlayerController
proto external PlayerController GetPlayerController()
Definition: SCR_PlayerDeployMenuHandlerComponent.c:307
EEditableEntityBudget
EEditableEntityBudget
Definition: EEditableEntityBudget.c:1
GetPlayerLoadoutData
protected SCR_PlayerLoadoutData GetPlayerLoadoutData(GameEntity characterEntity)
Definition: SCR_ArsenalManagerComponent.c:552
m_sArsenalSaveTypeInfoHolder
protected ResourceName m_sArsenalSaveTypeInfoHolder
Definition: SCR_ArsenalManagerComponent.c:38
SCR_LoadoutSaveBlackListHolder
Definition: SCR_LoadoutSaveBlackListHolder.c:2
GetGameMode
SCR_BaseGameMode GetGameMode()
Definition: SCR_BaseGameModeComponent.c:15
ENotification
ENotification
Definition: ENotification.c:4
SCR_WeaponLoadoutData
Definition: SCR_PlayerLoadoutData.c:1
DoPlayerClearHasLoadout
protected void DoPlayerClearHasLoadout(int playerId)
Definition: SCR_ArsenalManagerComponent.c:834
Attribute
typedef Attribute
Post-process effect of scripted camera.
GetPlayerArsenalLoadout
bool GetPlayerArsenalLoadout(string playerUID, out SCR_ArsenalPlayerLoadout playerLoadout)
Definition: SCR_ArsenalManagerComponent.c:169
SCR_ArsenalManagerComponent_OnPlayerLoadoutChanged
func SCR_ArsenalManagerComponent_OnPlayerLoadoutChanged
Definition: SCR_ArsenalManagerComponent.c:10
m_OnPlayerLoadoutUpdated
protected ref ScriptInvokerBase< SCR_ArsenalManagerComponent_OnPlayerLoadoutChanged > m_OnPlayerLoadoutUpdated
Definition: SCR_ArsenalManagerComponent.c:50
s_Instance
SCR_ArsenalManagerComponentClass s_Instance
OnPostInit
override void OnPostInit(IEntity owner)
Editable Mine.
Definition: SCR_ArsenalManagerComponent.c:858
m_bLocalPlayerLoadoutData
ref SCR_PlayerLoadoutData m_bLocalPlayerLoadoutData
Definition: SCR_ArsenalManagerComponent.c:56
m_bLocalPlayerLoadoutAvailable
protected bool m_bLocalPlayerLoadoutAvailable
Definition: SCR_ArsenalManagerComponent.c:55
SCR_EntityBudgetValue
Definition: SCR_EntityBudgetValue.c:2
loadoutData
ref SCR_PlayerLoadoutData loadoutData
Definition: SCR_ArsenalManagerComponent.c:3
GetOnLoadoutUpdated
ScriptInvokerBase< SCR_ArsenalManagerComponent_OnPlayerLoadoutChanged > GetOnLoadoutUpdated()
Definition: SCR_ArsenalManagerComponent.c:159
EOnInit
override void EOnInit(IEntity owner)
Definition: SCR_ArsenalManagerComponent.c:843
SCR_BaseContainerTools
Definition: SCR_BaseContainerTools.c:3
Faction
Definition: Faction.c:12
SetPlayerArsenalLoadout
void SetPlayerArsenalLoadout(int playerId, GameEntity characterEntity, SCR_ArsenalComponent arsenalComponent, SCR_EArsenalSupplyCostType arsenalSupplyType)
Definition: SCR_ArsenalManagerComponent.c:519
SCR_PlayerFactionAffiliationComponent
Definition: SCR_PlayerFactionAffiliationComponent.c:16
SCR_Global
Definition: Functions.c:6
SCR_EntityCatalog
Definition: SCR_EntityCatalog.c:181
ComputeStorage
protected void ComputeStorage(notnull SCR_JsonLoadContext context, notnull SCR_Faction faction, notnull SCR_ArsenalPlayerLoadout playerLoadout, string storageName, SCR_EArsenalSupplyCostType arsenalSupplyType)
Definition: SCR_ArsenalManagerComponent.c:638
data
Get all prefabs that have the spawner data
Definition: SCR_EntityCatalogManagerComponent.c:305
params
Configs ServerBrowser KickDialogs params
Definition: SCR_NotificationSenderComponent.c:24
SCR_PlayerArsenalLoadout
Definition: SCR_PlayerArsenalLoadout.c:2
SCR_FactionManager
void SCR_FactionManager(IEntitySource src, IEntity parent)
Definition: SCR_FactionManager.c:461
CanSaveLoadout
protected bool CanSaveLoadout(int playerId, notnull GameEntity characterEntity, FactionAffiliationComponent playerFactionAffiliation, SCR_ArsenalComponent arsenalComponent, bool sendNotificationOnFailed)
Definition: SCR_ArsenalManagerComponent.c:361
GetArsenalSaveTypeInfoHolder
SCR_ArsenalSaveTypeInfoHolder GetArsenalSaveTypeInfoHolder()
Definition: SCR_ArsenalManagerComponent.c:72
OnPlayerAuditSuccess
override protected void OnPlayerAuditSuccess(int playerId)
Definition: SCR_ArsenalManagerComponent.c:776
SCR_ArsenalComponent
Definition: SCR_ArsenalComponent.c:9
SetLoadoutBlackListActiveStates
void SetLoadoutBlackListActiveStates(notnull array< bool > orderedActiveStates, bool clearExistingLoadouts, int editorPlayerIdClearedLoadout=-1)
Definition: SCR_ArsenalManagerComponent.c:108
m_fLoadoutSpawnSupplyCostMultiplier
protected float m_fLoadoutSpawnSupplyCostMultiplier
Definition: SCR_ArsenalManagerComponent.c:59
SCR_ArsenalItem
Definition: SCR_ArsenalItem.c:2
SCR_BasePlayerLoadout
Definition: SCR_BasePlayerLoadout.c:2
SCR_BaseGameModeComponentClass
Definition: SCR_BaseGameModeComponent.c:2
m_ArsenalSaveTypeInfoHolder
protected ref SCR_ArsenalSaveTypeInfoHolder m_ArsenalSaveTypeInfoHolder
Definition: SCR_ArsenalManagerComponent.c:52
SCR_Faction
Definition: SCR_Faction.c:6
ComputeStorageEntity
protected void ComputeStorageEntity(notnull SCR_JsonLoadContext context, notnull SCR_Faction faction, notnull SCR_ArsenalPlayerLoadout playerLoadout, string entityName, SCR_EArsenalSupplyCostType arsenalSupplyType)
Definition: SCR_ArsenalManagerComponent.c:689
SCR_EntityCatalogEntry
Definition: SCR_EntityCatalogEntry.c:5
SCR_ArsenalManagerComponentClass
Definition: SCR_ArsenalManagerComponent.c:13
SCR_CampaignMilitaryBaseComponent
Definition: SCR_CampaignMilitaryBaseComponent.c:38
category
params category
Definition: SCR_VehicleDamageManagerComponent.c:180
SCR_BaseGameModeComponent
void SCR_BaseGameModeComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
Definition: SCR_BaseGameModeComponent.c:199