Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_CatalogEntitySpawnerComponent.c
Go to the documentation of this file.
1[EntityEditorProps(category: "GameScripted/Components", description: "Allows player to spawn entities configured in EntityCatalogs, usually found on factions. Requires SCR_EntitySpawnerSlotComponent in vicinity.", color: "0 0 255 255")]
3{
4 [Attribute(defvalue: "{56EBF5038622AC95}Assets/Conflict/CanBuild.emat", params: "emat", desc: "Material used on entity previews, visible to local players only", category: "Entity Spawner")]
5 ResourceName m_sPreviewEntityMaterial;
6
7 [Attribute(defvalue: "{14A9DCEA57D1C381}Assets/Conflict/CannotBuild.emat", params: "emat", desc: "Material used on unavailable entity previews, visible to local players only", category: "Entity Spawner")]
8 ResourceName m_sPreviewEntityMaterialUnavailable;
9
10 [Attribute(defvalue :"{000CD338713F2B5A}Prefabs/AI/Groups/Group_Base.et", UIWidgets.ResourceNamePicker, "Default group to be initially assigned to created units", "et", category: "Entity Spawner")]
12
13 [Attribute(defvalue: "{FFF9518F73279473}PrefabsEditable/Auto/AI/Waypoints/E_AIWaypoint_Move.et", UIWidgets.ResourceNamePicker, "Defend waypoint prefab", "et", category: "Entity Spawner")]
15
16 [Attribute(defvalue: "150", params: "0 inf", desc: "Supply component search radius.", category: "Supplies")]
18
19 [Attribute(defvalue: "2.5", params: "0 inf", desc: "Completion radius of initial move waypoint", "et", category: "Entity Spawner")]
21
22 [Attribute(defvalue: "10", params: "0 inf", desc: "How long should be vehicle locked after spawn", category: "Vehicle lock protection")]
24
25 //------------------------------------------------------------------------------------------------
31
32 //------------------------------------------------------------------------------------------------
38
39 //------------------------------------------------------------------------------------------------
45
46 //------------------------------------------------------------------------------------------------
52
53 //------------------------------------------------------------------------------------------------
59}
60
63class SCR_CatalogEntitySpawnerComponent : SCR_SlotServiceComponent
64{
66 static const ref array<SCR_CatalogEntitySpawnerComponent> INSTANCES = {};
67
68 protected const float UPDATE_PERIOD = 10.0 / 60.0;
69
70 [Attribute(category: "Catalog Parameters", desc: "Type of entity catalogs that will be allowed on this spawner.", uiwidget: UIWidgets.SearchComboBox, enums: ParamEnumArray.FromEnum(EEntityCatalogType))]
71 protected ref array<EEntityCatalogType> m_aCatalogTypes;
72
73 [Attribute(uiwidget: UIWidgets.SearchComboBox, category: "Catalog Parameters", desc: "Allowed labels.", enums: ParamEnumArray.FromEnum(EEditableEntityLabel))]
74 protected ref array<EEditableEntityLabel> m_aAllowedLabels;
75
76 [Attribute(uiwidget: UIWidgets.SearchComboBox, category: "Catalog Parameters", desc: "Ignored labels.", enums: ParamEnumArray.FromEnum(EEditableEntityLabel))]
77 protected ref array<EEditableEntityLabel> m_aIgnoredLabels;
78
79 [RplProp()]
80 protected ref array<RplId> m_aGracePeriodEntries = {};
81
82 [RplProp()]
83 protected ref array<RplId> m_aGracePeriodRequesters = {};
84
85 protected ref array<float> m_aGracePeriodStartingTimes = {};
86 protected float m_fLastUpdateElapsedTime;
87
88 [Attribute(defvalue: "1", desc: "If true, Spawner will require from entities that they have all allowed labels.", category: "Catalog Parameters")]
89 protected bool m_bNeedAllLabels;
90
91 [Attribute(desc: "Enables supplies usage.", category: "Supplies")]
93
94 [Attribute(params: "0 inf", desc: "Custom supplies value.", category: "Supplies")]
95 protected int m_iCustomSupplies;
96
97 [Attribute(desc: "Enables the refund grace period.", category: "Supplies")]
98 protected bool m_bEnableGracePeriod;
99
100 [Attribute(params: "0 inf", desc: "Time in seconds for the duration of the grace period for refunding.", category: "Supplies")]
101 protected float m_fGracePeriodTime;
102
103 [Attribute(params: "0 inf", desc: "Range in meters for the area of the grace period for refunding.", category: "Supplies")]
104 protected float m_fGracePeriodAreaRange;
105
106 [Attribute(params: "0 inf", desc: "Multiplier used to affect the resource usage of the refund actions after the grace period has expired.", category: "Supplies")]
108
112 protected SCR_ResourceComponent m_ResourceComponent;
113 protected SCR_CampaignSuppliesComponent m_SupplyComponent
114 protected RplComponent m_RplComponent;
115
116 protected ref ScriptInvoker m_OnEntitySpawned; //~ Sends Spawned IEntity
117 protected ref ScriptInvoker m_OnSpawnerSuppliesChanged; //~ Sends Spawned prev and new spawn supplies
118
119 static const int SLOT_CHECK_INTERVAL = 60;
120
121 protected ref array<SCR_EntityCatalogEntry> m_aAssetList = {};
122 protected ref array<ref Tuple2<SCR_AIGroup, SCR_AIGroup>> m_aGroupsToAssign = {};
124
125 //arrays used for UI Slot checks
128
129 //------------------------------------------------------------------------------------------------
131 bool IsProxy()
132 {
133 return (m_RplComponent && m_RplComponent.IsProxy());
134 }
135
136 //------------------------------------------------------------------------------------------------
142
143 //------------------------------------------------------------------------------------------------
149
150 //------------------------------------------------------------------------------------------------
154 {
155 RplId entityId = Replication.FindItemId(entity);
156
157 if (entityId.IsValid())
158 return m_aGracePeriodEntries.Contains(entityId);
159
160 return false;
161 }
162
163 //------------------------------------------------------------------------------------------------
166 bool IsInGracePeriod(RplId entityId)
167 {
168 if (entityId.IsValid())
169 return m_aGracePeriodEntries.Contains(entityId);
170
171 return false;
172 }
173
174 //------------------------------------------------------------------------------------------------
178 bool CanRefund(RplId entityId, RplId userId)
179 {
180 if (!entityId.IsValid() || !userId.IsValid())
181 return false;
182
183 int idx = m_aGracePeriodEntries.Find(entityId);
184
185 return idx == -1
186 || ( m_aGracePeriodEntries[idx] == entityId
187 && m_aGracePeriodRequesters[idx] == userId);
188 }
189
190 //------------------------------------------------------------------------------------------------
194 bool CanRefund(notnull IEntity entity, notnull IEntity user)
195 {
196 RplId entityId = Replication.FindItemId(entity);
197 RplId userId = Replication.FindItemId(user);
198
199 if (!entityId.IsValid() || !userId.IsValid())
200 return false;
201
202 int idx = m_aGracePeriodEntries.Find(entityId);
203
204 return idx == -1
205 || ( m_aGracePeriodEntries[idx] == entityId
206 && m_aGracePeriodRequesters[idx] == userId);
207 }
208
209 //------------------------------------------------------------------------------------------------
212 void UnregisterGracePeriod(notnull IEntity entity)
213 {
214 RplId entityId = Replication.FindItemId(entity);
215
216 if (!entityId.IsValid())
217 return;
218
219 int idx = m_aGracePeriodEntries.Find(entityId);
220
224
225 if (m_aGracePeriodEntries.Count() == 0)
226 ClearEventMask(GetOwner(), EntityEvent.FRAME);
227
228 Replication.BumpMe();
229 }
230
231 //------------------------------------------------------------------------------------------------
235 {
236 if (!entityId.IsValid())
237 return;
238
239 int idx = m_aGracePeriodEntries.Find(entityId);
240
244
245 if (m_aGracePeriodEntries.Count() == 0)
246 ClearEventMask(GetOwner(), EntityEvent.FRAME);
247
248 Replication.BumpMe();
249 }
250
251 //------------------------------------------------------------------------------------------------
256 void RegisterGracePeriod(notnull IEntity entity, notnull IEntity user, float startingTime = FLT_INF)
257 {
258 RplId entityId = Replication.FindItemId(entity);
259 RplId userId = Replication.FindItemId(user);
260
261 if (!entityId.IsValid())
262 return;
263
264 if (!userId.IsValid())
265 return;
266
267 if (startingTime == FLT_INF)
268 startingTime = GetGame().GetWorld().GetWorldTime() / 1000.0;
269
270 if (m_aGracePeriodEntries.Count() == 0)
271 SetEventMask(GetOwner(), EntityEvent.FRAME);
272
273 m_aGracePeriodEntries.Insert(entityId);
274 m_aGracePeriodRequesters.Insert(userId);
275 m_aGracePeriodStartingTimes.Insert(startingTime + m_fGracePeriodTime);
276 Replication.BumpMe();
277 }
278
279 //------------------------------------------------------------------------------------------------
284 void RegisterGracePeriod(RplId entityId, RplId userId, float startingTime = FLT_INF)
285 {
286 if (startingTime == FLT_INF)
287 startingTime = GetGame().GetWorld().GetWorldTime() / 1000.0;
288
289 if (m_aGracePeriodEntries.Count() == 0)
290 SetEventMask(GetOwner(), EntityEvent.FRAME);
291
292 m_aGracePeriodEntries.Insert(entityId);
293 m_aGracePeriodRequesters.Insert(userId);
294 m_aGracePeriodStartingTimes.Insert(startingTime + m_fGracePeriodTime);
295 Replication.BumpMe();
296 }
297
298 //------------------------------------------------------------------------------------------------
302 bool RankCheck(notnull SCR_EntityCatalogEntry entityEntry, notnull IEntity user)
303 {
304 if (!entityEntry)
305 return false;
306
307 SCR_GameModeCampaign campaign = SCR_GameModeCampaign.GetInstance();
308 if (!campaign)
309 return false;
310
311 if (campaign.CanRequestVehicleWithoutRank())
312 return true;
313
314 int playerId = GetGame().GetPlayerManager().GetPlayerIdFromControlledEntity(user);
315 if (playerId == 0)
316 return false;
317
318 IEntity playerController = GetGame().GetPlayerManager().GetPlayerController(playerId);
319 if (!playerController)
320 return false;
321
322 SCR_ECharacterRank rank = SCR_CharacterRankComponent.GetCharacterRank(user);
323
324 //Check if the player has high enough rank
325 SCR_EntityCatalogSpawnerData spawnerData = SCR_EntityCatalogSpawnerData.Cast(entityEntry.GetEntityDataOfType(SCR_EntityCatalogSpawnerData));
326
327 return spawnerData && spawnerData.HasRequiredRank(rank);
328 }
329
330 //------------------------------------------------------------------------------------------------
333 {
334 m_aAssetList.Clear();
335
336 SCR_Faction faction = SCR_Faction.Cast(GetFaction());
337 if (!faction || m_aCatalogTypes.IsEmpty())
338 {
340 return;
341 }
342
343 SCR_EntityCatalog catalog;
344 foreach (EEntityCatalogType catalogType : m_aCatalogTypes)
345 {
346 catalog = faction.GetFactionEntityCatalogOfType(catalogType);
347 if (!catalog)
348 continue;
349
350 AddAssetsFromCatalog(catalog);
351 }
352
354 }
355
356 //------------------------------------------------------------------------------------------------
360 protected void AddAssetsFromCatalog(notnull SCR_EntityCatalog entityCatalog, bool overwriteOld = false)
361 {
362 array<SCR_EntityCatalogEntry> newAssets = {};
363 array<typename> includedDataClasses = {};
364 includedDataClasses.Insert(SCR_EntityCatalogSpawnerData); //~ The Data the entity must have
365
366 entityCatalog.GetFullFilteredEntityList(newAssets, m_aAllowedLabels, m_aIgnoredLabels, includedDataClasses, null, m_bNeedAllLabels);
367
368 if (overwriteOld)
369 m_aAssetList = newAssets;
370 else
371 m_aAssetList.InsertAll(newAssets);
372 }
373
374 //------------------------------------------------------------------------------------------------
377 {
378 if (!m_aAssetList || !m_aAssetList.IsIndexValid(index))
379 return null;
380
381 return m_aAssetList[index];
382 }
383
384 //------------------------------------------------------------------------------------------------
387 protected void AssignUserActions()
388 {
389 if (!m_ActionManager)
390 return;
391
392 if (m_aAssetList.IsEmpty())
393 return;
394
395 array<BaseUserAction> userActions = {};
396 m_ActionManager.GetActionsList(userActions);
397
398 if (userActions.Count() < m_aAssetList.Count())
399 Print("There is not enough of SCR_CatalogSpawnerUserAction attached to actionManager. Some assets won't appear.", LogLevel.WARNING);
400
401 SCR_CatalogSpawnerUserAction spawnerUserAction;
402
403 foreach (int i, BaseUserAction userAction : userActions)
404 {
405 spawnerUserAction = SCR_CatalogSpawnerUserAction.Cast(userAction);
406 if (!spawnerUserAction)
407 continue;
408
409 if (m_aAssetList.IsIndexValid(i))
410 spawnerUserAction.SetSpawnerData(m_aAssetList[i]);
411 else
412 spawnerUserAction.SetSpawnerData(null);
413 }
414 }
415
416 //------------------------------------------------------------------------------------------------
418 void AssignResourceComponent(notnull SCR_ResourceComponent component)
419 {
420 m_ResourceComponent = component;
421 }
422
423 //------------------------------------------------------------------------------------------------
426 [Obsolete("SCR_CatalogEntitySpawnerComponent.AssignSupplyComponent() should be used instead.")]
428 {
429 m_SupplyComponent = supplyComp;
430 }
431
432 //------------------------------------------------------------------------------------------------
435 {
437 m_mKnownFreeSlots.Clear();
438
440 m_mKnownOccupiedSlots.Clear();
441 }
442 //------------------------------------------------------------------------------------------------
445 void AddKnownOccupiedSlot(notnull SCR_EntitySpawnerSlotComponent slot)
446 {
449
450 ChimeraWorld world = GetOwner().GetWorld();
451 m_mKnownOccupiedSlots.Set(slot, world.GetServerTimestamp());
452 }
453
454 //------------------------------------------------------------------------------------------------
457 protected void UpdateOccupiedSlots(out array<SCR_EntitySpawnerSlotComponent> occupiedSlots)
458 {
460 return;
461
462 occupiedSlots = {};
463
464 ChimeraWorld world = GetOwner().GetWorld();
465 WorldTimestamp currentTime = world.GetServerTimestamp();
466 foreach (SCR_EntitySpawnerSlotComponent slot, WorldTimestamp timestamp : m_mKnownOccupiedSlots)
467 {
468 if (currentTime.DiffMilliseconds(timestamp) > (SLOT_CHECK_INTERVAL * 100))
469 m_mKnownOccupiedSlots.Remove(slot);
470 else
471 occupiedSlots.Insert(slot);
472 }
473 }
474
475 //------------------------------------------------------------------------------------------------
477 protected SCR_EntitySpawnerSlotComponent GetLastKnownSuitableSlot(notnull SCR_EntityCatalogSpawnerData spawnerData)
478 {
480 return null;
481
482 ChimeraWorld world = GetOwner().GetWorld();
483 WorldTimestamp currentTime = world.GetServerTimestamp();
484 foreach (SCR_EntitySpawnerSlotComponent slot, WorldTimestamp timestamp : m_mKnownFreeSlots)
485 {
486 if (currentTime.DiffMilliseconds(timestamp) > (SLOT_CHECK_INTERVAL * 100))
487 m_mKnownFreeSlots.Remove(slot);
488 else if (spawnerData.CanSpawnInSlot(slot.GetSlotType()))
489 return slot;
490 }
491
492 return null;
493 }
494
495 //------------------------------------------------------------------------------------------------
500 protected SCR_EntitySpawnerSlotComponent GetFreeSlotFromArray(notnull array<SCR_EntitySpawnerSlotComponent> slots, notnull SCR_EntityCatalogSpawnerData spawnerData, notnull array<SCR_EntitySpawnerSlotComponent> occupiedSlots)
501 {
502 foreach (SCR_EntitySpawnerSlotComponent slot : slots)
503 {
504 if (!spawnerData.CanSpawnInSlot(slot.GetSlotType()) || occupiedSlots.Contains(slot))
505 continue;
506
507 if (!slot.IsOccupied())
508 {
511
512 ChimeraWorld world = GetOwner().GetWorld();
513 m_mKnownFreeSlots.Insert(slot, world.GetServerTimestamp());
514
515 return slot;
516 }
517
518 //Add to array of recenly found occupied slots
520 }
521
522 return null;
523 }
524
525 //------------------------------------------------------------------------------------------------
528 SCR_EntitySpawnerSlotComponent GetFreeSlot(notnull SCR_EntityCatalogSpawnerData spawnerData)
529 {
530 // First go through recently checked slots to prevent redundant checks. Should be used only for Interaction visualisation.
531 SCR_EntitySpawnerSlotComponent freeSlot = GetLastKnownSuitableSlot(spawnerData);
532 if (freeSlot)
533 return freeSlot;
534
535 array<SCR_EntitySpawnerSlotComponent> occupiedSlots = {};
536 UpdateOccupiedSlots(occupiedSlots);
537
538 // Second check for slots in hiearchy, If no child slot available, look for nearby slots
539 freeSlot = GetFreeSlotFromArray(m_aChildSlots, spawnerData, occupiedSlots);
540 if (!freeSlot)
541 freeSlot = GetFreeSlotFromArray(m_aNearSlots, spawnerData, occupiedSlots);
542
543 return freeSlot;
544 }
545
546 //------------------------------------------------------------------------------------------------
551 void InitiateSpawn(notnull SCR_EntityCatalogEntry entityEntry, int userId, SCR_EntitySpawnerSlotComponent slot)
552 {
553 IEntity user = GetGame().GetPlayerManager().GetPlayerControlledEntity(userId);
554 if (!user)
555 return;
556
557 int supplies = GetSpawnerResourceValue();
558 SCR_EntityCatalogSpawnerData spawnerData = SCR_EntityCatalogSpawnerData.Cast(entityEntry.GetEntityDataOfType(SCR_EntityCatalogSpawnerData));
559 if (!spawnerData)
560 return;
561
562 if (m_bSuppliesConsumptionEnabled && supplies < spawnerData.GetSupplyCost())
563 return;
564
565 if (GetRequestState(entityEntry, user) == SCR_EEntityRequestStatus.CAN_SPAWN)
566 PerformSpawn(entityEntry, user, slot);
567 }
568
569 //------------------------------------------------------------------------------------------------
574 {
575 if (!m_aAssetList || !m_aAssetList.Contains(entityEntry))
576 return SCR_EEntityRequestStatus.NOT_AVAILABLE;
577
578 SCR_EntityCatalogSpawnerData entitySpawnerData = SCR_EntityCatalogSpawnerData.Cast(entityEntry.GetEntityDataOfType(SCR_EntityCatalogSpawnerData));
579
580 //Supply consumption specific states
582 {
584 return SCR_EEntityRequestStatus.NOT_AVAILABLE;
585
586 SCR_ResourceConsumer consumer = m_ResourceComponent.GetConsumer(EResourceGeneratorID.DEFAULT, EResourceType.SUPPLIES);
587
588 if (consumer && entitySpawnerData && (entitySpawnerData.GetSupplyCost() > consumer.GetAggregatedResourceValue()))
589 return SCR_EEntityRequestStatus.NOT_ENOUGH_SUPPLIES;
590 else if (!consumer && entitySpawnerData && (entitySpawnerData.GetSupplyCost() > m_iCustomSupplies))
591 return SCR_EEntityRequestStatus.NOT_ENOUGH_SUPPLIES;
592 }
593
594
595 //Do not show anything, if user is of another faction than spawner
596 if (GetRequesterFaction(user) != GetFaction())
597 return SCR_EEntityRequestStatus.NOT_AVAILABLE;
598
599 // Campaign dependent ranking and cooldowns. To be replaced once stand-alone rank system is present
600 if (SCR_GameModeCampaign.GetInstance())
601 {
602 if (!RankCheck(entityEntry, user))
603 return SCR_EEntityRequestStatus.RANK_LOW;
604
605 if (!CooldownCheck(user))
606 return SCR_EEntityRequestStatus.COOLDOWN;
607 }
608
609 EEntityCatalogType catalogType = entityEntry.GetCatalogParent().GetCatalogType();
610 // Additional states to be returned if entity Entry is of Character or Group type
611 if (catalogType == EEntityCatalogType.CHARACTER || catalogType == EEntityCatalogType.GROUP)
612 {
613 BaseGameMode gameMode = GetGame().GetGameMode();
614 if (!gameMode)
615 return SCR_EEntityRequestStatus.NOT_AVAILABLE;
616
617 SCR_SpawnerAIGroupManagerComponent groupSpawningManager = SCR_SpawnerAIGroupManagerComponent.Cast(gameMode.FindComponent(SCR_SpawnerAIGroupManagerComponent));
618 if (!groupSpawningManager || groupSpawningManager.IsAtAILimit())
619 return SCR_EEntityRequestStatus.AI_LIMIT_REACHED;
620
622 if (!controller)
623 return SCR_EEntityRequestStatus.NOT_AVAILABLE;
624
625 //Do not allow requesting, if player is not in group or is not its leader
626 SCR_PlayerControllerGroupComponent groupController = SCR_PlayerControllerGroupComponent.Cast(controller.FindComponent(SCR_PlayerControllerGroupComponent));
627 if (!groupController || !groupController.IsPlayerLeaderOwnGroup())
628 return SCR_EEntityRequestStatus.REQUESTER_NOT_GROUPLEADER;
629
630 if (!CanRequestAI(user, entitySpawnerData.GetEntityCount()))
631 return SCR_EEntityRequestStatus.GROUP_FULL;
632 }
633
634 // Campaign dependent ranking and cooldowns. To be replaced once stand-alone rank system is present
635 if (SCR_GameModeCampaign.GetInstance())
636 {
637 if (!RankCheck(entityEntry, user))
638 return SCR_EEntityRequestStatus.RANK_LOW;
639
640 if (!CooldownCheck(user))
641 return SCR_EEntityRequestStatus.COOLDOWN;
642 }
643
644 return SCR_EEntityRequestStatus.CAN_SPAWN;
645 }
646
647 //------------------------------------------------------------------------------------------------
651 bool CanRequestAI(notnull IEntity user, int aiCount = 1)
652 {
653 SCR_CommandingManagerComponent commandingManager = SCR_CommandingManagerComponent.GetInstance();
654 if (!commandingManager)
655 return false;
656
658 if (!playerController)
659 return false;
660
661 SCR_PlayerControllerGroupComponent groupController = SCR_PlayerControllerGroupComponent.Cast(playerController.FindComponent(SCR_PlayerControllerGroupComponent));
662 if (!groupController)
663 return false;
664
665 SCR_AIGroup group = groupController.GetPlayersGroup();
666 if (!group)
667 return false;
668
669 SCR_AIGroup slaveGroup = group.GetSlave();
670 if (!slaveGroup)
671 return false;
672
673 SCR_SpawnerRequestComponent reqComponent = SCR_SpawnerRequestComponent.Cast(playerController.FindComponent(SCR_SpawnerRequestComponent));
674 if (!reqComponent)
675 return false;
676
677 int queuedAICount = reqComponent.GetQueuedAIs();
678
679 return commandingManager.GetMaxAIPerGroup() >= (slaveGroup.GetAIMembers().Count() + queuedAICount + aiCount);
680 }
681
682 //------------------------------------------------------------------------------------------------
685 protected void OnGroupWaypointFinished(notnull AIWaypoint wp)
686 {
688 return;
689
690 SCR_AIGroup group = m_mGroupWaypoints.Get(wp);
691 if (!group)
692 return;
693
694 SCR_AIGroup playerGroup;
695 foreach (int index, Tuple2<SCR_AIGroup, SCR_AIGroup> groups : m_aGroupsToAssign)
696 {
697 if (groups.param1 == group)
698 {
699 playerGroup = groups.param2;
700 m_aGroupsToAssign.Remove(index);
701 break;
702 }
703 }
704
705 if (!playerGroup)
706 return;
707
708 SCR_PlayerController playerController = SCR_PlayerController.Cast(GetGame().GetPlayerManager().GetPlayerController(playerGroup.GetLeaderID()));
709 if (!playerController)
710 return;
711
712 SCR_PlayerControllerGroupComponent groupController = SCR_PlayerControllerGroupComponent.Cast(playerController.FindComponent(SCR_PlayerControllerGroupComponent));
713 if (!groupController)
714 return;
715
716 array<AIAgent> agents = {};
717 group.GetAgents(agents);
718 group.GetOnAgentRemoved().Remove(OnAIAgentRemoved);
719
720 SCR_ChimeraCharacter aiCharacter;
721 foreach (AIAgent agent : agents)
722 {
723 aiCharacter = SCR_ChimeraCharacter.Cast(agent.GetControlledEntity());
724 if (!aiCharacter)
725 continue;
726
727 groupController.AddAIToSlaveGroup(agent.GetControlledEntity(), playerGroup); //AddAISoldierToPlayerGroup(aiCharacter, groupLeaderEntity);
728 }
729
730 SCR_SpawnerRequestComponent spawnerReqComponent = SCR_SpawnerRequestComponent.Cast(playerController.FindComponent(SCR_SpawnerRequestComponent));
731 if (spawnerReqComponent)
732 spawnerReqComponent.AddQueuedAI(-1);
733
734 //Delete old entries or empty maps
735 m_mGroupWaypoints.Remove(wp);
736 if (m_mGroupWaypoints.IsEmpty())
737 m_mGroupWaypoints = null;
738
739 if (m_aGroupsToAssign.IsEmpty())
740 m_aGroupsToAssign = null;
741 }
742
743 //------------------------------------------------------------------------------------------------
744 protected void AddAISoldierToPlayerGroup(notnull SCR_ChimeraCharacter ai, notnull IEntity user)
745 {
747 if (!controller)
748 return;
749
750 SCR_PlayerControllerGroupComponent groupController = SCR_PlayerControllerGroupComponent.Cast(controller.FindComponent(SCR_PlayerControllerGroupComponent));
751 if (!groupController)
752 return;
753
754 groupController.RequestAddAIAgent(ai, controller.GetPlayerId());
755 }
756
757 //------------------------------------------------------------------------------------------------
761 {
762 SCR_ChimeraCharacter player = SCR_ChimeraCharacter.Cast(user);
763 if (!player)
764 return null;
765
766 return player.GetFaction();
767 }
768
769 //------------------------------------------------------------------------------------------------
780
781 //------------------------------------------------------------------------------------------------
792
793 //------------------------------------------------------------------------------------------------
797 {
798 PlayerManager playerManager = GetGame().GetPlayerManager();
799 int playerId = playerManager.GetPlayerIdFromControlledEntity(userEntity);
800
801 return SCR_PlayerController.Cast(playerManager.GetPlayerController(playerId));
802
803 }
804
805 //------------------------------------------------------------------------------------------------
808 SCR_SpawnerRequestComponent GetRequestComponentFromPlayerEntity(notnull IEntity playerEntity)
809 {
810 SCR_PlayerController playerController = GetPlayerControllerFromEntity(playerEntity);
811 if (!playerController)
812 return null;
813
814 return SCR_SpawnerRequestComponent.Cast(playerController.FindComponent(SCR_SpawnerRequestComponent));
815 }
816
817 //------------------------------------------------------------------------------------------------
818 // Send notification to player requesting spawn
819 protected void SendNotification(int msgId, notnull IEntity user, int assetId = -1, int catalogType = -1)
820 {
821 SCR_SpawnerRequestComponent reqComponent = GetRequestComponentFromPlayerEntity(user);
822 if (!reqComponent)
823 return;
824
825 reqComponent.SendPlayerFeedback(msgId, assetId, catalogType);
826 }
827
828 //------------------------------------------------------------------------------------------------
833 void CreatePreviewEntity(notnull SCR_EntityCatalogEntry spawnData, notnull SCR_EntitySpawnerSlotComponent slot, SCR_EEntityRequestStatus reqStatus = SCR_EEntityRequestStatus.CAN_SPAWN)
834 {
836 if (!prefabData)
837 return;
838
839 //This will delete any existing preview entity
841
842 // Don't show preview for Groups.
843 if (spawnData.GetCatalogParent().GetCatalogType() == EEntityCatalogType.GROUP)
844 return;
845
846 if (!m_aAssetList || m_aAssetList.IsEmpty() || !m_aAssetList.Contains(spawnData))
847 return;
848
849 Resource resource = Resource.Load(spawnData.GetPrefab());
850
851 if (!resource || !resource.IsValid())
852 return;
853
855 params.TransformMode = ETransformMode.WORLD;
856
857 slot.GetOwner().GetTransform(params.Transform);
858
859 ResourceName material;
860 if (reqStatus == SCR_EEntityRequestStatus.CAN_SPAWN)
861 material = prefabData.m_sPreviewEntityMaterial;
862 else
863 material = prefabData.m_sPreviewEntityMaterialUnavailable;
864
865 m_PreviewEntity = SCR_PrefabPreviewEntity.Cast(SCR_PrefabPreviewEntity.SpawnPreviewFromPrefab(resource, "SCR_PrefabPreviewEntity", GetOwner().GetWorld(), params, material));
866
867 if (m_PreviewEntity)
868 {
869 // Align preview with terrain and update it to make it appear correctly
870 m_PreviewEntity.SetPreviewTransform(params.Transform, EEditorTransformVertical.TERRAIN);
871 m_PreviewEntity.Update();
872 }
873 }
874
875 //------------------------------------------------------------------------------------------------
878 {
879 if (m_PreviewEntity)
880 SCR_EntityHelper.DeleteEntityAndChildren(m_PreviewEntity);
881 }
882
883 //------------------------------------------------------------------------------------------------
889
890 //------------------------------------------------------------------------------------------------
895 protected void PerformSpawn(notnull SCR_EntityCatalogEntry entityEntry, IEntity user = null, SCR_EntitySpawnerSlotComponent preferredSlot = null)
896 {
897 if (IsProxy())
898 return;
899
900 m_SpawnedEntity = null;
901
902 SCR_EntityCatalogSpawnerData spawnerData = SCR_EntityCatalogSpawnerData.Cast(entityEntry.GetEntityDataOfType(SCR_EntityCatalogSpawnerData));
903
904 //Slot from preferredSlot parameter is checked first, should it be occupied, new slot will be looked for (if there is any)
905 SCR_EntitySpawnerSlotComponent slot;
906 if (preferredSlot && spawnerData.CanSpawnInSlot(preferredSlot.GetSlotType()) && !preferredSlot.IsOccupied())
907 {
908 slot = preferredSlot;
909 }
910 else
911 {
913 slot = GetFreeSlot(spawnerData)
914 }
915
916 if (!slot)
917 {
918 SendNotification(SCR_EEntityRequestStatus.NOT_ENOUGH_SPACE, user);
919 return;
920 }
921
922 //Prevents next spawned SCR_AIGroup from being fully spawned
923 if (entityEntry.GetCatalogParent().GetCatalogType() == EEntityCatalogType.GROUP)
925
926 //Spawns entity using Resource Name from prefab data and slot owning entity
927 m_SpawnedEntity = SpawnEntity(spawnerData.GetRandomDefaultOrVariantPrefab(), slot.GetOwner());
928
929 if (!m_SpawnedEntity)
930 {
931 if (entityEntry.GetCatalogParent().GetCatalogType() == EEntityCatalogType.GROUP)
933
934 return;
935 }
936
938 AddSpawnerSupplies(-spawnerData.GetSupplyCost());
939
941 m_OnEntitySpawned.Invoke(m_SpawnedEntity, user, SCR_Faction.Cast(GetFaction()), this);
942
943 //Send notification to player, whom requested entity
944 SCR_EntityCatalog parentCatalog = entityEntry.GetCatalogParent();
945 if (parentCatalog)
946 {
947 array<SCR_EntityCatalogEntry> entityList = {};
948 parentCatalog.GetEntityList(entityList);
949 int assetIndex = entityList.Find(entityEntry);
950
951 if (assetIndex > -1)
952 SendNotification(0, user, entityList.Find(entityEntry), parentCatalog.GetCatalogType());
953 }
954
955 //Called, if spawned entity is vehicle
956 if (m_SpawnedEntity.IsInherited(Vehicle))
957 {
959 if (carController)
960 carController.SetPersistentHandBrake(true);
961
962 Physics physicsComponent = m_SpawnedEntity.GetPhysics();
963 if (physicsComponent)
964 physicsComponent.SetVelocity("0 -0.1 0"); // Make the entity copy the terrain properly
965
966 LockSpawnedVehicle(user);
967
968 ActionsManagerComponent actionsManagerComponent = ActionsManagerComponent.Cast(m_SpawnedEntity.FindComponent(ActionsManagerComponent));
969
970 if (!actionsManagerComponent)
971 return;
972
974 array<BaseUserAction> outActions = {};
975
976 actionsManagerComponent.GetActionsList(outActions);
977
978 foreach (BaseUserAction action : outActions)
979 {
980 refundAction = SCR_ResourceEntityRefundAction.Cast(action);
981
982 if (!refundAction)
983 continue;
984 }
985 }
986
987 //Called, if spawned entity is SCR_ChimeraCharacter or inherits from it.
988 if (m_SpawnedEntity.IsInherited(SCR_ChimeraCharacter))
989 {
990 SCR_SpawnerRequestComponent requestComponent = GetRequestComponentFromPlayerEntity(user);
991 if (!requestComponent)
992 return;
993
994 OnChimeraCharacterSpawned(SCR_ChimeraCharacter.Cast(m_SpawnedEntity), user, slot.GetRallyPoint());
995 requestComponent.AddQueuedAI(spawnerData.GetEntityCount());
996 }
997 else
998 {
999 slot.MoveCharactersFromSlot();
1000 }
1001
1002 //Called, if spawned entity is SCR_AIGroup or inherits from it.
1003 if (m_SpawnedEntity.IsInherited(SCR_AIGroup))
1004 OnAIGroupSpawned(SCR_AIGroup.Cast(m_SpawnedEntity), user, slot.GetOwner(), slot.GetRallyPoint());
1005 }
1006
1007 //------------------------------------------------------------------------------------------------
1008 protected IEntity SpawnEntity(ResourceName entityResourceName, notnull IEntity slotOwner)
1009 {
1010 Resource entityResource = Resource.Load(entityResourceName);
1011 if (!entityResource || !entityResource.IsValid())
1012 {
1013 Print("CatalogEntitySpawnerComponent - SpawnEntity cannot spawn new entity without valid resource. Used SCR_EntityCatalogEntry is probably set incorrectly", LogLevel.ERROR);
1014 return null;
1015 }
1016
1018 params.TransformMode = ETransformMode.WORLD;
1019 slotOwner.GetTransform(params.Transform);
1020
1021 return GetGame().SpawnEntityPrefab(entityResource, GetOwner().GetWorld(), params);
1022 }
1023
1024 //------------------------------------------------------------------------------------------------
1025 protected void LockSpawnedVehicle(notnull IEntity owningUser)
1026 {
1027 if (!m_SpawnedEntity)
1028 return;
1029
1030 SCR_VehicleSpawnProtectionComponent protectionComp = SCR_VehicleSpawnProtectionComponent.Cast(m_SpawnedEntity.FindComponent(SCR_VehicleSpawnProtectionComponent));
1031 if (!protectionComp)
1032 return;
1033
1035 if (!prefabData)
1036 return;
1037
1038 protectionComp.SetVehicleOwner(GetGame().GetPlayerManager().GetPlayerIdFromControlledEntity(owningUser));
1039 protectionComp.SetProtectionTime(prefabData.GetVehicleLockedDuration());
1040 }
1041
1042 //------------------------------------------------------------------------------------------------
1045 SCR_ResourceComponent GetSpawnerResourceComponent()
1046 {
1047 return m_ResourceComponent;
1048 }
1049
1050 //------------------------------------------------------------------------------------------------
1053 [Obsolete("SCR_CatalogEntitySpawnerComponent.GetSpawnerResourceComponent() should be used instead.")]
1055 {
1056 return m_SupplyComponent;
1057 }
1058
1059 //------------------------------------------------------------------------------------------------
1063 {
1065 return 0.0;
1066
1067 SCR_ResourceConsumer consumer = m_ResourceComponent.GetConsumer(EResourceGeneratorID.DEFAULT, EResourceType.SUPPLIES);
1068
1069 if (!consumer)
1070 return 0.0;
1071
1072 return consumer.GetAggregatedResourceValue();
1073 }
1074
1075 //------------------------------------------------------------------------------------------------
1078 [Obsolete("SCR_CatalogEntitySpawnerComponent.GetSpawnerResourceValue() should be used instead.")]
1080 {
1081 if (!m_SupplyComponent)
1082 return m_iCustomSupplies;
1083
1084 return m_SupplyComponent.GetSupplies();
1085 }
1086
1087 //------------------------------------------------------------------------------------------------
1090 void AddSpawnerSupplies(float supplies)
1091 {
1093 {
1094 SCR_ResourceInteractor interactor;
1095
1096 if (supplies >= 0)
1097 {
1098 SCR_ResourceGenerator generator = m_ResourceComponent.GetGenerator(EResourceGeneratorID.DEFAULT, EResourceType.SUPPLIES);
1099
1100 if (!generator)
1101 return;
1102
1103 interactor = generator;
1104
1105 generator.RequestGeneration(supplies);
1106 }
1107 else
1108 {
1109 SCR_ResourceConsumer consumer = m_ResourceComponent.GetConsumer(EResourceGeneratorID.DEFAULT, EResourceType.SUPPLIES);
1110
1111 if (!consumer)
1112 return;
1113
1114 interactor = consumer;
1115
1116 consumer.RequestConsumtion(-supplies);
1117 }
1118
1120 m_OnSpawnerSuppliesChanged.Invoke(interactor.GetAggregatedResourceValue());
1121 }
1122
1123 m_iCustomSupplies += supplies;
1124 Replication.BumpMe();
1125
1128 }
1129
1130 //------------------------------------------------------------------------------------------------
1133 protected bool CooldownCheck(notnull IEntity user)
1134 {
1135 int userId = GetGame().GetPlayerManager().GetPlayerIdFromControlledEntity(user);
1136 if (userId == 0)
1137 return false;
1138
1139 SCR_PlayerController playerController = SCR_PlayerController.Cast(GetGame().GetPlayerManager().GetPlayerController(userId));
1140 if (!playerController)
1141 return false;
1142
1143 SCR_CampaignNetworkComponent networkComponent = SCR_CampaignNetworkComponent.Cast(playerController.FindComponent(SCR_CampaignNetworkComponent));
1144 if (!networkComponent)
1145 return false;
1146
1147 SCR_CampaignFactionManager factionManager = SCR_CampaignFactionManager.Cast(GetGame().GetFactionManager());
1148 if (!factionManager)
1149 return false;
1150
1151 SCR_ECharacterRank rank = SCR_CharacterRankComponent.GetCharacterRank(user);
1152 WorldTimestamp lastTimestamp = networkComponent.GetLastRequestTimestamp();
1153 WorldTimestamp timeout = lastTimestamp.PlusMilliseconds(factionManager.GetRankRequestCooldown(rank, playerController.GetPlayerId()));
1154 ChimeraWorld world = GetOwner().GetWorld();
1155 return (lastTimestamp == 0 || timeout.Less(world.GetServerTimestamp()));
1156 }
1157
1158 //------------------------------------------------------------------------------------------------
1159 protected override void OnFactionChanged(FactionAffiliationComponent owner, Faction previousFaction, Faction faction)
1160 {
1162 }
1163
1164 //------------------------------------------------------------------------------------------------
1166 protected void OnAIGroupSpawned(notnull SCR_AIGroup group, notnull IEntity user, notnull IEntity slotEntity, SCR_EntityLabelPointComponent rallyPoint = null)
1167 {
1168 SCR_SpawnerRequestComponent requestComponent = GetRequestComponentFromPlayerEntity(user);
1169 if (!requestComponent)
1170 return;
1171
1172 BaseGameMode gameMode = GetGame().GetGameMode();
1173 if (!gameMode)
1174 return;
1175
1176 SCR_SpawnerAIGroupManagerComponent groupSpawningManager = SCR_SpawnerAIGroupManagerComponent.Cast(gameMode.FindComponent(SCR_SpawnerAIGroupManagerComponent));
1177 if (!groupSpawningManager)
1178 return;
1179
1180 foreach (int i, ResourceName resName : group.m_aUnitPrefabSlots)
1181 {
1182 groupSpawningManager.QueueSpawn(this, resName, user, slotEntity, rallyPoint);
1183 }
1184
1185 requestComponent.AddQueuedAI(group.m_aUnitPrefabSlots.Count());
1186 }
1187
1188 //------------------------------------------------------------------------------------------------
1194 //protected void SpawnAIGroupMember(ResourceName resName, notnull IEntity user, IEntity slotEntity, SCR_EntityLabelPointComponent rallyPoint = null)
1195 void SpawnAIGroupMember(ResourceName resName, notnull IEntity user, IEntity slotEntity, SCR_EntityLabelPointComponent rallyPoint = null)
1196 {
1197 SCR_ChimeraCharacter ai = SCR_ChimeraCharacter.Cast(SpawnEntity(resName, slotEntity));
1198 if (!ai)
1199 return;
1200
1201 OnChimeraCharacterSpawned(ai, user, rallyPoint);
1202 }
1203
1204 //------------------------------------------------------------------------------------------------
1205 protected void OnAIAgentRemoved(SCR_AIGroup group, AIAgent ai)
1206 {
1207 SCR_AIGroup playerGroup;
1208
1209 foreach (Tuple2<SCR_AIGroup, SCR_AIGroup> groups : m_aGroupsToAssign)
1210 {
1211 if (groups.param1 != group)
1212 continue;
1213
1214 playerGroup = groups.param2;
1215 }
1216
1217 SCR_PlayerController playerController = SCR_PlayerController.Cast(GetGame().GetPlayerManager().GetPlayerController(playerGroup.GetLeaderID()));
1218 if (!playerController)
1219 return;
1220
1221 SCR_SpawnerRequestComponent spawnerReqComponent = SCR_SpawnerRequestComponent.Cast(playerController.FindComponent(SCR_SpawnerRequestComponent));
1222 if (spawnerReqComponent)
1223 spawnerReqComponent.AddQueuedAI(-1);
1224 }
1225
1226 //------------------------------------------------------------------------------------------------
1228 protected void OnChimeraCharacterSpawned(notnull SCR_ChimeraCharacter ai, notnull IEntity user, SCR_EntityLabelPointComponent rallyPoint = null)
1229 {
1230 AIControlComponent control = AIControlComponent.Cast(ai.FindComponent(AIControlComponent));
1231 if (!control)
1232 return;
1233
1234 control.ActivateAI();
1235
1236 // If other type of slot is used, thus without default waypoint, AI unit will be added directly into player group, not going anywhere before that.
1237 if (!rallyPoint)
1238 {
1239 AddAISoldierToPlayerGroup(ai, user);
1240 return;
1241 }
1242
1244 if (!prefabData)
1245 return;
1246
1248 wp.SetCompletionRadius(prefabData.GetMoveWaypointCompletionRadius());
1249
1250 AIAgent agent = control.GetAIAgent();
1251 if (!agent)
1252 return;
1253
1254 SCR_AIGroup group = SCR_AIGroup.Cast(agent.GetParentGroup());
1255 if (!group)
1256 {
1257 Resource res = Resource.Load(prefabData.GetDefaultGroupPrefab());
1258 group = SCR_AIGroup.Cast(GetGame().SpawnEntityPrefab(res, GetGame().GetWorld()));
1259 if (!group)
1260 return;
1261 }
1262
1263 group.AddAgent(agent);
1264 group.AddWaypoint(wp);
1265
1266 if (!m_mGroupWaypoints)
1268
1269 m_mGroupWaypoints.Insert(wp, group);
1270
1272 group.GetOnAgentRemoved().Insert(OnAIAgentRemoved);
1273
1274 if (!m_aGroupsToAssign)
1275 m_aGroupsToAssign = {};
1276
1277 SCR_PlayerController playerController = GetPlayerControllerFromEntity(user);
1278 if (!playerController)
1279 return;
1280
1281 SCR_GroupsManagerComponent groupManager = SCR_GroupsManagerComponent.GetInstance();
1282 if (!groupManager)
1283 return;
1284
1285 m_aGroupsToAssign.Insert(new Tuple2<SCR_AIGroup, SCR_AIGroup>(group, groupManager.GetPlayerGroup(playerController.GetPlayerId())));
1286 }
1287
1288 //------------------------------------------------------------------------------------------------
1290 protected SCR_AIWaypoint CreateRallyPointWaypoint(notnull SCR_EntityLabelPointComponent rallyPoint)
1291 {
1293 if (!prefabData)
1294 return null;
1295
1296 EntitySpawnParams wpParams = new EntitySpawnParams();
1297 wpParams.TransformMode = ETransformMode.WORLD;
1298 rallyPoint.GetOwner().GetTransform(wpParams.Transform);
1299
1300 Resource wpRes = Resource.Load(prefabData.GetDefaultWaypointPrefab());
1301 if (!wpRes.IsValid())
1302 return null;
1303
1304 return SCR_AIWaypoint.Cast(GetGame().SpawnEntityPrefabLocal(wpRes, null, wpParams));
1305 }
1306
1307 //------------------------------------------------------------------------------------------------
1310 {
1312 {
1313 SCR_ResourceComponent resourceComponent = SCR_ResourceComponent.FindResourceComponent(ent);
1314
1315 if (resourceComponent)
1316 {
1317 AssignResourceComponent(resourceComponent);
1318
1319 return false;
1320 }
1321 }
1322
1323 return true;
1324 }
1325
1326 //------------------------------------------------------------------------------------------------
1327 override void EOnFrame(IEntity owner, float timeSlice)
1328 {
1330 return;
1331
1332 m_fLastUpdateElapsedTime += timeSlice;
1333
1335 {
1336 float worldTime = GetGame().GetWorld().GetWorldTime() / 1000.0;
1337 IEntity entity;
1338 vector entityMins;
1339 vector entityMaxs;
1340 vector entityMat[4];
1341
1342 for (int idx, count = m_aGracePeriodEntries.Count(); idx < count; idx++)
1343 {
1345
1346 entity = IEntity.Cast(Replication.FindItem(id));
1347
1348 if (!entity)
1349 {
1350 m_aGracePeriodEntries.Remove(idx);
1352 idx = Math.Max(0, idx - 1);
1353 count = Math.Max(0, count - 1);
1354
1355 continue;
1356 }
1357
1358 entity.GetBounds(entityMins, entityMaxs);
1359 entity.GetWorldTransform(entityMat);
1360
1361 if (worldTime < m_aGracePeriodStartingTimes[idx] && Math3D.IntersectionSphereAABB(GetOwner().GetOrigin().InvMultiply4(entityMat), m_fGracePeriodAreaRange, entityMins, entityMaxs))
1362 continue;
1363
1365 idx = Math.Max(0, idx - 1);
1366 count = Math.Max(0, count - 1);
1367 }
1368
1370 }
1371 }
1372
1373 //------------------------------------------------------------------------------------------------
1374 protected override void EOnInit(IEntity owner)
1375 {
1376 super.EOnInit(owner);
1377
1378 m_RplComponent = RplComponent.Cast(GetOwner().FindComponent(RplComponent));
1379 if (!m_RplComponent)
1380 {
1381 Print("SCR_CatalogEntitySpawnerComponent requires RplComponent for its functionality!", LogLevel.WARNING);
1382 return;
1383 }
1384
1386 if (!m_ActionManager)
1387 Print("No Action Manager detected on owner of Spawner Component!", LogLevel.WARNING);
1388
1389 if (SCR_GameModeCampaign.GetInstance())
1390 {
1392 if (prefabData)
1393 GetGame().GetWorld().QueryEntitiesBySphere(GetOwner().GetOrigin(), prefabData.GetSupplySearchRadius(), SupplyComponentSearchCallback);
1394 }
1395
1396 m_ResourceComponent = SCR_ResourceComponent.FindResourceComponent(owner);
1397
1398 SCR_CatalogEntitySpawnerComponent.INSTANCES.Insert(this);
1399 }
1400
1401 //------------------------------------------------------------------------------------------------
1402 override protected void OnDelete(IEntity owner)
1403 {
1404 super.OnDelete(owner);
1405
1406 SCR_CatalogEntitySpawnerComponent.INSTANCES.RemoveItem(this);
1407 }
1408
1409 //------------------------------------------------------------------------------------------------
1410 protected override void OnPostInit(IEntity owner)
1411 {
1412 if (SCR_Global.IsEditMode())
1413 return;
1414
1415 super.OnPostInit(owner);
1416
1417 SetEventMask(owner, EntityEvent.INIT);
1418 }
1419
1420 //------------------------------------------------------------------------------------------------
1421 // destructor
1423 {
1424 SCR_EntityHelper.DeleteEntityAndChildren(m_PreviewEntity);
1425 }
1426}
1427
EEditableEntityLabel
EEntityCatalogType
ArmaReforgerScripted GetGame()
Definition game.c:1398
vector GetOrigin()
SCR_CacheNoteComponentClass ScriptComponentClass RplProp()] protected ref array< string > m_aLines
RplComponent m_RplComponent
SCR_CampaignFaction GetFaction()
void SCR_CampaignSuppliesComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
void SendNotification(int msgId, notnull IEntity user, int assetId=-1, int catalogType=-1)
ref array< SCR_EntityCatalogEntry > m_aAssetList
void OnAIAgentRemoved(SCR_AIGroup group, AIAgent ai)
SCR_EEntityRequestStatus GetRequestState(notnull SCR_EntityCatalogEntry entityEntry, IEntity user=null)
void ~SCR_CatalogEntitySpawnerComponent()
void DeletePreviewEntity()
Delete existing Preview entity at spawner.
SCR_CampaignSuppliesComponent GetSpawnerSupplyComponent()
ref array< float > m_aGracePeriodStartingTimes
ref array< RplId > m_aGracePeriodRequesters
SCR_CatalogEntitySpawnerComponentClass INSTANCES
static variable used to store all the instances created of this component.
ref array< EEditableEntityLabel > m_aAllowedLabels
bool RankCheck(notnull SCR_EntityCatalogEntry entityEntry, notnull IEntity user)
void SpawnAIGroupMember(ResourceName resName, notnull IEntity user, IEntity slotEntity, SCR_EntityLabelPointComponent rallyPoint=null)
bool IsSuppliesConsumptionEnabled()
bool m_bSuppliesConsumptionEnabled
ref array< RplId > m_aGracePeriodEntries
ScriptInvoker GetOnSpawnerSuppliesChanged()
void OnGroupWaypointFinished(notnull AIWaypoint wp)
void OnChimeraCharacterSpawned(notnull SCR_ChimeraCharacter ai, notnull IEntity user, SCR_EntityLabelPointComponent rallyPoint=null)
Called from PerformSpawn, if spawned entity is ChimeraCharacter.
SCR_EntitySpawnerSlotComponent GetLastKnownSuitableSlot(notnull SCR_EntityCatalogSpawnerData spawnerData)
Returns last known suitable free slot. Used to reduce amount of redundant slot checks and save perfor...
void AddKnownOccupiedSlot(notnull SCR_EntitySpawnerSlotComponent slot)
void OnAIGroupSpawned(notnull SCR_AIGroup group, notnull IEntity user, notnull IEntity slotEntity, SCR_EntityLabelPointComponent rallyPoint=null)
Called from PerformSpawn, if spawned entity is AIGroup.
ref array< EEditableEntityLabel > m_aIgnoredLabels
void UnregisterGracePeriod(notnull IEntity entity)
ActionsManagerComponent m_ActionManager
ref ScriptInvoker m_OnSpawnerSuppliesChanged
ScriptInvoker GetOnEntitySpawned()
ref array< ref Tuple2< SCR_AIGroup, SCR_AIGroup > > m_aGroupsToAssign
SCR_PlayerController GetPlayerControllerFromEntity(notnull IEntity userEntity)
bool CanRefund(RplId entityId, RplId userId)
void AddAISoldierToPlayerGroup(notnull SCR_ChimeraCharacter ai, notnull IEntity user)
void InitiateSpawn(notnull SCR_EntityCatalogEntry entityEntry, int userId, SCR_EntitySpawnerSlotComponent slot)
SCR_EntityCatalogEntry GetEntryAtIndex(int index)
Obtain Faction entity from AssetList on specific index.
ref array< EEntityCatalogType > m_aCatalogTypes
bool CanRequestAI(notnull IEntity user, int aiCount=1)
ref map< SCR_EntitySpawnerSlotComponent, WorldTimestamp > m_mKnownFreeSlots
SCR_EntitySpawnerSlotComponent GetFreeSlot(notnull SCR_EntityCatalogSpawnerData spawnerData)
SCR_EntitySpawnerSlotComponent GetFreeSlotFromArray(notnull array< SCR_EntitySpawnerSlotComponent > slots, notnull SCR_EntityCatalogSpawnerData spawnerData, notnull array< SCR_EntitySpawnerSlotComponent > occupiedSlots)
void ClearKnownSlots()
Manually clears known slots, thus forcing Spawner to do otherwise ignored checks.
bool CooldownCheck(notnull IEntity user)
void UpdateOccupiedSlots(out array< SCR_EntitySpawnerSlotComponent > occupiedSlots)
void AddSpawnerSupplies(float supplies)
float m_fPostGracePeriodRefundMultiplier
float GetPostGracePeriodRefundMultiplier()
bool SupplyComponentSearchCallback(IEntity ent)
Callback for Search query in EOnInit. Search will be stopped, if Base with Supply component is found.
ref map< AIWaypoint, SCR_AIGroup > m_mGroupWaypoints
SCR_ResourceComponent GetSpawnerResourceComponent()
void SetCurrentFactionCatalog()
Set Asset Catalog from currently owning faction. If null, asset list will be cleared.
float GetSpawnerResourceValue()
void AssignSupplyComponent(notnull SCR_CampaignSuppliesComponent supplyComp)
ref map< SCR_EntitySpawnerSlotComponent, WorldTimestamp > m_mKnownOccupiedSlots
bool IsInGracePeriod(IEntity entity)
void LockSpawnedVehicle(notnull IEntity owningUser)
void RegisterGracePeriod(notnull IEntity entity, notnull IEntity user, float startingTime=FLT_INF)
SCR_AIWaypoint CreateRallyPointWaypoint(notnull SCR_EntityLabelPointComponent rallyPoint)
Returns waypoint created as rally point for spawned unit.
void AssignResourceComponent(notnull SCR_ResourceComponent component)
Assign resource component to handle resources of spawner.
const float UPDATE_PERIOD
void AddAssetsFromCatalog(notnull SCR_EntityCatalog entityCatalog, bool overwriteOld=false)
Faction GetRequesterFaction(notnull IEntity user)
IEntity SpawnEntity(ResourceName entityResourceName, notnull IEntity slotOwner)
SCR_SpawnerRequestComponent GetRequestComponentFromPlayerEntity(notnull IEntity playerEntity)
ref ScriptInvoker m_OnEntitySpawned
SCR_PrefabPreviewEntity GetPreviewEntity()
void CreatePreviewEntity(notnull SCR_EntityCatalogEntry spawnData, notnull SCR_EntitySpawnerSlotComponent slot, SCR_EEntityRequestStatus reqStatus=SCR_EEntityRequestStatus.CAN_SPAWN)
void SCR_CharacterRankComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
SCR_CharacterSoundComponentClass GetComponentData()
void SCR_CommandingManagerComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
enum SCR_ECompassType EntityEditorProps(category:"GameScripted/Gadgets", description:"Compass", color:"0 0 255 255")
Prefab data class for compass component.
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
void SCR_GameModeCampaign(IEntitySource src, IEntity parent)
void SCR_GroupsManagerComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
IEntity m_PreviewEntity
override void EOnFrame(IEntity owner, float timeSlice)
EResourceGeneratorID
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
ref array< SCR_EntitySpawnerSlotComponent > m_aNearSlots
ref array< SCR_EntitySpawnerSlotComponent > m_aChildSlots
SCR_ResourceComponent m_ResourceComponent
proto external Managed FindComponent(typename typeName)
proto external void GetBounds(out vector mins, out vector maxs)
proto external void GetWorldTransform(out vector mat[])
See IEntity::GetTransform.
proto external BaseWorld GetWorld()
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
Replication item identifier.
Definition RplId.c:14
array< SCR_ChimeraCharacter > GetAIMembers()
SCR_AIGroup GetSlave()
ScriptInvoker GetOnAgentRemoved()
ScriptInvoker GetOnWaypointCompleted()
static void IgnoreSpawning(bool ignore)
int GetLeaderID()
Takes care of Campaign-specific server <> client communication and requests.
void SetSpawnerData(SCR_EntityCatalogEntry entityData)
Get Data type return Returns Catalog type of holder *EEntityCatalogType GetCatalogType()
Get random variant or default prefab return Random variant or default prefab *ResourceName GetRandomDefaultOrVariantPrefab()
Check if entity can be spawned in slot of given size param slotSize Slot size to check return Returns true if entity can spawn in given slot size *bool CanSpawnInSlot(SCR_EEntitySpawnerSlotType slotSize)
Get supply cost of spawning Entity return Supply cost *int GetSupplyCost()
Check if entity can be spawned by player with specific rank Will check if given rank is equal or greater then minimum required rank param rank Rank of player that request the spawn return Returns true if player has the required rank *bool HasRequiredRank(SCR_ECharacterRank rank)
SCR_EntityCatalog GetFactionEntityCatalogOfType(EEntityCatalogType catalogType, bool printNotFound=true)
static bool IsEditMode()
Definition Functions.c:1566
SCR_ResourceGenerationResponse RequestGeneration(float resourceAmount, SCR_ResourceGenerator generator=null)
Definition Types.c:486
enum EPhysicsLayerPresets Vehicle
Definition gameLib.c:24
void EntitySpawnParams()
Definition gameLib.c:130
IEntity GetOwner()
Owner entity of the fuel tank.
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
EEditorTransformVertical
Vertical transformation mode.
EntityEvent
Various entity events.
Definition EntityEvent.c:14
proto external PlayerController GetPlayerController()
TypeID handle64 Count()
ScriptInvokerBase< func > ScriptInvoker
Definition tools.c:134