Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_ArsenalManagerComponent.c
Go to the documentation of this file.
3 string loadout;
5 float suppliesCost = 0.0;
7 SCR_ECharacterRank m_eRequiredRank;
8}
9
11enum SCR_EArsenalTypes
12{
13 STATIC_ENTITIES = 1 << 0,
14 VEHICLES = 1 << 1,
15 GADGETS = 1 << 2,
16}
17
18//~ Scriptinvokers
19void SCR_ArsenalManagerComponent_OnPlayerLoadoutChanged(int playerId, bool hasValidLoadout);
21
22[ComponentEditorProps(category: "GameScripted/GameMode", description: "")]
27
28class SCR_ArsenalManagerComponent : SCR_BaseGameModeComponent
29{
30 protected static SCR_ArsenalManagerComponent s_Instance;
31
32 [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")]
34
35 [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")]
37
38 [Attribute()]
39 protected bool m_bDisable
40
41 //=== Authority
43
44 //=== Broadcast
45 protected ref ScriptInvokerBase<SCR_ArsenalManagerComponent_OnPlayerLoadoutChanged> m_OnPlayerLoadoutUpdated = new ScriptInvokerBase<SCR_ArsenalManagerComponent_OnPlayerLoadoutChanged>();
46
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: "0 inf"), RplProp(onRplName: "OnLoadoutSpawnSupplyCostMultiplierChanged")]
60
61 [RplProp(onRplName: "OnArsenalGameModeTypeChanged"), Attribute("-1", desc: "This value dictates which arsenal items are available in the gamemode. UNRESTRICTED means there are no restrictions and all items with an ArsenalItem data in the catalog manager", uiwidget: UIWidgets.SearchComboBox, enums: SCR_Enum.GetList(SCR_EArsenalGameModeType, new ParamEnum("UNRESTRICTED", "-1")))]
63
64 [Attribute("{39B145760CDDFF59}Configs/Arsenal/ArsenalGameModeUIData.conf", desc: "Holds a list of all Arsenal Game Mode data types. Any entry in here will be displayed in the Editor attributes and can be set.", params: "conf class=SCR_ArsenalGameModeUIDataHolder")]
66
67 [RplProp(onRplName: "OnArsenalTypeEnabledChanged"), Attribute(SCR_Enum.GetFlagValues(SCR_EArsenalTypes).ToString(), desc: "This determinds if arsenals are enabled on All entities or non-vehicle only", uiwidget: UIWidgets.Flags, enums: ParamEnumArray.FromEnum(SCR_EArsenalTypes))]
68 protected SCR_EArsenalTypes m_eArsenalTypesEnabled;
69
70 [Attribute(desc: "Items can be ranked locked if true. Conflict functionality only.")]
71 protected bool m_bRankLockedItems;
72
73 [Attribute(desc: "Link to config that holds military supply allocation data", params: "conf class=SCR_MilitarySupplyAllocationConfig")]
75
76 [Attribute("0", desc: "Items consume Military Supply Allocation if true")]
78
79 [Attribute("1", desc: "Multiplier of refund value for items that belong to the same faction as Arsenal.", params: "0 1 0.01")]
81
82 [Attribute("1", desc: "Multiplier of refund value for items belonging to different faction from Arsenal.", params: "0 1 0.01")]
84
86
87 //------------------------------------------------------------------------------------------------
88 static void GetArsenalLoadoutComponentsToCheck(out array<typename> componentsToCheck)
89 {
90 componentsToCheck = {
94 ClothNodeStorageComponent,
95 SCR_EquipmentStorageComponent,
96 SCR_WeaponAttachmentsStorageComponent,
98 };
99 }
100
101 //------------------------------------------------------------------------------------------------
104 static bool GetArsenalManager(out SCR_ArsenalManagerComponent arsenalManager)
105 {
106 arsenalManager = s_Instance;
107 return s_Instance != null;
108 }
109
110 //------------------------------------------------------------------------------------------------
116 static float GetItemRefundAmount(notnull IEntity item, SCR_ArsenalComponent arsenalComponent, bool mustHaveSupplyStorage, out bool isSupplyStorageAvailable = true)
117 {
118 isSupplyStorageAvailable = !mustHaveSupplyStorage;
119
120 //~ Get prefab data
121 EntityPrefabData prefabData = item.GetPrefabData();
122 if (!prefabData)
123 return -1;
124
125 //~ Get prefab
126 ResourceName itemPrefab = prefabData.GetPrefabName();
127 if (itemPrefab.IsEmpty())
128 return -1;
129
130 SCR_EntityCatalogManagerComponent entityCatalogManager = SCR_EntityCatalogManagerComponent.GetInstance();
131 if (!entityCatalogManager)
132 return -1;
133
134 SCR_Faction faction;
135 SCR_EArsenalSupplyCostType supplyCostType = SCR_EArsenalSupplyCostType.DEFAULT;
136 float refundMultiplier = 1;
137
138 SCR_ResourceGenerator generator;
139
140 if (arsenalComponent)
141 {
142 //~ Does not use supplies
143 if (!arsenalComponent.IsArsenalUsingSupplies())
144 return -1;
145
146 faction = arsenalComponent.GetAssignedFaction();
147 supplyCostType = arsenalComponent.GetSupplyCostType();
148
149 SCR_ResourceComponent resourceComponent = SCR_ResourceComponent.Cast(arsenalComponent.GetOwner().FindComponent(SCR_ResourceComponent));
150 if (resourceComponent)
151 {
152 generator = resourceComponent.GetGenerator(EResourceGeneratorID.DEFAULT, EResourceType.SUPPLIES);
153 if (generator)
154 refundMultiplier = generator.GetResourceMultiplier();
155 }
156 }
157 //~ No arsenal so so supply storage
158 else if (mustHaveSupplyStorage)
159 {
160 return -1;
161 }
162 //~ No arsenal so check if supplies are enabled or not globally
163 else if (!SCR_ResourceSystemHelper.IsGlobalResourceTypeEnabled())
164 {
165 return -1;
166 }
167
168 //~ No generator so no storage
169 if (!generator && mustHaveSupplyStorage)
170 return -1;
171
172 //~ The total item refund amount
173 set<IEntity> countedItems = new set<IEntity>();
174 float refundAmount = GetItemRefundCost(countedItems, item, entityCatalogManager, supplyCostType, refundMultiplier, faction);
175
176 //~ Refund amount is invalid
177 if (refundAmount < 0)
178 return -1;
179
180 //~ Get stored Items refund amount
181 refundAmount += GetStoredItemsRefundAmount(countedItems, item, entityCatalogManager, supplyCostType, refundMultiplier, faction);
182
183 //~ Can the supplies be stored?
184 if (mustHaveSupplyStorage)
185 {
186 isSupplyStorageAvailable = refundAmount == 0;
187
188 if (refundAmount > 0 && generator)
189 isSupplyStorageAvailable = refundAmount > 0 && generator.GetAggregatedResourceValue() + refundAmount <= generator.GetAggregatedMaxResourceValue();
190 }
191
192 return refundAmount;
193 }
194
195 //------------------------------------------------------------------------------------------------
196 static protected int GetItemRefundCost(notnull inout set<IEntity> countedItems, notnull IEntity item, notnull SCR_EntityCatalogManagerComponent entityCatalogManager, SCR_EArsenalSupplyCostType supplyCostType, float refundMultiplier, SCR_Faction faction, bool minusIfInvalid = true)
197 {
198 if (countedItems.Contains(item))
199 return 0;
200
201 //~ Get prefab data
202 EntityPrefabData prefabData = item.GetPrefabData();
203 if (!prefabData)
204 return minusIfInvalid * -1;
205
206 ResourceName itemPrefab = prefabData.GetPrefabName();
207 if (itemPrefab.IsEmpty())
208 return minusIfInvalid * -1;
209
210 //~ Could not find the base entry
211 SCR_EntityCatalogEntry entry = entityCatalogManager.GetEntryWithPrefabFromAnyCatalog(EEntityCatalogType.ITEM, itemPrefab, faction);
212 if (!entry)
213 return minusIfInvalid * -1;
214
215 array<SCR_BaseEntityCatalogData> entityDataList = {};
216 if (entry.GetEntityDataList(entityDataList) <= 0)
217 return minusIfInvalid * -1;
218
219 SCR_ArsenalManagerComponent arsenalManagerComponent;
220 if (!GetArsenalManager(arsenalManagerComponent))
221 return minusIfInvalid * -1;
222
223 // Adjust refund multiplier based on arsenal and item factions
224 if (entry.GetCatalogParent() == entityCatalogManager.GetFactionEntityCatalogOfType(EEntityCatalogType.ITEM, faction.GetFactionKey()))
225 refundMultiplier *= arsenalManagerComponent.m_fRefundSameFactionItemMultiplier;
226 else
227 refundMultiplier *= arsenalManagerComponent.m_fRefundDifferentFactionItemMultiplier;
228
229 SCR_ArsenalItem arsenalData;
230 SCR_NonArsenalItemCostCatalogData nonArsenalData;
231
232 float refundAmount;
233
234 //~ Get refund amount of entry
235 foreach (SCR_BaseEntityCatalogData data : entityDataList)
236 {
237 arsenalData = SCR_ArsenalItem.Cast(data);
238 if (arsenalData)
239 {
240 refundAmount = SCR_ResourceSystemHelper.RoundRefundSupplyAmount(arsenalData.GetSupplyRefundAmount(supplyCostType, false) * refundMultiplier);
241 countedItems.Insert(item);
242 break;
243 }
244
245 nonArsenalData = SCR_NonArsenalItemCostCatalogData.Cast(data);
246 if (nonArsenalData)
247 {
248 refundAmount = SCR_ResourceSystemHelper.RoundRefundSupplyAmount(nonArsenalData.GetSupplyCost(supplyCostType, false) * refundMultiplier);
249 countedItems.Insert(item);
250 break;
251 }
252 }
253
254 //~ Get attachments refund amount if the item is a weapon
255 if (arsenalData && (arsenalData.GetItemMode() == SCR_EArsenalItemMode.WEAPON || arsenalData.GetItemMode() == SCR_EArsenalItemMode.WEAPON_VARIANTS))
256 {
257 array<Managed> attachments = {};
258 item.FindComponents(AttachmentSlotComponent, attachments);
259
260 IEntity attachedEntity;
261 ResourceName attachmentPrefab;
262
263 AttachmentSlotComponent attachment;
264
265 foreach (Managed managed : attachments)
266 {
267 attachment = AttachmentSlotComponent.Cast(managed);
268 if (!attachment)
269 continue;
270
271 attachedEntity = attachment.GetAttachedEntity();
272 if (!attachedEntity)
273 continue;
274
275 prefabData = attachedEntity.GetPrefabData();
276 if (!prefabData)
277 continue;
278
279 attachmentPrefab = prefabData.GetPrefabName();
280 if (attachmentPrefab.IsEmpty())
281 continue;
282
283 entry = entityCatalogManager.GetEntryWithPrefabFromAnyCatalog(EEntityCatalogType.ITEM, attachmentPrefab, faction);
284 if (!entry)
285 continue;
286
287 if (entry.GetEntityDataList(entityDataList) <= 0)
288 continue;
289
290 //~ Get the supply cost of attachment
291 foreach (SCR_BaseEntityCatalogData data : entityDataList)
292 {
293 arsenalData = SCR_ArsenalItem.Cast(data);
294 if (arsenalData)
295 {
296 refundAmount += SCR_ResourceSystemHelper.RoundRefundSupplyAmount(arsenalData.GetSupplyRefundAmount(supplyCostType, false) * refundMultiplier);
297 countedItems.Insert(attachedEntity);
298 break;
299 }
300
301 nonArsenalData = SCR_NonArsenalItemCostCatalogData.Cast(data);
302 if (nonArsenalData)
303 {
304 refundAmount += SCR_ResourceSystemHelper.RoundRefundSupplyAmount(nonArsenalData.GetSupplyCost(supplyCostType, false) * refundMultiplier);
305 countedItems.Insert(attachedEntity);
306 break;
307 }
308 }
309 }
310 }
311
312 return refundAmount;
313 }
314
315 //------------------------------------------------------------------------------------------------
316 //~ Gets all item in storage and calculate the refund amount.
317 static protected int GetStoredItemsRefundAmount(notnull inout set<IEntity> countedItems, notnull IEntity item, notnull SCR_EntityCatalogManagerComponent entityCatalogManager, SCR_EArsenalSupplyCostType supplyCostType, float refundMultiplier, SCR_Faction faction)
318 {
319 BaseInventoryStorageComponent inventoryStorage = BaseInventoryStorageComponent.Cast(item.FindComponent(BaseInventoryStorageComponent));
320 if (!inventoryStorage)
321 return 0;
322
323 array<IEntity> storedItems = {};
324 inventoryStorage.GetAll(storedItems);
325
326 int storedItemRefundAmount;
327
328 foreach (IEntity storedItem : storedItems)
329 {
330 storedItemRefundAmount += GetItemRefundCost(countedItems, storedItem, entityCatalogManager, supplyCostType, refundMultiplier, faction, false);
331
332 //~ Get stored item refund amount
333 storedItemRefundAmount += GetStoredItemsRefundAmount(countedItems, storedItem, entityCatalogManager, supplyCostType, refundMultiplier, faction);
334 }
335
336 return storedItemRefundAmount;
337 }
338
339 //------------------------------------------------------------------------------------------------
344 static void OnItemRefunded_S(notnull IEntity item, notnull PlayerController playerController, SCR_ArsenalComponent arsenal)
345 {
346 SCR_ArsenalManagerComponent arsenalManager;
347 if (!GetArsenalManager(arsenalManager))
348 return;
349
350 //~ Only execute if has player controller and if server
351 if ((arsenalManager && !arsenalManager.GetGameMode().IsMaster()) || (!arsenalManager && Replication.IsClient()))
352 return;
353
354 SCR_ArsenalRefundEffectComponent arsenalRefundEffectComp = SCR_ArsenalRefundEffectComponent.Cast(item.FindComponent(SCR_ArsenalRefundEffectComponent));
355 if (!arsenalRefundEffectComp)
356 return;
357
358 //~ Get Prefab class data
359 SCR_ArsenalRefundEffectComponentClass arsenalRefundEffectClass = SCR_ArsenalRefundEffectComponentClass.Cast(arsenalRefundEffectComp.GetComponentData(arsenalRefundEffectComp.GetOwner()));
360 if (!arsenalRefundEffectClass)
361 return;
362
363 arsenalRefundEffectClass.ExecuteFirstValidRefundEffect(item, playerController, arsenal);
364 }
365
366 //------------------------------------------------------------------------------------------------
368 SCR_EArsenalTypes GetEnabledArsenalTypes()
369 {
371 }
372
373 //------------------------------------------------------------------------------------------------
375 static bool IsArsenalTypeEnabled_Static(SCR_EArsenalTypes arsenalType)
376 {
377 SCR_ArsenalManagerComponent arsenalManager;
378
379 if (!GetArsenalManager(arsenalManager))
380 return false;
381
382 return arsenalManager.IsArsenalTypeEnabled(arsenalType);
383 }
384
385 //------------------------------------------------------------------------------------------------
387 bool IsArsenalTypeEnabled(SCR_EArsenalTypes arsenalType)
388 {
389 return SCR_Enum.HasFlag(m_eArsenalTypesEnabled, arsenalType);
390 }
391
392 //------------------------------------------------------------------------------------------------
396 void SetEnabledArsenalTypes(SCR_EArsenalTypes newEnabledArsenalTypes, int playerID = -1)
397 {
398 if (newEnabledArsenalTypes == m_eArsenalTypesEnabled)
399 return;
400
401 //~ Server only
403 if ((gameMode && !gameMode.IsMaster()) || (!gameMode && Replication.IsClient()))
404 return;
405
406 m_eArsenalTypesEnabled = newEnabledArsenalTypes;
407
408 if (playerID > 0)
409 SCR_NotificationsComponent.SendToEveryone(ENotification.EDITOR_ATTRIBUTES_CHANGED_ARSENAL_TYPE_ENABLED, playerID);
410
411 Replication.BumpMe();
412
413 if ((gameMode && gameMode.IsMaster()) || (!gameMode && Replication.IsServer()))
415 }
416
417 //------------------------------------------------------------------------------------------------
420 {
421 return m_bRankLockedItems;
422 }
423
424 //------------------------------------------------------------------------------------------------
425 static bool IsMilitarySupplyAllocationEnabled()
426 {
427 SCR_ArsenalManagerComponent arsenalManager;
428
429 if (!GetArsenalManager(arsenalManager))
430 return false;
431
432 return arsenalManager.m_bUseMilitarySupplyAllocation;
433 }
434
435 //------------------------------------------------------------------------------------------------
447
448 //------------------------------------------------------------------------------------------------
449 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
455
456 //------------------------------------------------------------------------------------------------
465
466 //------------------------------------------------------------------------------------------------
472
473 //------------------------------------------------------------------------------------------------
479
480 //------------------------------------------------------------------------------------------------
485
486 //------------------------------------------------------------------------------------------------
492
493 //------------------------------------------------------------------------------------------------
495 static SCR_EArsenalGameModeType GetArsenalGameModeType_Static()
496 {
497 SCR_ArsenalManagerComponent arsenalManager;
498
499 if (!GetArsenalManager(arsenalManager))
500 return -1;
501
502 return arsenalManager.GetArsenalGameModeType();
503 }
504
505 //------------------------------------------------------------------------------------------------
511
512 //------------------------------------------------------------------------------------------------
515 void SetArsenalGameModeType_S(SCR_EArsenalGameModeType arsenalGameModeType, int playerID = 0)
516 {
517 //~ Server only
519 if ((gameMode && !gameMode.IsMaster()) || (!gameMode && Replication.IsClient()))
520 return;
521
522 //~ Set Unrestricted
523 if (arsenalGameModeType <= 0)
524 arsenalGameModeType = -1;
525
526 //~ Send notification
527 if (playerID > 0)
528 SCR_NotificationsComponent.SendToEveryone(ENotification.EDITOR_ATTRIBUTES_CHANGED_ARSENAL_GAMEMODE_TYPE, playerID, arsenalGameModeType);
529
530 m_eArsenalGameModeType = arsenalGameModeType;
531 Replication.BumpMe();
532
533 if ((gameMode && gameMode.IsMaster()) || (!gameMode && Replication.IsServer()))
535 }
536
537 //------------------------------------------------------------------------------------------------
541 {
543 {
544 Print("Arsenal Manager is missing the 'm_ArsenalGameModeUIDataHolder'!", LogLevel.WARNING);
545
546 SCR_UIInfo unknown = new SCR_UIInfo();
547 unknown.SetName("MISSING");
548 return unknown;
549 }
550
551 return m_ArsenalGameModeUIDataHolder.GetArsenalGameModeUIInfo(arsenalGameModeType);
552 }
553
554 //------------------------------------------------------------------------------------------------
557 int GetArsenalGameModeUIInfoList(inout notnull array<SCR_ArsenalGameModeUIData> arsenalGameModeTypeUIInfoList)
558 {
559 arsenalGameModeTypeUIInfoList.Clear();
560
562 {
563 Print("Arsenal Manager is missing the 'm_ArsenalGameModeUIDataHolder'!", LogLevel.WARNING);
564 return 0;
565 }
566
567 return m_ArsenalGameModeUIDataHolder.GetArsenalGameModeUIInfoList(arsenalGameModeTypeUIInfoList);
568 }
569
570 //------------------------------------------------------------------------------------------------
575
576 //------------------------------------------------------------------------------------------------
582
583 //------------------------------------------------------------------------------------------------
589
590 //------------------------------------------------------------------------------------------------
595 void SetLoadoutBlackListActiveStates(notnull array<bool> orderedActiveStates, bool clearExistingLoadouts, int editorPlayerIdClearedLoadout = -1)
596 {
598 return;
599
600 if (editorPlayerIdClearedLoadout > 0)
601 SCR_NotificationsComponent.SendToEveryone(ENotification.EDITOR_CHANGED_LOADOUT_SAVE_BLACKLIST, editorPlayerIdClearedLoadout);
602
603 m_LoadoutSaveBlackListHolder.SetOrderedBlackListsActive(orderedActiveStates);
604
605 //~ Clear existing loadouts
606 if (clearExistingLoadouts)
607 {
608 //~ Clear local loadout
609 Rpc(RPC_OnPlayerLoadoutCleared, editorPlayerIdClearedLoadout);
610 RPC_OnPlayerLoadoutCleared(editorPlayerIdClearedLoadout);
611
612 //~ Clear existing loadouts on server
613 m_aPlayerLoadouts.Clear();
614 }
615 }
616
617 //------------------------------------------------------------------------------------------------
618 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
619 protected void RPC_OnPlayerLoadoutCleared(int playerIdClearedLoadout)
620 {
622 return;
623
624 //~ No local loadout available anymore
626
627 //~ Player loadout was cleared. This can happen when respawn menu is open and needs to be refreshed
629
630 //~ Send notification to player to inform them their loadout was cleared
631 if (playerIdClearedLoadout > 0)
632 SCR_NotificationsComponent.SendLocal(ENotification.PLAYER_LOADOUT_CLEARED_BY_EDITOR);
633 else
634 SCR_NotificationsComponent.SendLocal(ENotification.PLAYER_LOADOUT_CLEARED);
635 }
636
637 //------------------------------------------------------------------------------------------------
638 [Friend(SCR_PlayerLoadoutComponent)]
639 protected void SetLocalPlayerLoadoutAvailable(bool available)
640 {
642 }
643
644 //------------------------------------------------------------------------------------------------
647 {
649 return false;
650
651 Faction faction = SCR_FactionManager.SGetLocalPlayerFaction();
652 if (!faction)
653 return false;
654
655 return m_LocalPlayerLoadoutData.FactionIndex == GetGame().GetFactionManager().GetFactionIndex(faction);
656 }
657
658 //------------------------------------------------------------------------------------------------
659 [Friend(SCR_PlayerLoadoutComponent)]
664
665 //------------------------------------------------------------------------------------------------
667 ScriptInvokerBase<SCR_ArsenalManagerComponent_OnPlayerLoadoutChanged> GetOnLoadoutUpdated()
668 {
670 }
671
672 //------------------------------------------------------------------------------------------------
677 bool GetPlayerArsenalLoadout(UUID playerUID, out SCR_ArsenalPlayerLoadout playerLoadout)
678 {
679 return m_aPlayerLoadouts.Find(playerUID, playerLoadout) && playerLoadout.loadout != string.Empty;
680 }
681
682 //------------------------------------------------------------------------------------------------
686 void SetLoadoutSpawnCostMultiplier_S(float multiplier, int playerID = 0)
687 {
688 //~ Same or invalid values
689 if (m_fLoadoutSpawnSupplyCostMultiplier == multiplier || multiplier < 0)
690 return;
691
693 Replication.BumpMe();
694
695 //~ Notification
696 if (playerID > 0)
697 SCR_NotificationsComponent.SendToEveryone(ENotification.EDITOR_ATTRIBUTES_CHANGED_SPAWN_SUPPLYCOST_MULTIPLIER, playerID, m_fLoadoutSpawnSupplyCostMultiplier * 1000);
698
700 if ((gameMode && gameMode.IsMaster()) || (!gameMode && Replication.IsServer()))
702 }
703
704 //------------------------------------------------------------------------------------------------
707 {
708 if (!SCR_ResourceSystemHelper.IsGlobalResourceTypeEnabled())
709 return 0;
710
712 }
713
714 //------------------------------------------------------------------------------------------------
720
721 //------------------------------------------------------------------------------------------------
726
727 //------------------------------------------------------------------------------------------------
733
734 //------------------------------------------------------------------------------------------------
744 static float GetLoadoutCalculatedSupplyCost(notnull SCR_BasePlayerLoadout playerLoadout, bool getLocalPlayer, int playerID, SCR_Faction playerFaction, IEntity spawnTarget, out SCR_CampaignMilitaryBaseComponent spawnPointParentBase = null, out SCR_ResourceComponent spawnpointResourceComponent = null)
745 {
746 //~ Check if spawn cost is enabled
747 float multiplier = 1;
748 SCR_ArsenalManagerComponent arsenalManager;
749 if (!GetArsenalManager(arsenalManager))
750 return 0;
751
752 if (spawnTarget)
753 {
754 IEntity parent = spawnTarget;
755
756 //~ Check if spawn target is a base
757 while (parent)
758 {
759 spawnPointParentBase = SCR_CampaignMilitaryBaseComponent.Cast(parent.FindComponent(SCR_CampaignMilitaryBaseComponent));
760
761 if (spawnPointParentBase)
762 break;
763
764 parent = parent.GetParent();
765 }
766
767 if (spawnPointParentBase)
768 spawnpointResourceComponent = spawnPointParentBase.GetResourceComponent();
769 else
770 spawnpointResourceComponent = SCR_ResourceComponent.FindResourceComponent(spawnTarget);
771 }
772
773 multiplier = arsenalManager.GetCalculatedLoadoutSpawnSupplyCostMultiplier();
774
775 //~ Spawn multiplier is 0
776 if (multiplier <= 0)
777 return 0;
778
779 //~ Supplies are disabled
780 if (spawnpointResourceComponent && !spawnpointResourceComponent.IsResourceTypeEnabled())
781 return 0;
782 else if (!spawnpointResourceComponent && !SCR_ResourceSystemHelper.IsGlobalResourceTypeEnabled())
783 return 0;
784
785 float baseMultiplier = 0;
786
787 if (spawnPointParentBase)
788 {
789 if (!spawnPointParentBase.CostSuppliesToSpawn())
790 return 0;
791
792 baseMultiplier = spawnPointParentBase.GetBaseSpawnCostFactor();
793 }
794
795 SCR_PlayerArsenalLoadout playerArsenalLoadout = SCR_PlayerArsenalLoadout.Cast(playerLoadout);
796
797 if (playerArsenalLoadout)
798 {
799 SCR_BaseGameMode gameMode = SCR_BaseGameMode.Cast(GetGame().GetGameMode());
800
801 //~ Local
802 if (getLocalPlayer && arsenalManager.m_LocalPlayerLoadoutData)
803 {
804 if (baseMultiplier > 0)
805 return Math.Clamp(arsenalManager.m_LocalPlayerLoadoutData.LoadoutCost * baseMultiplier, 0, float.MAX);
806 else
807 return Math.Clamp(arsenalManager.m_LocalPlayerLoadoutData.LoadoutCost, 0, float.MAX);
808 }
809 //~ Server
810 else if ((gameMode && gameMode.IsMaster()) || (!gameMode && Replication.IsServer()))
811 {
812 if (baseMultiplier > 0)
813 return Math.Clamp(playerArsenalLoadout.GetLoadoutSuppliesCost(playerID) * baseMultiplier, 0, float.MAX);
814 else
815 return Math.Clamp(playerArsenalLoadout.GetLoadoutSuppliesCost(playerID), 0, float.MAX);
816 }
817
818 //~ No custom loadout found so spawn cost is 0
819 return 0;
820 }
821 //~ Not an arsenal loadout so take cost from catalog
822 else
823 {
824 SCR_EntityCatalogManagerComponent entityCatalogManager = SCR_EntityCatalogManagerComponent.GetInstance();
825 if (!entityCatalogManager)
826 return 0;
827
828 ResourceName loadoutResource = playerLoadout.GetLoadoutResource();
829 if (!loadoutResource)
830 return 0;
831
832 Resource resource = Resource.Load(loadoutResource);
833 if (!resource)
834 return 0;
835
836 SCR_EntityCatalogEntry entry = entityCatalogManager.GetEntryWithPrefabFromAnyCatalog(EEntityCatalogType.CHARACTER, resource.GetResource().GetResourceName(), playerFaction);
837 if (!entry)
838 {
839 Print("Loadout: '" + resource.GetResource().GetResourceName() + "' is not in catalog so supply cost is 0!", LogLevel.WARNING);
840 return 0;
841 }
842
843 SCR_EntityCatalogLoadoutData data = SCR_EntityCatalogLoadoutData.Cast(entry.GetEntityDataOfType(SCR_EntityCatalogLoadoutData));
844 float supplyCost;
845
846 if (data)
847 {
848 supplyCost = data.GetLoadoutSpawnCost();
849 }
850 //~ No data so try to get Campaign budget for supply cost
851 else
852 {
853 Print("Loadout: '" + resource.GetResource().GetResourceName() + "' has no 'SCR_EntityCatalogLoadoutData' assigned in catalog so supply cost is taken from Campaign budget on prefab!", LogLevel.WARNING);
854
855 SCR_EditableEntityUIInfo editableUIInfo = SCR_EditableEntityUIInfo.Cast(entry.GetEntityUiInfo());
856 if (!editableUIInfo)
857 return 0;
858
859 array<ref SCR_EntityBudgetValue> budgets = {};
860
861 if (!editableUIInfo.GetEntityBudgetCost(budgets))
862 return 0;
863
864 //~ Get campaign budget
865 foreach (SCR_EntityBudgetValue budget : budgets)
866 {
867 if (budget.GetBudgetType() == EEditableEntityBudget.CAMPAIGN)
868 {
869 supplyCost = budget.GetBudgetValue();
870 break;
871 }
872 }
873
874 //~ No campaign budget assigned
875 if (supplyCost <= 0)
876 return 0;
877 }
878
879 //~ Add multipliers to the supply cost
880 if (baseMultiplier > 0)
881 return Math.Clamp((supplyCost * multiplier) * baseMultiplier, 0, float.MAX);
882 else
883 return Math.Clamp(supplyCost * multiplier, 0, float.MAX);
884 }
885
886 //~ If all fails set supply cost 0
887 return 0;
888 }
889
890 //------------------------------------------------------------------------------------------------
892 {
894 return 0;
895
896 if (SCR_PlayerController.GetLocalPlayerId() == playerId)
897 {
898 SCR_ArsenalManagerComponent arsenalManager;
899 if (!GetArsenalManager(arsenalManager))
900 return 0;
901
902 SCR_PlayerLoadoutData playerLoadoutData = arsenalManager.m_LocalPlayerLoadoutData;
903 if (!playerLoadoutData)
904 return 0;
905
906 return playerLoadoutData.LoadoutPlayerSupplyAllocationCost;
907 }
908
909 const UUID playerUID = SCR_PlayerIdentityUtils.GetPlayerIdentityId(playerId);
910 SCR_ArsenalPlayerLoadout playerLoadout = m_aPlayerLoadouts.Get(playerUID);
911 if (!playerLoadout)
912 return 0;
913
914 return playerLoadout.m_fMilitarySupplyAllocationCost * GetCalculatedLoadoutSpawnSupplyCostMultiplier();
915 }
916
917 //------------------------------------------------------------------------------------------------
919 {
921 return 0;
922
923 SCR_EntityCatalogManagerComponent entityCatalogManager = SCR_EntityCatalogManagerComponent.GetInstance();
924 if (!entityCatalogManager)
925 return 0;
926
927 ResourceName loadoutResource = playerLoadout.GetLoadoutResource();
928 if (!loadoutResource)
929 return 0;
930
931 Resource resource = Resource.Load(loadoutResource);
932 if (!resource)
933 return 0;
934
935 SCR_EntityCatalogEntry entry = entityCatalogManager.GetEntryWithPrefabFromAnyCatalog(EEntityCatalogType.CHARACTER, resource.GetResource().GetResourceName());
936 if (!entry)
937 {
938 Print("Loadout: '" + resource.GetResource().GetResourceName() + "' is not in catalog so supply cost is 0!", LogLevel.WARNING);
939 return 0;
940 }
941
943 float supplyCost;
944
945 if (data)
946 {
947 supplyCost = data.GetLoadoutSpawnCost();
948 }
949 //~ No data so try to get Campaign budget for supply cost
950 else
951 {
952 Print("Loadout: '" + resource.GetResource().GetResourceName() + "' has no 'SCR_EntityCatalogLoadoutData' assigned in catalog so supply cost is taken from Campaign budget on prefab!", LogLevel.WARNING);
953
955 if (!editableUIInfo)
956 return 0;
957
958 array<ref SCR_EntityBudgetValue> budgets = {};
959
960 if (!editableUIInfo.GetEntityBudgetCost(budgets))
961 return 0;
962
963 //~ Get campaign budget
964 foreach (SCR_EntityBudgetValue budget : budgets)
965 {
966 if (budget.GetBudgetType() == EEditableEntityBudget.CAMPAIGN)
967 {
968 supplyCost = budget.GetBudgetValue();
969 break;
970 }
971 }
972
973 //~ No campaign budget assigned
974 if (supplyCost <= 0)
975 return 0;
976 }
977
979 }
980
981 //------------------------------------------------------------------------------------------------
982 float GetLoadoutMilitarySupplyAllocationCost(notnull SCR_BasePlayerLoadout playerLoadout, int playerId)
983 {
985 return 0;
986
987 SCR_PlayerArsenalLoadout playerArsenalLoadout = SCR_PlayerArsenalLoadout.Cast(playerLoadout);
988 if (playerArsenalLoadout)
990
991 //~ Default loadouts cost the same as their supply cost
993 }
994
995 //------------------------------------------------------------------------------------------------
996 int GetItemMilitarySupplyAllocationCost(ResourceName resource, SCR_ArsenalComponent arsenalComponent, bool addAdditionalCosts = false)
997 {
999 return 0;
1000
1001 SCR_ArsenalItemListConfig overwriteArsenalConfig = arsenalComponent.GetOverwriteArsenalConfig();
1002 bool overwriteArsenalItemUseMSAR;
1003 if (overwriteArsenalConfig && overwriteArsenalConfig.GetUseMilitarySupplyAllocationForPrefab(resource, overwriteArsenalItemUseMSAR) && !overwriteArsenalItemUseMSAR)
1004 return 0;
1005
1006 SCR_EntityCatalogManagerComponent entityCatalogManager = SCR_EntityCatalogManagerComponent.GetInstance();
1007 if (!entityCatalogManager)
1008 return 0;
1009
1010 SCR_EntityCatalogEntry catalogEntry = entityCatalogManager.GetEntryWithPrefabFromAnyCatalog(EEntityCatalogType.ITEM, resource, arsenalComponent.GetAssignedFaction());
1011 if (!catalogEntry)
1012 return 0;
1013
1014 SCR_ArsenalItem arsenalItemData = SCR_ArsenalItem.Cast(catalogEntry.GetEntityDataOfType(SCR_ArsenalItem));
1015 if (!arsenalItemData)
1016 {
1018 if (nonArsenalItemData)
1019 return nonArsenalItemData.GetSupplyCost(SCR_EArsenalSupplyCostType.DEFAULT, addAdditionalCosts);
1020 else
1021 return 0;
1022 }
1023
1024 if (!arsenalItemData.GetUseMilitarySupplyAllocation())
1025 return 0;
1026
1027 return arsenalItemData.GetMilitarySupplyAllocationCost(SCR_EArsenalSupplyCostType.DEFAULT, addAdditionalCosts);
1028 }
1029
1030 //------------------------------------------------------------------------------------------------
1032 {
1034 return 0;
1035
1036 if (!arsenalComponent || !arsenalComponent.IsArsenalUsingSupplies())
1037 return 0;
1038
1039 SCR_Faction faction = arsenalComponent.GetAssignedFaction();
1040 if (!faction)
1041 return 0;
1042
1043 SCR_EntityCatalogManagerComponent entityCatalogManager = SCR_EntityCatalogManagerComponent.GetInstance();
1044 if (!entityCatalogManager)
1045 return 0;
1046
1047 set<IEntity> countedItems = new set<IEntity>();
1048 return GetItemMilitarySupplyAllocationRefundCost(item, countedItems, entityCatalogManager, arsenalComponent, faction);
1049 }
1050
1051 //------------------------------------------------------------------------------------------------
1052 protected int GetItemMilitarySupplyAllocationRefundCost(notnull IEntity item, inout set<IEntity> countedItems, SCR_EntityCatalogManagerComponent entityCatalogManager, SCR_ArsenalComponent arsenalComponent, SCR_Faction faction)
1053 {
1054 if (countedItems.Contains(item))
1055 return 0;
1056
1057 int storedItemRefundAmount;
1058 BaseInventoryStorageComponent inventoryStorage = BaseInventoryStorageComponent.Cast(item.FindComponent(BaseInventoryStorageComponent));
1059 if (inventoryStorage)
1060 {
1061 array<IEntity> storedItems = {};
1062 inventoryStorage.GetAll(storedItems);
1063
1064 foreach (IEntity storedItem : storedItems)
1065 {
1066 storedItemRefundAmount += GetItemMilitarySupplyAllocationRefundCost(storedItem, countedItems, entityCatalogManager, arsenalComponent, faction);
1067 }
1068 }
1069
1070 EntityPrefabData prefabData = item.GetPrefabData();
1071 if (!prefabData)
1072 return storedItemRefundAmount;
1073
1074 ResourceName itemPrefab = prefabData.GetPrefabName();
1075 if (itemPrefab.IsEmpty())
1076 return storedItemRefundAmount;
1077
1078 SCR_EntityCatalogEntry entry = entityCatalogManager.GetEntryWithPrefabFromAnyCatalog(EEntityCatalogType.ITEM, itemPrefab, faction);
1079 if (!entry)
1080 return storedItemRefundAmount;
1081
1082 float refundMultiplier = 1;
1083 // Adjust refund multiplier based on arsenal and item factions
1084 if (entry.GetCatalogParent() == entityCatalogManager.GetFactionEntityCatalogOfType(EEntityCatalogType.ITEM, faction.GetFactionKey()))
1085 refundMultiplier *= m_fRefundSameFactionItemMultiplier;
1086 else
1087 refundMultiplier *= m_fRefundDifferentFactionItemMultiplier;
1088
1089 // Calculate refund cost
1090 int refundCost = SCR_ResourceSystemHelper.RoundRefundSupplyAmount(GetItemMilitarySupplyAllocationCost(itemPrefab, arsenalComponent) * refundMultiplier);
1091 countedItems.Insert(item);
1092
1093 return refundCost + storedItemRefundAmount;
1094 }
1095
1096 //------------------------------------------------------------------------------------------------
1098 {
1100 if (!holder || !holder.IsValid())
1101 return null;
1102
1103 return SCR_MilitarySupplyAllocationConfig.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
1104 }
1105
1106 //------------------------------------------------------------------------------------------------
1107 protected bool CanSaveLoadout(int playerId, notnull GameEntity characterEntity, Faction characterFaction, SCR_ArsenalComponent arsenalComponent, bool sendNotificationOnFailed)
1108 {
1109 //~ Always allow saving if no arsenal component or no restrictions
1110 if (!arsenalComponent || (arsenalComponent.GetArsenalSaveType() == SCR_EArsenalSaveType.NO_RESTRICTIONS && (!m_LoadoutSaveBlackListHolder || m_LoadoutSaveBlackListHolder.GetBlackListsCount() == 0)))
1111 return true;
1112
1113 SCR_Faction playerFaction = SCR_Faction.Cast(characterFaction);
1114 if (playerFaction && !playerFaction.IsCustomLoadoutSupported())
1115 {
1116 if (sendNotificationOnFailed)
1117 SCR_NotificationsComponent.SendToPlayer(playerId, ENotification.PLAYER_LOADOUT_NOT_SAVED);
1118
1119 return false;
1120 }
1121
1122 SCR_InventoryStorageManagerComponent characterInventory = SCR_InventoryStorageManagerComponent.Cast(characterEntity.FindComponent(SCR_InventoryStorageManagerComponent));
1123 if (!characterInventory)
1124 {
1125 Print("'SCR_ArsenalManagerComponent' is checking 'CanSaveArsenal()' but character has no inventory manager!", LogLevel.ERROR);
1126
1127 if (sendNotificationOnFailed)
1128 SCR_NotificationsComponent.SendToPlayer(playerId, ENotification.PLAYER_LOADOUT_NOT_SAVED);
1129
1130 return false;
1131 }
1132
1133 array<SCR_EntityCatalog> itemCatalogs = {};
1134 SCR_ArsenalInventoryStorageManagerComponent arsenalInventory;
1135
1136 //~ Check either faction or arsenal inventory if item is in it
1137 if (arsenalComponent.GetArsenalSaveType() == SCR_EArsenalSaveType.FACTION_ITEMS_ONLY || arsenalComponent.GetArsenalSaveType() == SCR_EArsenalSaveType.FRIENDLY_AND_FACTION_ITEMS_ONLY || arsenalComponent.GetArsenalSaveType() == SCR_EArsenalSaveType.IN_ARSENAL_ITEMS_ONLY)
1138 {
1139 if (arsenalComponent.GetArsenalSaveType() == SCR_EArsenalSaveType.FACTION_ITEMS_ONLY)
1140 {
1141 //~ Player has no faction
1142 if (!playerFaction)
1143 {
1144 Print("'SCR_ArsenalManagerComponent' is checking 'CanSaveArsenal()' but player has no SCR_Faction, arsenal saving will simply be allowed", LogLevel.WARNING);
1145 return true;
1146 }
1147
1148 SCR_EntityCatalog itemCatalog = playerFaction.GetFactionEntityCatalogOfType(EEntityCatalogType.ITEM);
1149 if (!itemCatalog)
1150 {
1151 Print(string.Format("'SCR_ArsenalManagerComponent' is checking 'CanSaveArsenal()' but player faction '%1' has no ITEM catalog!", playerFaction.GetFactionKey()), LogLevel.ERROR);
1152
1153 if (sendNotificationOnFailed)
1154 SCR_NotificationsComponent.SendToPlayer(playerId, ENotification.PLAYER_LOADOUT_NOT_SAVED);
1155
1156 return false;
1157 }
1158 else
1159 {
1160 itemCatalogs.Insert(itemCatalog);
1161 }
1162 }
1163 else if (arsenalComponent.GetArsenalSaveType() == SCR_EArsenalSaveType.FRIENDLY_AND_FACTION_ITEMS_ONLY)
1164 {
1165 //~ Player has no faction
1166 if (!playerFaction)
1167 {
1168 Print("'SCR_ArsenalManagerComponent' is checking 'CanSaveArsenal()' but player has no SCR_Faction, arsenal saving will simply be allowed", LogLevel.WARNING);
1169 return true;
1170 }
1171
1172 array<Faction> friendlyFactions = {};
1173 if (playerFaction.GetFriendlyFactions(friendlyFactions) == 0)
1174 {
1175 if (sendNotificationOnFailed)
1176 SCR_NotificationsComponent.SendToPlayer(playerId, ENotification.PLAYER_LOADOUT_NOT_SAVED);
1177
1178 return false;
1179 }
1180
1181 SCR_Faction scrFaction;
1182 SCR_EntityCatalog itemCatalog;
1183
1184 foreach (Faction faction : friendlyFactions)
1185 {
1186 scrFaction = SCR_Faction.Cast(faction);
1187 if (!scrFaction)
1188 continue;
1189
1190 itemCatalog = scrFaction.GetFactionEntityCatalogOfType(EEntityCatalogType.ITEM);
1191 if (!itemCatalog)
1192 continue;
1193
1194 itemCatalogs.Insert(itemCatalog);
1195 }
1196
1197 if (itemCatalogs.IsEmpty())
1198 {
1199 if (sendNotificationOnFailed)
1200 SCR_NotificationsComponent.SendToPlayer(playerId, ENotification.PLAYER_LOADOUT_NOT_SAVED);
1201
1202 //~ Failed to find any item catalogs
1203 return false;
1204 }
1205 }
1206 else
1207 {
1208 arsenalInventory = arsenalComponent.GetArsenalInventoryComponent();
1209 if (!arsenalInventory)
1210 {
1211 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);
1212 return true;
1213 }
1214 }
1215 }
1216
1217 set<ResourceName> validatedPrefabs = new set<ResourceName>();
1218 array<IEntity> allPlayerItems = {};
1219 characterInventory.GetItems(allPlayerItems, EStoragePurpose.PURPOSE_DEPOSIT | EStoragePurpose.PURPOSE_WEAPON_PROXY);
1220
1221 EntityPrefabData prefabData;
1222 RplComponent itemRplComponent;
1224
1225 int invalidItemCount = 0;
1226 SCR_ECharacterRank requiredRank = SCR_ECharacterRank.RENEGADE;
1227
1228 foreach (IEntity item : allPlayerItems)
1229 {
1230 prefabData = item.GetPrefabData();
1231
1232 //~ Ignore if no prefab data
1233 if (!prefabData)
1234 continue;
1235
1236 //~ Ignore if no prefab resource name
1237 resourceName = prefabData.GetPrefabName();
1238 if (resourceName.IsEmpty())
1239 continue;
1240
1241 //~ Do not check the same prefab twice
1242 if (!validatedPrefabs.Insert(resourceName))
1243 continue;
1244
1245 //~ Check if item is blacklisted if there is a blacklist
1247 {
1248 //~ Item is blackListed so do not allow saving
1249 if (m_LoadoutSaveBlackListHolder.IsPrefabBlacklisted(resourceName))
1250 {
1251 if (sendNotificationOnFailed)
1252 {
1253 itemRplComponent = RplComponent.Cast(item.FindComponent(RplComponent));
1254 if (itemRplComponent)
1255 SCR_NotificationsComponent.SendToPlayer(playerId, ENotification.PLAYER_LOADOUT_ITEM_FAILED_ITEM_BLACKLISTED, itemRplComponent.Id());
1256 }
1257
1258 invalidItemCount++;
1259 continue;
1260 }
1261 }
1262
1263 //~ Check arsenal inventory
1264 if (arsenalInventory)
1265 {
1266 //~ Not in inventory of arsenal so cannot save
1267 if (!arsenalInventory.IsPrefabInArsenalStorage(resourceName))
1268 {
1269 if (sendNotificationOnFailed)
1270 {
1271 itemRplComponent = RplComponent.Cast(item.FindComponent(RplComponent));
1272 if (itemRplComponent)
1273 SCR_NotificationsComponent.SendToPlayer(playerId, ENotification.PLAYER_LOADOUT_ITEM_FAILED_NOT_IN_ARSENAL, itemRplComponent.Id());
1274 }
1275
1276 invalidItemCount++;
1277 continue;
1278 }
1279 }
1280 //~ Check item catalog(s)
1281 else if (!itemCatalogs.IsEmpty())
1282 {
1283 bool itemFound;
1284 SCR_EntityCatalogEntry itemEntry;
1285 foreach (SCR_EntityCatalog itemCatalog : itemCatalogs)
1286 {
1287 itemEntry = itemCatalog.GetEntryWithPrefab(resourceName);
1288 if (itemEntry)
1289 {
1290 itemFound = true;
1291 break;
1292 }
1293 }
1294
1295 if (!itemFound)
1296 {
1297 if (sendNotificationOnFailed)
1298 {
1299 itemRplComponent = RplComponent.Cast(item.FindComponent(RplComponent));
1300 if (itemRplComponent)
1301 SCR_NotificationsComponent.SendToPlayer(playerId, ENotification.PLAYER_LOADOUT_ITEM_FAILED_NOT_FACTION, itemRplComponent.Id());
1302 }
1303
1304 invalidItemCount++;
1305 continue;
1306 }
1307
1308 if (AreItemsRankLocked())
1309 {
1310 SCR_ArsenalItem arsenalItemData = SCR_ArsenalItem.Cast(itemEntry.GetEntityDataOfType(SCR_ArsenalItem));
1311 if (arsenalItemData)
1312 requiredRank = Math.Max(requiredRank, arsenalItemData.GetRequiredRank());
1313 }
1314 }
1315 }
1316
1317 //~ Saving failed because of invalid items
1318 if (invalidItemCount > 0 && sendNotificationOnFailed)
1319 SCR_NotificationsComponent.SendToPlayer(playerId, ENotification.PLAYER_LOADOUT_NOT_SAVED_INVALID_ITEMS, invalidItemCount);
1320
1321 SCR_PlayerController playerController = SCR_PlayerController.Cast(GetGame().GetPlayerManager().GetPlayerController(playerId));
1322 if (playerController && AreItemsRankLocked())
1323 {
1324 SCR_PlayerXPHandlerComponent xpHandler = SCR_PlayerXPHandlerComponent.Cast(playerController.FindComponent(SCR_PlayerXPHandlerComponent));
1325 if (xpHandler && xpHandler.GetPlayerRankByXP() < requiredRank)
1326 {
1327 if (sendNotificationOnFailed)
1328 SCR_NotificationsComponent.SendToPlayer(playerId, ENotification.PLAYER_LOADOUT_NOT_SAVED_INSUFFICIENT_RANK);
1329
1330 return false;
1331 }
1332 }
1333
1334 //~ Check if the player has enough personal supplies allocated for the loadout
1335 if (m_bUseMilitarySupplyAllocation && playerController)
1336 {
1337 SCR_PlayerSupplyAllocationComponent playerSupplyAllocationComponent = SCR_PlayerSupplyAllocationComponent.Cast(playerController.FindComponent(SCR_PlayerSupplyAllocationComponent));
1338 if (playerSupplyAllocationComponent)
1339 {
1340 if (GetCharacterLoadoutSupplyCost(characterEntity, true) > playerSupplyAllocationComponent.GetPlayerMilitarySupplyAllocation())
1341 {
1342 if (sendNotificationOnFailed)
1343 SCR_NotificationsComponent.SendToPlayer(playerId, ENotification.PLAYER_LOADOUT_NOT_SAVED_NOT_ENOUGH_MSA);
1344
1345 return false;
1346 }
1347 }
1348 }
1349
1350 return invalidItemCount == 0;
1351 }
1352
1353 //------------------------------------------------------------------------------------------------
1359 void SetPlayerArsenalLoadout(int playerId, GameEntity characterEntity, SCR_ArsenalComponent arsenalComponent, SCR_EArsenalSupplyCostType arsenalSupplyType)
1360 {
1361 //~ If Not Authority return
1362 if (!GetGameMode().IsMaster())
1363 return;
1364
1365 const UUID playerUID = SCR_PlayerIdentityUtils.GetPlayerIdentityId(playerId);
1366 if (!characterEntity)
1367 {
1368 DoSetPlayerLoadout(playerId, string.Empty, characterEntity, arsenalSupplyType);
1369 return;
1370 }
1371
1372 SCR_PlayerController clientPlayerController = SCR_PlayerController.Cast(GetGame().GetPlayerManager().GetPlayerController(playerId));
1373 if (!clientPlayerController || clientPlayerController.IsPossessing())
1374 return;
1375
1376 string factionKey = SCR_PlayerArsenalLoadout.ARSENALLOADOUT_FACTIONKEY_NONE;
1377 SCR_ChimeraCharacter character = SCR_ChimeraCharacter.Cast(characterEntity);
1378 Faction characterFaction;
1379 if (character)
1380 {
1381 characterFaction = character.GetFaction();
1382 factionKey = characterFaction.GetFactionKey();
1383 }
1384
1385 if (!CanSaveLoadout(playerId, characterEntity, characterFaction, arsenalComponent, true))
1386 return;
1387
1388 auto context = new JsonSaveContext();
1389 if (!context.WriteValue(SCR_PlayerArsenalLoadout.ARSENALLOADOUT_FACTION_KEY, factionKey) || !SCR_PlayerArsenalLoadout.ReadLoadoutString(characterEntity, context))
1390 return;
1391
1392 DoSetPlayerLoadout(playerId, context.SaveToString(), characterEntity, arsenalSupplyType);
1393 }
1394
1395 //------------------------------------------------------------------------------------------------
1396 protected int GetCharacterItemSupplyCost(notnull IEntity item, notnull inout set<IEntity> countedItems, notnull SCR_Faction faction, bool getPersonalSupplyAllocationCost)
1397 {
1398 if (countedItems.Contains(item))
1399 return 0;
1400
1401 int storedItemSupplyCost;
1402 BaseInventoryStorageComponent inventoryStorage = BaseInventoryStorageComponent.Cast(item.FindComponent(BaseInventoryStorageComponent));
1403 if (inventoryStorage)
1404 {
1405 array<IEntity> storedItems = {};
1406 inventoryStorage.GetAll(storedItems);
1407
1408 foreach (IEntity storedItem : storedItems)
1409 {
1410 storedItemSupplyCost += GetCharacterItemSupplyCost(storedItem, countedItems, faction, getPersonalSupplyAllocationCost);
1411 }
1412 }
1413
1414 EntityPrefabData prefabData = item.GetPrefabData();
1415 if (!prefabData)
1416 return storedItemSupplyCost;
1417
1418 ResourceName itemPrefab = prefabData.GetPrefabName();
1419 if (itemPrefab.IsEmpty())
1420 return storedItemSupplyCost;
1421
1422 SCR_EntityCatalogManagerComponent entityCatalogManager = SCR_EntityCatalogManagerComponent.GetInstance();
1423 if (!entityCatalogManager)
1424 return storedItemSupplyCost;
1425
1426 SCR_EntityCatalogEntry entry = entityCatalogManager.GetEntryWithPrefabFromAnyCatalog(EEntityCatalogType.ITEM, itemPrefab, faction);
1427 if (!entry)
1428 return storedItemSupplyCost;
1429
1430 int itemCost;
1432 if (!arsenalItemData)
1433 {
1435 if (nonArsenalItemData)
1436 itemCost = nonArsenalItemData.GetSupplyCost(SCR_EArsenalSupplyCostType.DEFAULT, false);
1437 }
1438 else
1439 {
1440 itemCost = arsenalItemData.GetSupplyCost(SCR_EArsenalSupplyCostType.DEFAULT, false);
1441 if (getPersonalSupplyAllocationCost && !arsenalItemData.GetUseMilitarySupplyAllocation())
1442 return storedItemSupplyCost;
1443 }
1444
1445 if (getPersonalSupplyAllocationCost && !m_bUseMilitarySupplyAllocation)
1446 return storedItemSupplyCost;
1447
1448 return storedItemSupplyCost + itemCost;
1449 }
1450
1451 //------------------------------------------------------------------------------------------------
1455 int GetCharacterLoadoutSupplyCost(notnull GameEntity characterEntity, bool getPersonalSupplyAllocationCost)
1456 {
1457 FactionAffiliationComponent factionAffiliation = FactionAffiliationComponent.Cast(characterEntity.FindComponent(FactionAffiliationComponent));
1458 if (!factionAffiliation)
1459 return 0;
1460
1461 SCR_Faction characterFaction = SCR_Faction.Cast(factionAffiliation.GetAffiliatedFaction());
1462 if (!characterFaction)
1463 return 0;
1464
1465 int loadoutCost;
1466 set<IEntity> countedItems = new set<IEntity>();
1467 array<IEntity> storageEntities = {};
1468
1469 EquipedLoadoutStorageComponent loadoutStorage = EquipedLoadoutStorageComponent.Cast(characterEntity.FindComponent(EquipedLoadoutStorageComponent));
1470 if (loadoutStorage)
1471 {
1472 loadoutStorage.GetAll(storageEntities, true);
1473 foreach (IEntity entity : storageEntities)
1474 {
1475 loadoutCost += GetCharacterItemSupplyCost(entity, countedItems, characterFaction, getPersonalSupplyAllocationCost)
1476 }
1477 }
1478
1479 EquipedWeaponStorageComponent weaponStorage = EquipedWeaponStorageComponent.Cast(characterEntity.FindComponent(EquipedWeaponStorageComponent));
1480 if (weaponStorage)
1481 {
1482 storageEntities.Clear();
1483 weaponStorage.GetAll(storageEntities, true);
1484 foreach (IEntity entity : storageEntities)
1485 {
1486 loadoutCost += GetCharacterItemSupplyCost(entity, countedItems, characterFaction, getPersonalSupplyAllocationCost)
1487 }
1488 }
1489
1490 return loadoutCost;
1491 }
1492
1493 //------------------------------------------------------------------------------------------------
1494 protected SCR_PlayerLoadoutData GetPlayerLoadoutData(GameEntity characterEntity)
1495 {
1497
1498 EquipedLoadoutStorageComponent loadoutStorage = EquipedLoadoutStorageComponent.Cast(characterEntity.FindComponent(EquipedLoadoutStorageComponent));
1499 if (loadoutStorage)
1500 {
1501 int slotsCount = loadoutStorage.GetSlotsCount();
1502 for (int i = 0; i < slotsCount; ++i)
1503 {
1504 InventoryStorageSlot slot = loadoutStorage.GetSlot(i);
1505 if (!slot)
1506 continue;
1507
1508 IEntity attachedEntity = slot.GetAttachedEntity();
1509 if (!attachedEntity)
1510 continue;
1511
1512 ResourceName prefabName;
1513 BaseContainer prefab = attachedEntity.GetPrefabData().GetPrefab();
1514 while (prefabName.IsEmpty() && prefab)
1515 {
1516 prefabName = prefab.GetResourceName();
1517 prefab = prefab.GetAncestor();
1518 }
1519
1520 if (prefabName.IsEmpty())
1521 continue;
1522
1523 SCR_ClothingLoadoutData clothingData = new SCR_ClothingLoadoutData();
1524 clothingData.SlotIdx = i;
1525 clothingData.ClothingPrefab = prefabName;
1526
1527 loadoutData.Clothings.Insert(clothingData);
1528 }
1529 }
1530
1531 const BaseWeaponManagerComponent weaponManager = BaseWeaponManagerComponent.Cast(characterEntity.FindComponent(BaseWeaponManagerComponent));
1532 EquipedWeaponStorageComponent weaponStorage = EquipedWeaponStorageComponent.Cast(characterEntity.FindComponent(EquipedWeaponStorageComponent));
1533 if (weaponStorage)
1534 {
1535 int slotsCount = weaponStorage.GetSlotsCount();
1536 for (int i = 0; i < slotsCount; ++i)
1537 {
1538 InventoryStorageSlot slot = weaponStorage.GetSlot(i);
1539 if (!slot)
1540 continue;
1541
1542 IEntity attachedEntity = slot.GetAttachedEntity();
1543 if (!attachedEntity)
1544 continue;
1545
1546 const ResourceName prefabName = SCR_ResourceNameUtils.GetPrefabName(attachedEntity);
1547 if (prefabName.IsEmpty())
1548 continue;
1549
1550 bool active = false;
1551 if (weaponManager && weaponManager.GetCurrentWeapon())
1552 active = weaponManager.GetCurrentWeapon().GetOwner() == attachedEntity;
1553
1555 weaponData.Active = active;
1556 weaponData.SlotIdx = i;
1557 weaponData.WeaponPrefab = prefabName;
1558
1559 WeaponAttachmentsStorageComponent attachmentsStorage = WeaponAttachmentsStorageComponent.Cast(attachedEntity.FindComponent(WeaponAttachmentsStorageComponent));
1560 if (attachmentsStorage)
1561 {
1562 const int slotCount = attachmentsStorage.GetSlotsCount();
1563 weaponData.Attachments.Reserve(slotCount);
1564 for (int nSlot = 0; nSlot < slotCount; ++nSlot)
1565 {
1566 weaponData.Attachments.Insert(SCR_ResourceNameUtils.GetPrefabName(attachmentsStorage.Get(nSlot)));
1567 }
1568 }
1569
1570 loadoutData.Weapons.Insert(weaponData);
1571 }
1572 }
1573
1574 return loadoutData;
1575 }
1576
1577 //------------------------------------------------------------------------------------------------
1578 protected void ComputeSuppliesCost(notnull SCR_Faction faction, notnull SCR_ArsenalPlayerLoadout playerLoadout, SCR_EArsenalSupplyCostType arsenalSupplyType)
1579 {
1580 playerLoadout.suppliesCost = 0.0;
1581 playerLoadout.m_fMilitarySupplyAllocationCost = 0;
1582
1583 auto context = new JsonLoadContext(false);
1584 if (!context.LoadFromString(playerLoadout.loadout))
1585 return;
1586
1587 context.StartObject(SCR_PlayerArsenalLoadout.ARSENALLOADOUT_KEY);
1588 SCR_PlayerArsenalLoadout.ComputeSuppliesCost(context, faction, playerLoadout, arsenalSupplyType);
1589 }
1590
1591 //------------------------------------------------------------------------------------------------
1592 protected void DoSetPlayerLoadout(int playerId, string loadoutString, GameEntity characterEntity, SCR_EArsenalSupplyCostType arsenalSupplyType)
1593 {
1594 const UUID playerUID = SCR_PlayerIdentityUtils.GetPlayerIdentityId(playerId);
1595 SCR_ArsenalPlayerLoadout playerLoadout;
1596 bool loadoutChanged;
1597 if (!loadoutString.IsEmpty())
1598 {
1599 playerLoadout = m_aPlayerLoadouts.Get(playerUID);
1600 if (!playerLoadout)
1601 playerLoadout = new SCR_ArsenalPlayerLoadout();
1602
1603 loadoutChanged = loadoutString != playerLoadout.loadout;
1604 playerLoadout.loadout = loadoutString;
1605 DoSetPlayerLoadout(playerUID, playerLoadout); // Need to set early for cost calculations below
1606
1607 if (loadoutChanged)
1608 {
1609 FactionAffiliationComponent factionAffiliation = FactionAffiliationComponent.Cast(characterEntity.FindComponent(FactionAffiliationComponent));
1610 if (factionAffiliation && factionAffiliation.GetAffiliatedFaction())
1611 ComputeSuppliesCost(SCR_Faction.Cast(factionAffiliation.GetAffiliatedFaction()), playerLoadout, arsenalSupplyType);
1612
1613 playerLoadout.loadoutData = GetPlayerLoadoutData(characterEntity);
1614 playerLoadout.loadoutData.LoadoutCost = GetCharacterLoadoutSupplyCost(characterEntity, false);
1615 playerLoadout.suppliesCost = playerLoadout.loadoutData.LoadoutCost;
1616 playerLoadout.loadoutData.LoadoutPlayerSupplyAllocationCost = GetCharacterLoadoutSupplyCost(characterEntity, true);
1617 playerLoadout.m_fMilitarySupplyAllocationCost = playerLoadout.loadoutData.LoadoutPlayerSupplyAllocationCost;
1618 playerLoadout.loadoutData.FactionIndex = GetGame().GetFactionManager().GetFactionIndex(SCR_FactionManager.SGetPlayerFaction(playerId));
1619 }
1620 }
1621 else
1622 {
1623 m_aPlayerLoadouts.Remove(playerUID); // Invalid loadout = no loadout
1624 }
1625
1626 SyncPlayerloadout(playerId, playerLoadout, loadoutChanged, true);
1627 }
1628
1629 //------------------------------------------------------------------------------------------------
1630 [Friend(SCR_PlayerLoadoutComponentSerializer)]
1631 protected void DoSetPlayerLoadout(const UUID playerIdentity, SCR_ArsenalPlayerLoadout loadout)
1632 {
1633 m_aPlayerLoadouts.Set(playerIdentity, loadout);
1634 }
1635
1636 //------------------------------------------------------------------------------------------------
1637 [Friend(SCR_PlayerLoadoutComponentSerializer)]
1638 protected void SyncPlayerloadout(int playerId, SCR_ArsenalPlayerLoadout playerLoadout, bool loadoutChanged = true, bool notification = false)
1639 {
1640 PlayerController pc = GetGame().GetPlayerManager().GetPlayerController(playerId);
1641 if (!pc)
1642 return;
1643
1645 if (!loadoutComp)
1646 return;
1647
1648 if (playerLoadout && loadoutChanged)
1649 loadoutComp.DoSendPlayerLoadout(playerLoadout.loadoutData);
1650
1651 const bool loadoutValid = playerLoadout && !playerLoadout.loadout.IsEmpty();
1652 loadoutComp.DoSetPlayerHasLoadout(loadoutValid, loadoutChanged, notification);
1653
1654 m_OnPlayerLoadoutUpdated.Invoke(playerId, loadoutValid);
1655 }
1656
1657 //------------------------------------------------------------------------------------------------
1658 override protected void OnPlayerAuditSuccess(int playerId)
1659 {
1660 super.OnPlayerAuditSuccess(playerId);
1661
1662 const UUID playerUID = SCR_PlayerIdentityUtils.GetPlayerIdentityId(playerId);
1663 SCR_ArsenalPlayerLoadout playerLoadout = m_aPlayerLoadouts.Get(playerUID);
1664 if (!playerLoadout || playerLoadout.loadout.IsEmpty())
1665 return;
1666
1667 SyncPlayerloadout(playerId, playerLoadout);
1668 }
1669
1670 //------------------------------------------------------------------------------------------------
1671 override void EOnInit(IEntity owner)
1672 {
1673 //~ Init item black list (Server only). Call one frame later to make sure catalogs are initalized
1675 GetGame().GetCallqueue().CallLater(m_LoadoutSaveBlackListHolder.Init);
1676 }
1677
1678 //------------------------------------------------------------------------------------------------
1679 override void OnPostInit(IEntity owner)
1680 {
1681 if (s_Instance || SCR_Global.IsEditMode())
1682 return;
1683
1684 SCR_ArsenalManagerComponent.GetArsenalLoadoutComponentsToCheck(SCR_PlayerArsenalLoadout.ARSENALLOADOUT_COMPONENTS_TO_CHECK);
1685
1686 s_Instance = SCR_ArsenalManagerComponent.Cast(GetGameMode().FindComponent(SCR_ArsenalManagerComponent));
1687 SetEventMask(owner, EntityEvent.INIT);
1688
1691 Print("'SCR_ArsenalManagerComponent' failed to loadm_Arsenal GameMode UI Data Holder config!", LogLevel.WARNING);
1692
1693 //~ Get config for saveType holder. This is used by arsenals in the world
1696 Print("'SCR_ArsenalManagerComponent' failed to load Arsenal Save Type Holder config!", LogLevel.ERROR);
1697
1698 //~ Get loadout save blacklist config, Can be null (Server Only)
1699 if (GetGameMode().IsMaster())
1701 }
1702}
1703
1704[BaseContainerProps(configRoot: true)]
1706{
1707 [Attribute(desc: "List of UIInfo for Arsenal GameMode types, Used for editor attributes and notifications. Only types in this list will be displayed in editor")]
1708 protected ref array<ref SCR_ArsenalGameModeUIData> m_aArsenalGameModeTypeUIInfoList;
1709
1710 //------------------------------------------------------------------------------------------------
1714 {
1715 if (arsenalGameModeType <= 0)
1716 arsenalGameModeType = -1;
1717
1718 //~ Get the game mode type
1719 foreach (SCR_ArsenalGameModeUIData data : m_aArsenalGameModeTypeUIInfoList)
1720 {
1721 if (data.m_eArsenalGameModeType == arsenalGameModeType)
1722 return data.m_UIInfo;
1723 }
1724
1725 Print("Cannot find arsenal Game Mode type for '" + typename.EnumToString(SCR_EArsenalGameModeType, arsenalGameModeType) + "'!", LogLevel.WARNING);
1726
1727 SCR_UIInfo unknown = new SCR_UIInfo();
1728 unknown.SetName("MISSING");
1729
1730 return unknown;
1731 }
1732
1733 //------------------------------------------------------------------------------------------------
1736 int GetArsenalGameModeUIInfoList(inout notnull array<SCR_ArsenalGameModeUIData> arsenalGameModeTypeUIInfoList)
1737 {
1738 arsenalGameModeTypeUIInfoList.Clear();
1739
1740 foreach (SCR_ArsenalGameModeUIData data : m_aArsenalGameModeTypeUIInfoList)
1741 {
1742 if (!data)
1743 continue;
1744
1745 arsenalGameModeTypeUIInfoList.Insert(data);
1746 }
1747
1748 return arsenalGameModeTypeUIInfoList.Count();
1749 }
1750}
1751
1753class SCR_ArsenalGameModeUIData
1754{
1755 [Attribute(uiwidget: UIWidgets.SearchComboBox, enums: SCR_Enum.GetList(SCR_EArsenalGameModeType, new ParamEnum("UNRESTRICTED", "-1")))]
1757
1758 [Attribute()]
1759 ref SCR_UIInfo m_UIInfo;
1760}
EEditableEntityBudget
@ VEHICLES
Vehicles and static guns.
EEntityCatalogType
ENotification
ArmaReforgerScripted GetGame()
Definition game.c:1398
ResourceName resourceName
Definition SCR_AIGroup.c:66
enum EAIGroupCombatMode ComponentEditorProps(category:"GameScripted/AI", description:"Component for utility AI system for groups")
SCR_ECharacterRank m_eRequiredRank
bool m_bUseMilitarySupplyAllocation
class SCR_ArsenalPlayerLoadout GADGETS
Arsenals are enabled on gadgets.
SCR_EArsenalTypes m_eArsenalTypesEnabled
void OnArsenalGameModeTypeChanged()
class SCR_ArsenalGameModeUIDataHolder SCR_BaseContainerCustomTitleUIInfo("m_UIInfo")
bool CanSaveLoadout(int playerId, notnull GameEntity characterEntity, Faction characterFaction, SCR_ArsenalComponent arsenalComponent, bool sendNotificationOnFailed)
bool GetLocalPlayerLoadoutAvailable()
ref ScriptInvokerBase< SCR_ArsenalManagerComponent_OnPlayerLoadoutChanged > m_OnPlayerLoadoutUpdated
SCR_LoadoutSaveBlackListHolder GetLoadoutSaveBlackListHolder()
void ComputeSuppliesCost(notnull SCR_Faction faction, notnull SCR_ArsenalPlayerLoadout playerLoadout, SCR_EArsenalSupplyCostType arsenalSupplyType)
void RPC_OnPlayerLoadoutCleared(int playerIdClearedLoadout)
float GetLoadoutMilitarySupplyAllocationCost(notnull SCR_BasePlayerLoadout playerLoadout, int playerId)
float m_fMilitarySupplyAllocationCost
ResourceName m_sLoadoutSaveBlackListHolder
void SetLocalPlayerLoadoutAvailable(bool available)
bool GetPlayerArsenalLoadout(UUID playerUID, out SCR_ArsenalPlayerLoadout playerLoadout)
bool m_bRankLockedItems
ResourceName m_sArsenalSaveTypeInfoHolder
int GetCharacterItemSupplyCost(notnull IEntity item, notnull inout set< IEntity > countedItems, notnull SCR_Faction faction, bool getPersonalSupplyAllocationCost)
float GetCustomLoadoutMilitarySupplyAllocationCost(int playerId)
int GetCharacterLoadoutSupplyCost(notnull GameEntity characterEntity, bool getPersonalSupplyAllocationCost)
void SetPlayerArsenalLoadout(int playerId, GameEntity characterEntity, SCR_ArsenalComponent arsenalComponent, SCR_EArsenalSupplyCostType arsenalSupplyType)
int GetItemMilitarySupplyAllocationRefundCost(notnull IEntity item, inout set< IEntity > countedItems, SCR_EntityCatalogManagerComponent entityCatalogManager, SCR_ArsenalComponent arsenalComponent, SCR_Faction faction)
class SCR_ArsenalPlayerLoadout STATIC_ENTITIES
Used to allow certain arsenal types to be enabled or disabled.
SCR_EArsenalTypes GetEnabledArsenalTypes()
float m_fLoadoutSpawnSupplyCostMultiplier
ResourceName m_sArsenalGameModeUIDataHolder
bool IsArsenalTypeEnabled(SCR_EArsenalTypes arsenalType)
float GetCalculatedLoadoutSpawnSupplyCostMultiplier()
ref ScriptInvokerInt m_OnArsenalGameModeTypeChanged
void SetArsenalGameModeType_S(SCR_EArsenalGameModeType arsenalGameModeType, int playerID=0)
ref SCR_PlayerLoadoutData m_LocalPlayerLoadoutData
ScriptInvokerBool GetOnMilitarySupplyAllocationToggle()
int GetItemMilitarySupplyAllocationCost(ResourceName resource, SCR_ArsenalComponent arsenalComponent, bool addAdditionalCosts=false)
SCR_PlayerLoadoutData GetLocalPlayerLoadoutData()
ref SCR_PlayerLoadoutData loadoutData
SCR_MilitarySupplyAllocationConfig GetMilitarySupplyApplicationConfigData()
ref ScriptInvokerInt m_OnArsenalTypeEnabledChanged
void OnMilitarySupplyAllocationToggle()
void SetLoadoutBlackListActiveStates(notnull array< bool > orderedActiveStates, bool clearExistingLoadouts, int editorPlayerIdClearedLoadout=-1)
ScriptInvokerFloat GetOnLoadoutSpawnSupplyCostMultiplierChanged()
ref SCR_LoadoutSaveBlackListHolder m_LoadoutSaveBlackListHolder
void OnLoadoutSpawnSupplyCostMultiplierChanged()
float GetLoadoutSpawnSupplyCostMultiplier()
SCR_EArsenalGameModeType m_eArsenalGameModeType
SCR_PlayerLoadoutData GetPlayerLoadoutData(GameEntity characterEntity)
void SetLoadoutSpawnCostMultiplier_S(float multiplier, int playerID=0)
int GetArsenalGameModeUIInfoList(inout notnull array< SCR_ArsenalGameModeUIData > arsenalGameModeTypeUIInfoList)
ScriptInvokerBase< SCR_ArsenalManagerComponent_OnPlayerLoadoutChanged > GetOnLoadoutUpdated()
void SetMilitarySupplyAllocationEnabled(bool enable)
bool AreItemsRankLocked()
If items can be ranked locked.
int GetItemMilitarySupplyAllocationRefundAmount(notnull IEntity item, SCR_ArsenalComponent arsenalComponent)
void DoSetPlayerLoadout(int playerId, string loadoutString, GameEntity characterEntity, SCR_EArsenalSupplyCostType arsenalSupplyType)
void SetEnabledArsenalTypes(SCR_EArsenalTypes newEnabledArsenalTypes, int playerID=-1)
void RpcAsk_SetMilitarySupplyAllocationEnabled(bool enable)
float suppliesCost
class SCR_ArsenalGameModeUIDataHolder BaseContainerProps()
ref SCR_ArsenalGameModeUIDataHolder m_ArsenalGameModeUIDataHolder
ref SCR_ArsenalSaveTypeInfoHolder m_ArsenalSaveTypeInfoHolder
void SyncPlayerloadout(int playerId, SCR_ArsenalPlayerLoadout playerLoadout, bool loadoutChanged=true, bool notification=false)
float m_fRefundSameFactionItemMultiplier
SCR_EArsenalGameModeType GetArsenalGameModeType()
ScriptInvokerInt GetOnArsenalGameModeTypeChanged()
void OnArsenalTypeEnabledChanged()
SCR_UIInfo GetArsenalGameModeUIInfo(SCR_EArsenalGameModeType arsenalGameModeType)
SCR_ArsenalSaveTypeInfoHolder GetArsenalSaveTypeInfoHolder()
ref map< UUID, ref SCR_ArsenalPlayerLoadout > m_aPlayerLoadouts
bool m_bLocalPlayerLoadoutAvailable
ref ScriptInvokerFloat m_OnLoadoutSpawnSupplyCostMultiplierChanged
float GetDefaultLoadoutMilitarySuppplyAllocationCost(notnull SCR_BasePlayerLoadout playerLoadout)
func SCR_ArsenalManagerComponent_OnPlayerLoadoutChanged
float m_fRefundDifferentFactionItemMultiplier
ScriptInvokerInt GetOnArsenalTypeEnabledChanged()
ref ScriptInvokerBool m_OnMilitarySupplyAllocationToggle
ResourceName m_sMilitarySupplyAllocationConfigHolder
SCR_BaseGameMode GetGameMode()
void SCR_BaseGameModeComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
SCR_CacheNoteComponentClass ScriptComponentClass RplProp()] protected ref array< string > m_aLines
override void OnPlayerAuditSuccess(int playerId)
SCR_EArsenalGameModeType
SCR_EArsenalItemMode
Get all prefabs that have the spawner data
void SCR_FactionManager(IEntitySource src, IEntity parent)
void SCR_FilteredInventoryStorageComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
EResourceGeneratorID
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
ScriptInvokerBase< ScriptInvokerFloatMethod > ScriptInvokerFloat
ScriptInvokerBase< ScriptInvokerBoolMethod > ScriptInvokerBool
ScriptInvokerBase< ScriptInvokerIntMethod > ScriptInvokerInt
SCR_SpawnerSlotManagerClass s_Instance
Class used for managing changes and removals of slots present in world.
void SCR_UniversalInventoryStorageComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
enum EVehicleType IEntity
proto external Managed FindComponent(typename typeName)
proto external EntityPrefabData GetPrefabData()
proto external IEntity GetParent()
Container context loading JSON format.
Container context saving in JSON format.
Definition Math.c:13
Main replication API.
Definition Replication.c:14
Object holding reference to resource. In destructor release the resource.
Definition Resource.c:25
SCR_ArsenalItemListConfig GetOverwriteArsenalConfig()
SCR_EArsenalSaveType GetArsenalSaveType()
SCR_EArsenalSupplyCostType GetSupplyCostType()
SCR_ArsenalInventoryStorageManagerComponent GetArsenalInventoryComponent()
SCR_UIInfo GetArsenalGameModeUIInfo(SCR_EArsenalGameModeType arsenalGameModeType)
ref array< ref SCR_ArsenalGameModeUIData > m_aArsenalGameModeTypeUIInfoList
int GetArsenalGameModeUIInfoList(inout notnull array< SCR_ArsenalGameModeUIData > arsenalGameModeTypeUIInfoList)
int GetSupplyRefundAmount(SCR_EArsenalSupplyCostType supplyCostType, bool addAdditionalCosts=true)
bool GetUseMilitarySupplyAllocation()
int GetSupplyCost(SCR_EArsenalSupplyCostType supplyCostType, bool addAdditionalCosts=true)
SCR_ECharacterRank GetRequiredRank()
int GetMilitarySupplyAllocationCost(SCR_EArsenalSupplyCostType supplyCostType, bool addAdditionalCosts=true)
SCR_EArsenalItemMode GetItemMode()
bool GetUseMilitarySupplyAllocationForPrefab(ResourceName prefab, out SCR_EArsenalItemType itemUseMilitarySupplyAllocation)
SCR_BaseArsenalRefundEffect ExecuteFirstValidRefundEffect(notnull IEntity item, notnull PlayerController playerController, SCR_ArsenalComponent arsenal)
sealed bool IsMaster()
bool GetEntityBudgetCost(out notnull array< ref SCR_EntityBudgetValue > outBudgets)
Get prefab entity Data of type Ignores disabled Data s param dataType class of Data type you with to obtain return Entity Data of given type Null if not found *SCR_BaseEntityCatalogData GetEntityDataOfType(typename dataType)
Get list of entity Data of all types Ignores Disabled Elements param[out] Array of enabled entity Data list return List size *int GetEntityDataList(notnull out array< SCR_BaseEntityCatalogData > entityDataList)
Get Catalog parent the entity entry is in return Catalog parent *SCR_EntityCatalog GetCatalogParent()
Get UI info Prefab needs to be an editable entity or have a custom UI info logic Note that if UIInfo is NULL then the autotest will fail return Ui info *SCR_UIInfo GetEntityUiInfo()
SCR_EntityCatalog GetFactionEntityCatalogOfType(EEntityCatalogType catalogType, bool printNotFound=true)
bool IsCustomLoadoutSupported()
int GetFriendlyFactions(notnull out array< Faction > friendlyFactions, bool includeSelf=true)
static bool IsEditMode()
Definition Functions.c:1566
Base Used for items and attachments which should not be shown in the arsenal but should have a cost t...
int GetSupplyCost(SCR_EArsenalSupplyCostType supplyCostType, bool addAdditionalCosts=true)
static void ComputeSuppliesCost(LoadContext context, SCR_Faction faction, SCR_ArsenalPlayerLoadout playerLoadout, SCR_EArsenalSupplyCostType arsenalSupplyType, int depth=0)
static int GetLocalPlayerId()
Returns either a valid ID of local player or 0.
void DoSetPlayerHasLoadout(bool loadoutValid, bool loadoutChanged, bool notification)
void DoSendPlayerLoadout(SCR_PlayerLoadoutData loadoutData)
override float GetAggregatedResourceValue()
override float GetAggregatedMaxResourceValue()
Definition UUID.c:28
Definition Types.c:486
override void EOnInit(IEntity owner)
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
SCR_FieldOfViewSettings Attribute
EntityEvent
Various entity events.
Definition EntityEvent.c:14
proto external PlayerController GetPlayerController()
EStoragePurpose
void RplRpc(RplChannel channel, RplRcver rcver, RplCondition condition=RplCondition.None, string customConditionName="")
Definition EnNetwork.c:95
RplRcver
Definition RplRcver.c:59
RplChannel
Communication channel. Reliable is guaranteed to be delivered. Unreliable not.
Definition RplChannel.c:14
@ MAX