Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_CampaignBuildingProviderComponent.c
Go to the documentation of this file.
1[EntityEditorProps(category: "GameScripted/Building", description: "Component attached to a provider, responsible for basic provider behaviour.")]
5
6class SCR_CampaignBuildingProviderComponent : SCR_MilitaryBaseLogicComponent
7{
8 [Attribute("", UIWidgets.EditBox, "Name of provider shown in provider interface", "")]
9 protected string m_sProviderDisplayName;
10
11 [Attribute("0", UIWidgets.CheckBox, "Can the building mode at this provider executed only via user action?")]
13
14 [Attribute("0", UIWidgets.CheckBox, "Can be used by any faction")]
15 protected bool m_bAnyFactionCanUse;
16
17 [Attribute("0", UIWidgets.CheckBox, "Master provider is for example HQ with other service (providers) in vicinity.")]
18 protected bool m_bIsMasterProvider;
19
20 [Attribute("0", UIWidgets.CheckBox, "When opening a Free Roam Building mode, try to use master provider. Master provider is HQ where the service is registered in.")]
21 protected bool m_bUseMasterProvider;
22
23 [Attribute("0", UIWidgets.CheckBox, "Reads data(EEditableEntityLabel) from available providers as and extends the building option.")]
25
26 [Attribute("0", UIWidgets.CheckBox, "Register at nearby base, if available.")]
27 protected bool m_bRegisterAtBase;
28
29 [Attribute("0", UIWidgets.CheckBox, "If set, player can command friendly AI in building radius.")]
30 protected bool m_bCanCommandAI;
31
32 [Attribute("1", UIWidgets.CheckBox, "Obstruct view when an enemy is present within the radius of the building.")]
34
35 [Attribute("50", UIWidgets.EditBox, "Building radius")]
36 protected float m_fBuildingRadius;
37
38 [Attribute(defvalue: "1", uiwidget: UIWidgets.ComboBox, desc: "Minimal rank that allows player to use the provider to build structures.", enums: ParamEnumArray.FromEnum(SCR_ECharacterRank))]
39 protected SCR_ECharacterRank m_iRank;
40
41 [Attribute(desc: "Fill in the budgets to be used with this provider")]
42 protected ref array<ref SCR_CampaignBuildingBudgetToEvaluateData> m_aBudgetsToEvaluate;
43
44 [Attribute(desc: "Traits this provider will provide. Each trait represents a tab in building interface. The tabs have to be defined in building mode's SCR_ContentBrowserEditorComponent.", UIWidgets.ComboBox, enums: ParamEnumArray.FromEnum(EEditableEntityLabel))]
45 protected ref array<EEditableEntityLabel> m_aAvailableTraits;
46
48 [RplProp()]
49 protected int m_iCurrentPropValue;
50
52 [RplProp()]
53 protected int m_iCurrentAIValue;
54
55 protected SCR_ResourceComponent m_ResourceComponent;
56
57 protected ref array<int> m_aActiveUsersIDs = {};
58 protected ref array<int> m_aAvailableUsersIDs = {};
59 protected ref array<SCR_CampaignBuildingBudgetToEvaluateData> m_aShownBudget = {};
60
61 protected static ref ScriptInvokerVoid s_OnProviderCreated = new ScriptInvokerVoid();
63
64 protected const int MOVING_CHECK_PERIOD = 1000;
65 protected const int PROVIDER_SPEED_TO_REMOVE_BUILDING_SQ = 1;
66
67 protected ref array<ref Tuple2<int, WorldTimestamp>> m_aPlacingCooldown = {};
68 protected bool m_bCooldownClientLock;
70
71 SCR_CampaignBuildingProviderComponent m_MasterProviderComponent;
72
73 private ref map<EEditableEntityBudget, int> m_accumulatedBudgetChanges = new map<EEditableEntityBudget, int>;
74 bool m_changesAccumulated = false;
75
76 //------------------------------------------------------------------------------------------------
77 void AccumulateBudgetChange(EEditableEntityBudget budgetType, int amount)
78 {
79 m_accumulatedBudgetChanges[budgetType] = m_accumulatedBudgetChanges[budgetType] + amount;
80
81 if(!m_changesAccumulated)
82 {
83 GetGame().GetCallqueue().CallLater(ClearAccumulatedBudgetChanges);
84 m_changesAccumulated = true;
85 }
86 }
87
88 //------------------------------------------------------------------------------------------------
89 int GetAccumulatedBudgetChanges(EEditableEntityBudget type)
90 {
91 int value = 0;
92 bool found = m_accumulatedBudgetChanges.Find(type, value);
93
94 if(found)
95 return value;
96
97 return -1;
98 }
99
100 //------------------------------------------------------------------------------------------------
101 void ClearAccumulatedBudgetChanges()
102 {
103 m_accumulatedBudgetChanges.Clear();
104 m_changesAccumulated = false;
105 }
106
107 //------------------------------------------------------------------------------------------------
108 bool IsThereEnoughSupplies(int availableSupplies, int supplyCost, int accumulatedSupplyCost)
109 {
110 int totalSupplyCost = supplyCost;
111
112 if(accumulatedSupplyCost != -1)
113 totalSupplyCost += accumulatedSupplyCost;
114
115 return totalSupplyCost <= availableSupplies;
116 }
117
118 //------------------------------------------------------------------------------------------------
119 bool IsThereEnoughBudgetToSpawn(notnull array<ref SCR_EntityBudgetValue> budgetCosts)
120 {
121 if(budgetCosts.IsEmpty())
122 return true;
123
124 SCR_BaseGameMode gameMode = SCR_BaseGameMode.Cast(GetGame().GetGameMode());
125
126 foreach(SCR_EntityBudgetValue budget : budgetCosts)
127 {
128 const EEditableEntityBudget budgetType = budget.GetBudgetType();
129
130 SCR_CampaignBuildingBudgetToEvaluateData data = GetBudgetData(budgetType);
131
132 //budget shouldn't be evaluated, so we don't care
133 if(!data)
134 continue;
135
136 SCR_CampaignBuildingProviderComponent realProvider = this;
137 const int currentBudgetValue = GetBudgetValue(budgetType, realProvider);
138
139 const int budgetIncrease = budget.GetBudgetValue();
140 const int accumulatedBudgetChanges = realProvider.GetAccumulatedBudgetChanges(budgetType);
141
142 if(budgetType == EEditableEntityBudget.CAMPAIGN)
143 {
144 //if supplies budget is disabled by GM we dont care
145 if(!gameMode.IsResourceTypeEnabled(EResourceType.SUPPLIES))
146 continue;
147
148 bool enoughSupplies = realProvider.IsThereEnoughSupplies(currentBudgetValue, budgetIncrease, accumulatedBudgetChanges);
149
150 //not enough supplies, we return false
151 if(!enoughSupplies)
152 return false;
153
154 //enough supplies, continue checking for other budgets
155 continue;
156 }
157
158 //max budget is unlimited, always allowed
159 const int maxBudgetValue = GetMaxBudgetValueFromMasterIfNeeded(budgetType);
160 if(maxBudgetValue == -1)
161 continue;
162
163 if(budgetIncrease + accumulatedBudgetChanges + currentBudgetValue > maxBudgetValue)
164 return false;
165 }
166
167 foreach(SCR_EntityBudgetValue budget : budgetCosts)
168 {
169 const EEditableEntityBudget budgetType = budget.GetBudgetType();
170 SCR_CampaignBuildingProviderComponent realProvider = this;
171
172 //get real provider if needed
173 const int currentBudgetValue = GetBudgetValue(budgetType, realProvider);
174
175 realProvider.AccumulateBudgetChange(budgetType, budget.GetBudgetValue());
176 }
177
178 //we accumulate supplies changes here
179 return true;
180 }
181
182 //------------------------------------------------------------------------------------------------
183 int GetBudgetValue(EEditableEntityBudget type, out SCR_CampaignBuildingProviderComponent componentToUse)
184 {
185 bool useMaster = UseMasterProviderBudget(EEditableEntityBudget.PROPS, componentToUse);
186
187 if(type == EEditableEntityBudget.PROPS)
188 return GetCurrentPropValue();
189
191 return GetCurrentAIValue();
192
193 //if its not supplies I have no idea how are we suppossed to handle it xdd
194 if(type != EEditableEntityBudget.CAMPAIGN)
195 return -1;
196
197 //check supplies
198 SCR_ResourceComponent resource = componentToUse.GetResourceComponent();
199
200 if(!resource)
201 return false;
202
203 SCR_ResourceConsumer consumer = resource.GetConsumer(EResourceGeneratorID.DEFAULT, EResourceType.SUPPLIES);
204 //Get number of supplies
205
206 float currentSupplies = consumer.GetAggregatedResourceValue();
207 return currentSupplies;
208 }
209
210 //------------------------------------------------------------------------------------------------
212 string GetProviderDisplayName()
213 {
214 return m_sProviderDisplayName;
215 }
216
217 //------------------------------------------------------------------------------------------------
219 bool UseMasterProvider()
220 {
222 }
223
224 //------------------------------------------------------------------------------------------------
226 bool IsMasterProvider()
227 {
228 return m_bIsMasterProvider;
229 }
230
231 //------------------------------------------------------------------------------------------------
232 bool UseAllAvailableProviders()
233 {
235 }
236
237 //------------------------------------------------------------------------------------------------
238 void SetUseAllAvailableProvidersByPlayer(bool useByPlayer)
239 {
241 }
242
243 //------------------------------------------------------------------------------------------------
245 bool CanCommandAI()
246 {
247 return m_bCanCommandAI;
248 }
249
250 //------------------------------------------------------------------------------------------------
252 bool ObstrucViewWhenEnemyInRange()
253 {
255 }
256
257 //------------------------------------------------------------------------------------------------
260 {
261 // Check bases this service is registered to. If non, it's standalone, return itself.
262 array<SCR_MilitaryBaseComponent> bases = {};
263 array<SCR_CampaignBuildingProviderComponent> providers = {};
264
265 GetBases(bases);
266
267 foreach (SCR_MilitaryBaseComponent base : bases)
268 {
269 base.GetBuildingProviders(providers);
270
271 foreach (SCR_CampaignBuildingProviderComponent provider : providers)
272 {
273 if (provider.IsMasterProvider())
274 return provider.GetOwner();
275 }
276 }
277
278 return GetOwner();
279 }
280
281 //------------------------------------------------------------------------------------------------
283 bool UseMasterProviderBudget(EEditableEntityBudget budget, out SCR_CampaignBuildingProviderComponent masterProviderComponent)
284 {
286 return false;
287
288 IEntity masterProvider;
289
290 foreach (SCR_CampaignBuildingBudgetToEvaluateData budgetData : m_aBudgetsToEvaluate)
291 {
292 if (budgetData.GetBudget() == budget && budgetData.UseMasterProviderBudget())
293 {
294 masterProvider = GetMasterProviderEntity();
295 if (masterProvider == GetOwner())
296 return false;
297
298 masterProviderComponent = SCR_CampaignBuildingProviderComponent.Cast(masterProvider.FindComponent(SCR_CampaignBuildingProviderComponent));
299 return true;
300 }
301 }
302
303 return false;
304 }
305
306 //------------------------------------------------------------------------------------------------
307 void SetClientLock(bool lock, IEntity provider, int playerId)
308 {
309 PlayerController playerController = GetGame().GetPlayerManager().GetPlayerController(playerId);
310 if (!playerController)
311 return;
312
313 SCR_CampaignBuildingNetworkComponent buildingNetworkComponent = SCR_CampaignBuildingNetworkComponent.Cast(playerController.FindComponent(SCR_CampaignBuildingNetworkComponent));
314 if (!buildingNetworkComponent)
315 return;
316
317 buildingNetworkComponent.SetClientLock(lock, provider);
318 }
319
320 //------------------------------------------------------------------------------------------------
321 void SetCooldownClientLock(bool val)
322 {
324
327 }
328
329 //------------------------------------------------------------------------------------------------
331 void SetPlayerCooldown(int playerId, int cooldownTime)
332 {
333 ChimeraWorld world = GetOwner().GetWorld();
334 if (!world)
335 return;
336
337 WorldTimestamp timestamp = world.GetServerTimestamp();
338 int existingEntryId = -1;
339 foreach (int i, Tuple2<int, WorldTimestamp> cooldownEntry : m_aPlacingCooldown)
340 {
341 if (cooldownEntry.param1 != playerId)
342 continue;
343
344 if (cooldownEntry.param2.DiffMilliseconds(timestamp) * 0.001 > cooldownTime)
345 continue;
346
347 existingEntryId = i;
348 break;
349 }
350
351 if (existingEntryId >= 0) // if player already has a cooldown entry, then lest just extend it, instead of adding more entries for him
352 m_aPlacingCooldown[existingEntryId].param2 = timestamp.PlusMilliseconds(CalculateCooldownTime(playerId, cooldownTime) * 1000);
353 else
354 m_aPlacingCooldown.Insert(new Tuple2<int, WorldTimestamp>(playerId, world.GetServerTimestamp().PlusMilliseconds(CalculateCooldownTime(playerId, cooldownTime) * 1000)));
355
356 SetClientLock(true, GetOwner(), playerId);
357
358 ScriptCallQueue callqueue = GetGame().GetCallqueue();
359 if (callqueue.GetRemainingTime(UpdateCooldownTimer) < 0) // add update call only if there isnt one already added
360 callqueue.CallLater(UpdateCooldownTimer, 250, true);
361 }
362
363 //------------------------------------------------------------------------------------------------
365 void RemovePlayerCooldowns(int playerId)
366 {
367 if (!m_aPlacingCooldown || m_aPlacingCooldown.IsEmpty())
368 return;
369
370 for (int i = m_aPlacingCooldown.Count() -1 ; i >= 0; i--)
371 {
372 if (m_aPlacingCooldown[i].param1 == playerId)
373 m_aPlacingCooldown.Remove(i);
374 }
375
376 SetClientLock(false, GetOwner(), playerId);
377 }
378
379 //------------------------------------------------------------------------------------------------
381 protected void UpdateCooldownTimer()
382 {
383 ChimeraWorld world = GetOwner().GetWorld();
384 if (!world)
385 return;
386
387 bool cooldownChange;
388
389 for (int i = m_aPlacingCooldown.Count() - 1; i >= 0; i--)
390 {
391 if (!m_aPlacingCooldown[i].param2.Greater(world.GetServerTimestamp()))
392 {
394 m_aPlacingCooldown.Remove(i);
395 cooldownChange = true;
396 }
397 }
398
399 if (m_OnCooldownLockUpdated && cooldownChange)
401
402 if (m_aPlacingCooldown.IsEmpty())
403 GetGame().GetCallqueue().Remove(UpdateCooldownTimer);
404 }
405
406 //------------------------------------------------------------------------------------------------
408 bool HasCooldownSet(int playerId)
409 {
410 return m_bCooldownClientLock || !m_aPlacingCooldown.IsEmpty();
411 }
412
413 //------------------------------------------------------------------------------------------------
415 float GetCooldownValue(int playerId)
416 {
417 ChimeraWorld world = GetOwner().GetWorld();
418 if (!world)
419 return 0;
420
421 WorldTimestamp timestamp = world.GetServerTimestamp();
422 foreach (Tuple2<int, WorldTimestamp> cooldownEntry : m_aPlacingCooldown)
423 {
424 if (cooldownEntry.param1 != playerId)
425 continue;
426
427 return cooldownEntry.param2.DiffMilliseconds(timestamp) * 0.001;
428 }
429
430 return 0;
431 }
432
433 //------------------------------------------------------------------------------------------------
441
442 //------------------------------------------------------------------------------------------------
443 override void RegisterBase(notnull SCR_MilitaryBaseComponent base)
444 {
446 return;
447
448 super.RegisterBase(base);
449 }
450
451 //------------------------------------------------------------------------------------------------
454 {
455 return m_bRegisterAtBase;
456 }
457
458 //------------------------------------------------------------------------------------------------
460 SCR_MilitaryBaseComponent GetMilitaryBaseComponent()
461 {
462 array<SCR_MilitaryBaseComponent> bases = {};
463 GetBases(bases);
464
465 if (bases.IsEmpty())
466 return null;
467
468 return bases[0];
469 }
470
471 //------------------------------------------------------------------------------------------------
474 {
475 array<SCR_MilitaryBaseComponent> bases = {};
476 GetBases(bases);
477
479 foreach (SCR_MilitaryBaseComponent base : bases)
480 {
481 campaignBase = SCR_CampaignMilitaryBaseComponent.Cast(base);
482 if (campaignBase)
483 return campaignBase;
484 }
485
486 return null;
487 }
488
489 //------------------------------------------------------------------------------------------------
491 SCR_ECharacterRank GetAccessRank()
492 {
493 return m_iRank;
494 }
495
496 //------------------------------------------------------------------------------------------------
499 {
500 return m_fBuildingRadius;
501 }
502
503 //------------------------------------------------------------------------------------------------
506 {
508 if (!budgetData)
509 return -1;
510
512 if (maxValueBudgetData)
513 return maxValueBudgetData.GetMaxValue();
514
515 return -1;
516 }
517
518 //------------------------------------------------------------------------------------------------
521 {
523 if (!budgetData)
524 return -1;
525
526 SCR_CampaignBuildingProviderComponent masterProviderComponent;
527
528 //if we should use the master's budget, also check master's budget no?
529 if (UseMasterProviderBudget(budgetData.GetBudget(), masterProviderComponent))
530 return masterProviderComponent.GetMaxBudgetValue(budget);
531
532 //otherwise return normal max budget
534 if (maxValueBudgetData)
535 return maxValueBudgetData.GetMaxValue();
536
537 return -1;
538 }
539
540 //------------------------------------------------------------------------------------------------
543 {
544 return m_iCurrentPropValue;
545 }
546
547 //------------------------------------------------------------------------------------------------
549 void SetPropValue(int value)
550 {
551 m_iCurrentPropValue = value;
552
553 SCR_CampaignBuildingProviderComponent masterProviderComponent;
554
555 if (UseMasterProviderBudget(EEditableEntityBudget.PROPS, masterProviderComponent))
556 masterProviderComponent.SetPropValue(value);
557
558 Replication.BumpMe();
559 }
560
561 //------------------------------------------------------------------------------------------------
564 void AddPropValue(int value)
565 {
566 m_iCurrentPropValue += value;
567
568 SCR_CampaignBuildingProviderComponent masterProviderComponent;
569
570 if (UseMasterProviderBudget(EEditableEntityBudget.PROPS, masterProviderComponent))
571 masterProviderComponent.AddPropValue(value);
572
573 Replication.BumpMe();
574 }
575
576 //------------------------------------------------------------------------------------------------
578 {
579 SCR_CampaignBuildingProviderComponent masterProviderComponent;
580
581 if (UseMasterProviderBudget(EEditableEntityBudget.AI, masterProviderComponent))
582 return masterProviderComponent.GetCurrentAIValue();
583
584 return m_iCurrentAIValue;
585 }
586
587 //------------------------------------------------------------------------------------------------
588 void SetAIValue(int value)
589 {
590 m_iCurrentAIValue = value;
591
592 SCR_CampaignBuildingProviderComponent masterProviderComponent;
593
594 if (UseMasterProviderBudget(EEditableEntityBudget.AI, masterProviderComponent))
595 masterProviderComponent.SetAIValue(value);
596
597 Replication.BumpMe();
598 }
599
600 //------------------------------------------------------------------------------------------------
601 void AddAIValue(int value)
602 {
603 m_iCurrentAIValue += value;
604
605 SCR_CampaignBuildingProviderComponent masterProviderComponent;
606
607 if (UseMasterProviderBudget(EEditableEntityBudget.AI, masterProviderComponent))
608 masterProviderComponent.AddAIValue(value);
609
610 Replication.BumpMe();
611 }
612
613 //------------------------------------------------------------------------------------------------
615 protected void OnAIRemoved(IEntity ent)
616 {
617 RemoveEvents(ent);
618 AddAIValue(-1);
619 }
620
621 //------------------------------------------------------------------------------------------------
624 {
625 SCR_EditableCharacterComponent editableCharacter = SCR_EditableCharacterComponent.Cast(ent.FindComponent(SCR_EditableCharacterComponent));
626 if (!editableCharacter)
627 return;
628
629 editableCharacter.GetOnDestroyed().Insert(OnAIRemoved);
630 editableCharacter.GetOnDeleted().Insert(OnAIRemoved);
631 }
632
633 //------------------------------------------------------------------------------------------------
635 protected void RemoveEvents(IEntity ent)
636 {
637 SCR_EditableCharacterComponent editableCharacter = SCR_EditableCharacterComponent.Cast(ent.FindComponent(SCR_EditableCharacterComponent));
638 if (!editableCharacter)
639 return;
640
641 editableCharacter.GetOnDestroyed().Remove(OnAIRemoved);
642 editableCharacter.GetOnDeleted().Remove(OnAIRemoved);
643 }
644
645 //------------------------------------------------------------------------------------------------
646 array<EEditableEntityLabel> GetAvailableTraits()
647 {
648 array<EEditableEntityLabel> availableTraits = {};
649 availableTraits.Copy(m_aAvailableTraits);
650
651 // if Establishing Bases is disabled, remove Base building trait
653 if (campaign && !campaign.GetEstablishingBasesEnabled())
654 availableTraits.RemoveItem(EEditableEntityLabel.SERVICE_HQ);
655
656 // extends available traits from other providers traits
657 if (!UseAllAvailableProviders())
658 return availableTraits;
659
660 array<SCR_MilitaryBaseComponent> bases = {};
661 int count = GetBases(bases);
662 if (count == 0)
663 return availableTraits;
664
665 array<SCR_CampaignBuildingProviderComponent> campaignBuildingProvides = {};
666 int providerCount = bases[0].GetBuildingProviders(campaignBuildingProvides);
667 bool isVehicle;
668 array<EEditableEntityLabel> otherProviderAvailableTraits;
669 int providerAvailableTraitCount;
670
671 for (int i = 0; i < providerCount; i++)
672 {
673 if (campaignBuildingProvides[i].UseAllAvailableProviders())
674 continue;
675
676 // checks if the provider is in the vehicle and skips them, we need only providers from compositions
677 isVehicle = Vehicle.Cast(campaignBuildingProvides[i].GetOwner().GetParent());
678 if (isVehicle)
679 continue;
680
681 otherProviderAvailableTraits = campaignBuildingProvides[i].GetAvailableTraits();
682 providerAvailableTraitCount = otherProviderAvailableTraits.Count();
683
684 for (int j = 0; j < providerAvailableTraitCount; j++)
685 {
686 if (!availableTraits.Contains(otherProviderAvailableTraits[j]))
687 {
688 availableTraits.Insert(otherProviderAvailableTraits[j]);
689 }
690 }
691 }
692
693 return availableTraits;
694 }
695
696 //------------------------------------------------------------------------------------------------
697 static bool CanBeUsedToEstablishBase(IEntity provider, int userPlayerId)
698 {
700 if (!gameMode)
701 return true; // The construction of command posts in allowed in every game mode
702
703 if (!gameMode.GetEstablishingBasesEnabled())
704 return false; // unless it is disabled
705
706 FactionAffiliationComponent affiliationComp;
707 while (provider && affiliationComp == null)
708 {
709 affiliationComp = FactionAffiliationComponent.Cast(provider.FindComponent(FactionAffiliationComponent));
710 if (!affiliationComp)
711 provider = provider.GetParent();
712 }
713
714 if (!affiliationComp)
715 return false;
716
717 Faction providerFaction;
718 if (Vehicle.Cast(provider))
719 providerFaction = affiliationComp.GetDefaultAffiliatedFaction();
720 else
721 providerFaction = affiliationComp.GetAffiliatedFaction();
722
723 if (!providerFaction)
724 return false;
725
726 SCR_CampaignFaction campaignFaction = SCR_CampaignFaction.Cast(providerFaction);
727 if (campaignFaction && !campaignFaction.CanBuildBases())
728 return false;
729
730 Faction playerFaction = SCR_FactionManager.SGetPlayerFaction(userPlayerId);
731 return playerFaction && playerFaction == providerFaction;
732 }
733
734 //------------------------------------------------------------------------------------------------
735 override void OnPostInit(IEntity owner)
736 {
737 SetEventMask(owner, EntityEvent.INIT);
738
739 super.OnPostInit(owner);
740 }
741
742 //------------------------------------------------------------------------------------------------
743 override void EOnInit(IEntity owner)
744 {
745 super.EOnInit(owner);
746
747 if (System.IsConsoleApp() || !GetGame().GetPlayerController())
749 }
750
751 //------------------------------------------------------------------------------------------------
754 void AddNewActiveUser(int userID)
755 {
756 m_aActiveUsersIDs.Insert(userID);
758 }
759
760 //------------------------------------------------------------------------------------------------
763 void RemoveActiveUser(int userID)
764 {
765 m_aActiveUsersIDs.RemoveItem(userID);
766 }
767
768 //------------------------------------------------------------------------------------------------
771 int GetActiveUsers(out notnull array<int> users)
772 {
773 return users.Copy(m_aActiveUsersIDs);
774 }
775
776 //------------------------------------------------------------------------------------------------
780 bool ContainActiveUsers(int playerId)
781 {
782 return m_aActiveUsersIDs.Contains(playerId);
783 }
784
785 //------------------------------------------------------------------------------------------------
788 void AddNewAvailableUser(int userID)
789 {
790 m_aAvailableUsersIDs.Insert(userID);
792 }
793
794 //------------------------------------------------------------------------------------------------
797 void RemoveAvailableUser(int userID)
798 {
799 m_aAvailableUsersIDs.RemoveItem(userID);
800 }
801
802 //------------------------------------------------------------------------------------------------
805 int GetAvailableUsers(out array<int> users)
806 {
807 return users.Copy(m_aAvailableUsersIDs);
808 }
809
810 //------------------------------------------------------------------------------------------------
814 bool ContainAvailableUsers(int playerId)
815 {
816 return m_aAvailableUsersIDs.Contains(playerId);
817 }
818
819 //------------------------------------------------------------------------------------------------
824 void RequestEnterBuildingMode(int playerID, bool userActionUsed, bool useAllAvailableProviders = false)
825 {
826 SCR_CampaignBuildingNetworkComponent networkComponent = GetNetworkManager();
827 if (!networkComponent)
828 return;
829
831 if (!editorManager)
832 return;
833
835 SetOnPlayerTeleported(playerID);
836 editorManager.GetOnOpenedServer().Insert(BuildingModeCreated);
837 editorManager.GetOnClosed().Insert(OnModeClosed);
838 networkComponent.RequestEnterBuildingMode(GetOwner(), playerID, m_bUserActionActivationOnly, userActionUsed, useAllAvailableProviders);
839 }
840
841 //------------------------------------------------------------------------------------------------
843 void SetOnPlayerTeleported(int playerID)
844 {
845 PlayerController playerController = GetGame().GetPlayerController();
846 if (!playerController)
847 return;
848
849 SCR_PlayerTeleportedFeedbackComponent playerTeleportComponent = SCR_PlayerTeleportedFeedbackComponent.Cast(playerController.FindComponent(SCR_PlayerTeleportedFeedbackComponent));
850 if (!playerTeleportComponent)
851 return;
852
853 playerTeleportComponent.GetOnPlayerTeleported().Insert(PlayerTeleported);
854 }
855
856 //------------------------------------------------------------------------------------------------
859 {
861 if (!player)
862 return;
863
864 SCR_CharacterControllerComponent controller = SCR_CharacterControllerComponent.Cast(player.GetCharacterController());
865 if (controller)
866 controller.m_OnLifeStateChanged.Insert(OnLifeStateChanged);
867 }
868
869 //------------------------------------------------------------------------------------------------
871 void OnLifeStateChanged(ECharacterLifeState previousLifeState, ECharacterLifeState newLifeState)
872 {
873 if (newLifeState == ECharacterLifeState.ALIVE)
874 return;
875
876 SCR_CampaignBuildingNetworkComponent networkComponent = GetNetworkManager();
877 if (!networkComponent)
878 return;
879
880 networkComponent.RemoveEditorMode(SCR_PlayerController.GetLocalPlayerId(), GetOwner());
881 }
882
883 //------------------------------------------------------------------------------------------------
888 void PlayerTeleported(SCR_EditableCharacterComponent character, bool isLongFade, SCR_EPlayerTeleportedReason teleportReason)
889 {
890 SCR_CampaignBuildingNetworkComponent networkComponent = GetNetworkManager();
891 if (!networkComponent)
892 return;
893
894 networkComponent.RemoveEditorMode(SCR_PlayerController.GetLocalPlayerId(), GetOwner());
895
896 }
897
898 //------------------------------------------------------------------------------------------------
901 {
903 if (!player)
904 return;
905
906 SCR_CharacterControllerComponent controller = SCR_CharacterControllerComponent.Cast(player.GetCharacterController());
907 if (controller)
908 controller.m_OnLifeStateChanged.Remove(OnLifeStateChanged);
909 }
910
911 //------------------------------------------------------------------------------------------------
914 {
916 if (!factionComponent)
917 return;
918
919 factionComponent.GetOnFactionChanged().Insert(OnBaseOwnerChanged);
920 }
921
922 //------------------------------------------------------------------------------------------------
925 {
927 if (!comp)
928 return;
929
931 }
932
933 //------------------------------------------------------------------------------------------------
936 {
938 if (!comp)
939 return;
940
942 }
943
944 //------------------------------------------------------------------------------------------------
948 void OnActiveUserDeath(SCR_CharacterControllerComponent characterControllerComponent, IEntity instigatorEntity, notnull Instigator instigator)
949 {
950 RemoveActiveUser(GetPlayerIdFromCharacterController(characterControllerComponent));
951 }
952
953 //------------------------------------------------------------------------------------------------
957 void OnAvailableUserDeath(SCR_CharacterControllerComponent characterControllerComponent, IEntity instigatorEntity, notnull Instigator instigator)
958 {
959 RemoveAvailableUser(GetPlayerIdFromCharacterController(characterControllerComponent));
960 }
961
962 //------------------------------------------------------------------------------------------------
965 {
967 if (!editorManager)
968 return;
969
970 editorManager.GetOnOpenedServer().Remove(BuildingModeCreated);
971
972 SCR_EditorModeEntity editorMode = editorManager.GetCurrentModeEntity();
973 if (!editorMode)
974 return;
975
976 SCR_PlacingEditorComponent placingComponent = SCR_PlacingEditorComponent.Cast(editorMode.FindComponent(SCR_PlacingEditorComponent));
977 if (!placingComponent)
978 return;
979
980 placingComponent.GetOnPlaceEntityServer().Insert(EntitySpawnedByProvider);
981 }
982
983 //------------------------------------------------------------------------------------------------
985 void EntitySpawnedByProvider(int prefabID, SCR_EditableEntityComponent editableEntity)
986 {
987 SCR_GameModeCampaign campaign = SCR_GameModeCampaign.GetInstance();
988 if (!campaign)
989 return;
990
991 if (m_aActiveUsersIDs.IsEmpty())
992 return;
993
994 IEntity player = GetGame().GetPlayerManager().GetPlayerControlledEntity(m_aActiveUsersIDs[0]);
995 campaign.OnEntityRequested(editableEntity.GetOwner(), player, SCR_Faction.Cast(GetEntityFaction(GetOwner())), this);
996 }
997
998 //------------------------------------------------------------------------------------------------
1001 {
1005
1006 m_aShownBudget.Clear();
1007
1008 SCR_CampaignBuildingNetworkComponent networkComponent = GetNetworkManager();
1009 if (!networkComponent)
1010 return;
1011
1012 networkComponent.RemoveEditorMode(SCR_PlayerController.GetLocalPlayerId(), GetOwner());
1013 }
1014
1015 //------------------------------------------------------------------------------------------------
1017 static ScriptInvokerVoid GetOnProviderCreated()
1018 {
1019 return s_OnProviderCreated;
1020 }
1021
1022 //------------------------------------------------------------------------------------------------
1025 {
1026 SCR_EditorManagerEntity editorManager = GetEditorManager();
1027 if (!editorManager)
1028 return;
1029
1030 editorManager.GetOnClosed().Remove(OnModeClosed);
1031 }
1032
1033 //------------------------------------------------------------------------------------------------
1036 {
1037 PlayerController playerController = GetGame().GetPlayerController();
1038 if (!playerController)
1039 return;
1040
1041 SCR_PlayerTeleportedFeedbackComponent playerTeleportComponent = SCR_PlayerTeleportedFeedbackComponent.Cast(playerController.FindComponent(SCR_PlayerTeleportedFeedbackComponent));
1042 if (!playerTeleportComponent)
1043 return;
1044
1045 playerTeleportComponent.GetOnPlayerTeleported().Remove(PlayerTeleported);
1046 }
1047
1048 //------------------------------------------------------------------------------------------------
1051 {
1053 }
1054
1055 //------------------------------------------------------------------------------------------------
1058 {
1059 return m_bAnyFactionCanUse;
1060 }
1061
1062 //------------------------------------------------------------------------------------------------
1064 protected SCR_CampaignBuildingNetworkComponent GetNetworkManager()
1065 {
1066 PlayerController playerController = GetGame().GetPlayerController();
1067 if (!playerController)
1068 return null;
1069
1070 return SCR_CampaignBuildingNetworkComponent.Cast(playerController.FindComponent(SCR_CampaignBuildingNetworkComponent));
1071 }
1072
1073 //------------------------------------------------------------------------------------------------
1076 {
1078 if (!core)
1079 return null;
1080
1081 return core.GetEditorManager();
1082 }
1083
1084 //------------------------------------------------------------------------------------------------
1087 {
1089 if (!core)
1090 return null;
1091
1092 return core.GetEditorManager(playerId);
1093 }
1094
1095 //------------------------------------------------------------------------------------------------
1097 {
1098 IEntity player = GetGame().GetPlayerManager().GetPlayerControlledEntity(playerID);
1099 if (!player)
1100 return null;
1101
1103 }
1104
1105 //------------------------------------------------------------------------------------------------
1107 {
1108 if (!characterControllerComponent)
1109 return -1;
1110
1111 IEntity ent = characterControllerComponent.GetOwner();
1112 if (!ent)
1113 return -1;
1114
1115 return GetGame().GetPlayerManager().GetPlayerIdFromControlledEntity(ent);
1116 }
1117
1118 //------------------------------------------------------------------------------------------------
1122 bool IsEntityFactionSame(notnull IEntity ent1, notnull IEntity ent2)
1123 {
1124 Faction ent1Faction = GetEntityFaction(ent1);
1125 if (!ent1Faction)
1126 return false;
1127
1128 Faction ent2Faction = GetEntityFaction(ent2);
1129 if (!ent2Faction)
1130 return false;
1131
1132 return ent1Faction == ent2Faction;
1133 }
1134
1135 //------------------------------------------------------------------------------------------------
1136 protected Faction GetEntityFaction(notnull IEntity ent)
1137 {
1138 FactionAffiliationComponent factionComp = FactionAffiliationComponent.Cast(ent.FindComponent(FactionAffiliationComponent));
1139
1140 // Seacrch for the faction component on parent entities as not always is it on the same component as this one (vehicle for an example)
1141 while (!factionComp && ent)
1142 {
1143 ent = ent.GetParent();
1144 if (ent)
1145 factionComp = FactionAffiliationComponent.Cast(ent.FindComponent(FactionAffiliationComponent));
1146 }
1147
1148 if (!factionComp)
1149 return null;
1150
1151 Faction faction = factionComp.GetAffiliatedFaction();
1152 if (!faction)
1153 faction = factionComp.GetDefaultAffiliatedFaction();
1154
1155 return faction;
1156 }
1157
1158 //------------------------------------------------------------------------------------------------
1163 protected void OnBaseOwnerChanged(FactionAffiliationComponent owner, Faction previousFaction, Faction newFaction)
1164 {
1165 // ToDo: In the future if the trigger activation will be enabled again, here I have to use a trigger range to find all entities which should be added and remove those on the list now.
1167 }
1168
1169 //------------------------------------------------------------------------------------------------
1171 SCR_ResourceComponent GetResourceComponent()
1172 {
1174 m_ResourceComponent = SCR_ResourceComponent.FindResourceComponent(GetOwner());
1175
1176 return m_ResourceComponent;
1177 }
1178
1179 //------------------------------------------------------------------------------------------------
1181 [Obsolete("SCR_CampaignBuildingProviderComponent.GetResourceComponent() should be used instead.")]
1186
1187 //------------------------------------------------------------------------------------------------
1190 {
1192 {
1193 if (budgetData.GetBudget() == budget)
1194 return budgetData;
1195 }
1196
1197 return null;
1198 }
1199
1200 //------------------------------------------------------------------------------------------------
1202 int GetBudgetTypesToEvaluate(notnull out array<ref EEditableEntityBudget> budgets)
1203 {
1205 {
1206 budgets.Insert(budgetData.GetBudget());
1207 }
1208
1209 return budgets.Count();
1210 }
1211
1212 //------------------------------------------------------------------------------------------------
1216 {
1218 return false;
1219
1221 {
1222 if (budgetData.GetBudget() == blockingBudget && budgetData.CanBeUsed())
1223 return true;
1224 }
1225
1226 return false;
1227 }
1228
1229 //------------------------------------------------------------------------------------------------
1232 {
1234 {
1235 if (budgetData.CanShowBudgetInUI() && !m_aShownBudget.Contains(budgetData))
1236 {
1237 m_aShownBudget.Insert(budgetData);
1238 return budgetData.GetBudget();
1239 }
1240 }
1241
1242 return -1;
1243 }
1244
1245 //------------------------------------------------------------------------------------------------
1247 int CalculateCooldownTime(int playerId, int cooldownTime)
1248 {
1250
1252 {
1253 if (budgetData.GetBudget() == EEditableEntityBudget.COOLDOWN)
1254 {
1255 cooldownBudgetData = SCR_CampaignBuildingCooldownWithRankBudgetToEvaluateData.Cast(budgetData);
1256 if (!cooldownBudgetData)
1257 continue;
1258
1259 return cooldownBudgetData.CooldownTimeModifier(playerId, cooldownTime);
1260 }
1261 }
1262
1263 return cooldownTime;
1264 }
1265
1266 //------------------------------------------------------------------------------------------------
1269 {
1270 BaseGameMode gameMode = GetGame().GetGameMode();
1271 if (!gameMode)
1272 return;
1273
1274 SCR_CampaignBuildingManagerComponent buildingManagerComponent = SCR_CampaignBuildingManagerComponent.Cast(gameMode.FindComponent(SCR_CampaignBuildingManagerComponent));
1275 if (!buildingManagerComponent)
1276 return;
1277
1278 bool isActiveUser;
1279 foreach (int playerId : m_aAvailableUsersIDs)
1280 {
1281 isActiveUser = false;
1282
1283 SCR_EditorManagerEntity editorManager = GetEditorManagerByID(playerId);
1284 if (!editorManager)
1285 return;
1286
1287 SCR_EditorModeEntity modeEntity = editorManager.FindModeEntity(EEditorMode.BUILDING);
1288 if (!modeEntity)
1289 return;
1290
1291 if (m_aActiveUsersIDs.Contains(playerId))
1292 {
1293 RemoveActiveUser(playerId);
1294 isActiveUser = true;
1295 }
1296
1297 buildingManagerComponent.RemoveProvider(playerId, this, isActiveUser);
1298 RemoveAvailableUser(playerId);
1299 }
1300
1302 }
1303
1304 //------------------------------------------------------------------------------------------------
1307 {
1308 if (IsProviderDynamic())
1309 GetGame().GetCallqueue().Remove(CheckProviderMove);
1310 }
1311
1312 //------------------------------------------------------------------------------------------------
1315 {
1316 if (IsProviderDynamic())
1317 GetGame().GetCallqueue().CallLater(CheckProviderMove, MOVING_CHECK_PERIOD, true);
1318 }
1319
1320 //------------------------------------------------------------------------------------------------
1322 private void CheckProviderMove()
1323 {
1324 IEntity mainParent = SCR_EntityHelper.GetMainParent(GetOwner(), true);
1325 if (!mainParent)
1326 return;
1327
1328 Physics providerPhysics = mainParent.GetPhysics();
1329 if (!providerPhysics)
1330 return;
1331
1332 vector velocity = providerPhysics.GetVelocity();
1333
1334 if ((velocity.LengthSq()) > PROVIDER_SPEED_TO_REMOVE_BUILDING_SQ)
1336 }
1337
1338 //------------------------------------------------------------------------------------------------
1340 private bool IsProviderDynamic()
1341 {
1342 IEntity mainParent = SCR_EntityHelper.GetMainParent(GetOwner(), true);
1343 if (!mainParent)
1344 return false;
1345
1346 Physics providerPhysics = mainParent.GetPhysics();
1347 if (!providerPhysics)
1348 return false;
1349
1350 return providerPhysics.IsDynamic();
1351 }
1352
1353 //------------------------------------------------------------------------------------------------
1356 bool IsEnemyFaction(notnull SCR_ChimeraCharacter char)
1357 {
1358 Faction faction = char.GetFaction();
1359 if (!faction)
1360 return false;
1361
1362 SCR_CampaignFactionManager factionManager = SCR_CampaignFactionManager.Cast(GetGame().GetFactionManager());
1363 if (!factionManager)
1364 return false;
1365
1366 Faction playerFaction = factionManager.GetLocalPlayerFaction();
1367 if (!playerFaction)
1368 return false;
1369
1370 return playerFaction.IsFactionEnemy(faction);
1371 }
1372
1373 //------------------------------------------------------------------------------------------------
1374 override bool RplLoad(ScriptBitReader reader)
1375 {
1376 s_OnProviderCreated.Invoke();
1377 return true;
1378 }
1379
1380 //------------------------------------------------------------------------------------------------
1381 // destructor
1382 void ~SCR_CampaignBuildingProviderComponent()
1383 {
1384 if (!m_aAvailableUsersIDs.IsEmpty())
1386 }
1387}
EEditableEntityBudget
EEditableEntityLabel
ArmaReforgerScripted GetGame()
Definition game.c:1398
override bool RplLoad(ScriptBitReader reader)
SCR_BaseGameMode GetGameMode()
SCR_CacheNoteComponentClass ScriptComponentClass RplProp()] protected ref array< string > m_aLines
IEntity GetMasterProviderEntity()
SCR_CharacterControllerComponent GetCharacterControllerComponent()
void RequestEnterBuildingMode(IEntity provider, int playerID, bool UserActionActivationOnly, bool UserActionUsed, bool useAllAvailableProviders=false)
void SetClientLock(bool lock, IEntity provider)
SCR_ECharacterRank m_iRank
SCR_CampaignSuppliesComponent GetSuppliesComponent()
override void RegisterBase(notnull SCR_MilitaryBaseComponent base)
void SetOnPlayerTeleported(int playerID)
void SetOnEntityKilled(IEntity ent)
Set an event called when entity spawned by this provider get killed.
EEditableEntityBudget GetShownBudget()
Evaluate all set budgets with this provider and return first one that is marked as to be shown in UI.
SCR_EditorManagerEntity GetEditorManagerByID(int playerId)
bool HasCooldownSet(int playerId)
Is placing allowed for this player?
void SetPropValue(int value)
SCR_CampaignMilitaryBaseComponent GetCampaignMilitaryBaseComponent()
int GetAvailableUsers(out array< int > users)
void SetOnPlayerDeathAvailableUserEvent(int userID)
bool IsBudgetToEvaluate(EEditableEntityBudget blockingBudget)
ScriptInvokerVoid GetOnCooldownLockUpdated()
SCR_CampaignBuildingProviderComponent m_MasterProviderComponent
void RemoveActiveUser(int userID)
void RemoveActiveUsers()
Method called when the provider was destroyed or deleted to remove a provider.
void OnAvailableUserDeath(SCR_CharacterControllerComponent characterControllerComponent, IEntity instigatorEntity, notnull Instigator instigator)
void UpdateCooldownTimer()
Periodically called method to evaluate a current status of the cooldown.
SCR_MilitaryBaseComponent GetMilitaryBaseComponent()
void SetOnPlayerDeathActiveUserEvent(int userID)
void SetOnProviderFactionChangedEvent()
Insert a method called when the provider faction is changed, e.g a base is taken by an enemy.
void AddAIValue(int value)
bool IsEntityFactionSame(notnull IEntity ent1, notnull IEntity ent2)
ref array< ref SCR_CampaignBuildingBudgetToEvaluateData > m_aBudgetsToEvaluate
void OnAIRemoved(IEntity ent)
An event called when AI spawned by this provider is killed or deleted.
ref array< int > m_aAvailableUsersIDs
void SetOnPlayerConsciousnessChanged()
Set even when player consciousness changed.
bool ContainActiveUsers(int playerId)
int GetBudgetTypesToEvaluate(notnull out array< ref EEditableEntityBudget > budgets)
Returns all budget types to evaluate with this provider.
void PlayerTeleported(SCR_EditableCharacterComponent character, bool isLongFade, SCR_EPlayerTeleportedReason teleportReason)
SCR_ResourceComponent GetResourceComponent()
Caches and returns the resource component.
ref array< EEditableEntityLabel > m_aAvailableTraits
ref ScriptInvokerVoid m_OnCooldownLockUpdated
float GetCooldownValue(int playerId)
Return current value of the cooldown time for a given player.
void EntitySpawnedByProvider(int prefabID, SCR_EditableEntityComponent editableEntity)
Event rised when the entity is spawned by this provider.
ref array< SCR_CampaignBuildingBudgetToEvaluateData > m_aShownBudget
SCR_CampaignBuildingNetworkComponent GetNetworkManager()
ref array< int > m_aActiveUsersIDs
void RemoveEvents(IEntity ent)
remove all methods invoked to entity and related to it's dead or delete.
void SetAIValue(int value)
void RemoveAvailableUser(int userID)
array< EEditableEntityLabel > GetAvailableTraits()
int m_iCurrentAIValue
Current AI Value represents, how many AI is currently spawned with this provider. The max number is l...
void OnActiveUserDeath(SCR_CharacterControllerComponent characterControllerComponent, IEntity instigatorEntity, notnull Instigator instigator)
int CalculateCooldownTime(int playerId, int cooldownTime)
Checks the budget setting and calculate final cooldown time based on it.
bool ContainAvailableUsers(int playerId)
const int PROVIDER_SPEED_TO_REMOVE_BUILDING_SQ
int GetPlayerIdFromCharacterController(SCR_CharacterControllerComponent characterControllerComponent)
void AddPropValue(int value)
void OnBaseOwnerChanged(FactionAffiliationComponent owner, Faction previousFaction, Faction newFaction)
ref array< ref Tuple2< int, WorldTimestamp > > m_aPlacingCooldown
SCR_EditorManagerEntity GetEditorManager()
int GetActiveUsers(out notnull array< int > users)
SCR_ECharacterRank GetAccessRank()
int GetMaxBudgetValueFromMasterIfNeeded(EEditableEntityBudget budget)
Return max value of the given budget if this budget is added to be evaluated with this provider and h...
void AddNewActiveUser(int userID)
int GetMaxBudgetValue(EEditableEntityBudget budget)
Return max value of the given budget if this budget is added to be evaluated with this provider and h...
void AddNewAvailableUser(int userID)
int m_iCurrentPropValue
Current props Value represents, how many entities with set prop budget can be spawned with this provi...
SCR_CampaignBuildingBudgetToEvaluateData GetBudgetData(EEditableEntityBudget budget)
Get data of given budget.
void SCR_CampaignSuppliesComponent(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.
EDamageType type
void SCR_EditorManagerEntity(IEntitySource src, IEntity parent)
Get all prefabs that have the spawner data
Get all prefabs that have the spawner the given labels and are valid in the editor mode param catalogType Type to catalog to get prefabs from param editorMode Editor mode to get valid entries from param faction Faction(Optional)
Faction GetParent()
void SCR_FactionManager(IEntitySource src, IEntity parent)
void SCR_GameModeCampaign(IEntitySource src, IEntity parent)
int GetBases(out array< SCR_MilitaryBaseComponent > bases)
EResourceGeneratorID
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
ScriptInvokerBase< ScriptInvokerVoidMethod > ScriptInvokerVoid
SCR_ResourceComponent m_ResourceComponent
enum EVehicleType IEntity
proto external Managed FindComponent(typename typeName)
proto external Physics GetPhysics()
proto external BaseWorld GetWorld()
proto external IEntity GetParent()
Main replication API.
Definition Replication.c:14
bool IsResourceTypeEnabled(EResourceType resourceType=EResourceType.SUPPLIES)
override int CooldownTimeModifier(int playerId, int originalCooldown)
Modify the cooldown time based on the player rank.
OnPlayerDeathWithParamInvoker GetOnPlayerDeathWithParam()
ref OnLifeStateChangedInvoker m_OnLifeStateChanged
Core component to manage SCR_EditorManagerEntity.
SCR_EditorManagerEntity GetEditorManager()
static int GetLocalPlayerId()
Returns either a valid ID of local player or 0.
static IEntity GetLocalControlledEntity()
Definition Types.c:486
enum EPhysicsLayerPresets Vehicle
Definition gameLib.c:24
IEntity GetOwner()
Owner entity of the fuel tank.
override void EOnInit(IEntity owner)
ECharacterLifeState
SCR_FieldOfViewSettings Attribute
EEditorMode
Editor mode that defines overall functionality.
Definition EEditorMode.c:6
EntityEvent
Various entity events.
Definition EntityEvent.c:14
proto external PlayerController GetPlayerController()
T2 param2
Definition tuple.c:92
Tuple param1