Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_EditableEntityComponent.c
Go to the documentation of this file.
1 
8 
14 {
15  [Attribute("1", UIWidgets.ComboBox, category: "Editable Entity", desc: "Decide whether the entity should be registered automatically to the list of editable entities.", enums: ParamEnumArray.FromEnum(EEditableEntityRegister))]
16  protected EEditableEntityRegister m_bAutoRegister;
17 
18  [Attribute("", UIWidgets.Auto, category: "Visualization", desc: "Icon offset (m) from entity's origin.")]
19  protected vector m_vIconPos;
20 
21  [RplProp()]
22  protected bool m_bEnabledVisibilityReplication;
23 
24  [RplProp(onRplName: "OnRplVisibilityChanged", condition: RplCondition.Custom, customConditionName: "CanReplicateVisibility"), Attribute("1", category: "Visualization", desc: "Set entity's visibility setting. Apart from this custom value, visibility of an entitymay be influenced by other factors like distance to the camera or active layer.")]
25  protected bool m_bVisible;
26 
27  [Attribute(category: "Visualization", desc: "Mark entity as static. When static, entity's position is not calculated each frame. Instead, cached position is used.")]
28  protected bool m_bStatic;
29 
30  [Attribute("0", category: "Visualization", desc: "Max distance in which the entity is drawn.\nWhen 0 or below, default for given type is used.")]
31  protected float m_fMaxDrawDistance;
32 
33  [Attribute("1", UIWidgets.Flags, category: "Editable Entity", desc: "For editor users to edit or even see the entity, at least one of their editor keys must match entity's keys.\nFOr example, if the entity has KEY_1 and KEY_2, while the editor has KEY_2 and KEY_8, the entity will be available, since both have KEY_2.", enums: ParamEnumArray.FromEnum(EEditableEntityAccessKey))]
34  protected EEditableEntityAccessKey m_AccessKey;
35 
36  [Attribute("", UIWidgets.Flags, category: "Editable Entity", desc: "Set unique flags.", enums: ParamEnumArray.FromEnum(EEditableEntityFlag))]
37  protected EEditableEntityFlag m_Flags;
38 
39  protected SCR_EditableEntityComponent m_ParentEntity;
40  protected GenericEntity m_Owner;
41  protected EEditableEntityState m_EntityState;
42  protected SCR_UIInfo m_UIInfoInstance;
43  protected ref set<SCR_EditableEntityComponent> m_Entities;
44  protected vector m_vStaticPos;
45  protected int m_iIconBoneIndex = -1;
46  protected ref ScriptInvokerEntity m_OnDeleted;
47 
48  //------------------------------------------------------------------------------------------------
52  string GetDisplayName()
53  {
54  string displayName;
55 
56  //--- Get GUI name
57  SCR_UIInfo info = GetInfo();
58  if (info)
59  displayName = info.GetName();
60 
61  if (!displayName.IsEmpty() || !m_Owner)
62  return displayName;
63 
64  //--- Get entity name
65  displayName = m_Owner.GetName();
66  if (!displayName.IsEmpty())
67  return "[" + displayName + "]";
68 
69  //--- Get class name
70  return "{" + m_Owner.Type().ToString() + "}";
71  }
72 
73  //------------------------------------------------------------------------------------------------
77  ResourceName GetPrefab(bool shorten = false)
78  {
79  if (!m_Owner)
80  return ResourceName.Empty;
81 
82  EntityPrefabData prefabData = m_Owner.GetPrefabData();
83  if (!prefabData)
84  return ResourceName.Empty;
85 
86  ResourceName prefab = prefabData.GetPrefabName();
87  if (!prefab)
88  prefab = SCR_BaseContainerTools.GetPrefabResourceName(prefabData.GetPrefab()); //--- Modified instance, find prefab in ancestors
89 
90  if (shorten && prefab)
91  {
92  "{"; // fix indent
93  int guidIndex = prefab.LastIndexOf("}");
94  if (guidIndex >= 0)
95  prefab = prefab.Substring(0, guidIndex + 1);
96  }
97 
98  return prefab;
99  }
100 
101  //------------------------------------------------------------------------------------------------
105  SCR_EditableEntityComponentClass GetEditableEntityData(IEntity owner = null)
106  {
107  if (owner)
108  return SCR_EditableEntityComponentClass.Cast(GetComponentData(owner));
109  else if (m_Owner)
110  return SCR_EditableEntityComponentClass.Cast(GetComponentData(m_Owner));
111  else
112  return null;
113  }
114 
115  //------------------------------------------------------------------------------------------------
122  EEditableEntityType GetEntityType(IEntity owner = null)
123  {
124  SCR_EditableEntityComponentClass prefabData = GetEditableEntityData(owner);
125  if (prefabData)
126  return prefabData.GetEntityType();
127  else
128  return EEditableEntityType.GENERIC;
129  }
130 
131  //------------------------------------------------------------------------------------------------
134  SCR_EditableEntityInteraction GetEntityInteraction(IEntity owner = null)
135  {
136  SCR_EditableEntityComponentClass prefabData = GetEditableEntityData(owner);
137  if (prefabData)
138  return prefabData.GetEntityInteraction();
139  else
140  return null;
141  }
142 
143  //------------------------------------------------------------------------------------------------
146  SCR_UIInfo GetInfo(IEntity owner = null)
147  {
148  //--- From instance
149  if (m_UIInfoInstance)
150  return m_UIInfoInstance;
151 
152  //--- From prefab
153  SCR_EditableEntityComponentClass prefabData = GetEditableEntityData(owner);
154  if (prefabData)
155  return prefabData.GetInfo();
156  else
157  return null;
158  }
159 
160  //------------------------------------------------------------------------------------------------
165  ScriptInvokerEntity GetOnDeleted()
166  {
167  if (!m_OnDeleted)
168  m_OnDeleted = new ScriptInvokerEntity();
169 
170  return m_OnDeleted;
171  }
172 
173  //------------------------------------------------------------------------------------------------
177  void SetInfoInstance(SCR_UIInfo info)
178  {
179  m_UIInfoInstance = info;
180  }
181 
182  //------------------------------------------------------------------------------------------------
186  bool IsReplicated(out RplId replicationID = -1)
187  {
188  //--- Never considered replicated when flagged as LOCAL
189  if (HasEntityFlag(EEditableEntityFlag.LOCAL))
190  return false;
191 
192  replicationID = Replication.FindId(this);
193  if (replicationID == -1)
194  {
195  //Print(string.Format("Replication ID not found for '%1'!", GetDisplayName()), LogLevel.ERROR);
196  return false;
197  }
198  return true;
199  }
200 
201  //------------------------------------------------------------------------------------------------
207  bool Serialize(out SCR_EditableEntityComponent outTarget = null, out int outTargetIndex = -1, out EEditableEntitySaveFlag outSaveFlags = 0)
208  {
209  if (IsDestroyed())
210  outSaveFlags |= EEditableEntitySaveFlag.DESTROYED;
211 
212  //--- Children are spawned by the link component, but they were not spawned yet (e.g., in building mode)
213  if ((m_Flags & EEditableEntityFlag.LINKED_CHILDREN) && !SCR_EditorLinkComponent.IsSpawned(this))
214  outSaveFlags |= EEditableEntitySaveFlag.NOT_SPAWNED;
215 
216  return !(m_Flags & EEditableEntityFlag.LOCAL) && !(m_Flags & EEditableEntityFlag.NON_SERIALIZABLE);
217  }
218 
219  //------------------------------------------------------------------------------------------------
223  void Deserialize(SCR_EditableEntityComponent target, int targetValue)
224  {
225  if (target)
226  SetParentEntity(target);
227  }
228 
229  //------------------------------------------------------------------------------------------------
230  protected bool IsServer()
231  {
232  //--- Do we have server rights (LOCAL entities have always full rights)
233  return Replication.IsServer() || Replication.Loadtime() || HasEntityFlag(EEditableEntityFlag.LOCAL);
234  }
235 
236  //------------------------------------------------------------------------------------------------
237  protected bool CanRpc()
238  {
239  //--- Check if replication is possible (e.g., not when the game is shutting down) or allowed (e.g., not when flagged as LOCAL)
240  return Replication.IsRunning() && !HasEntityFlag(EEditableEntityFlag.LOCAL);
241  }
242 
243  //------------------------------------------------------------------------------------------------
245  GenericEntity GetOwnerScripted()
246  {
247  return m_Owner;
248  }
249 
250  //------------------------------------------------------------------------------------------------
254  bool GetPos(out vector pos)
255  {
256  if (!m_Owner)
257  return false;
258 
259  if (m_bStatic)
260  {
261  //--- Cached position
262  pos = m_vStaticPos;
263  return true;
264  }
265  else if (m_iIconBoneIndex == -1)
266  {
267  //--- Offset position
268  pos = m_Owner.CoordToParent(m_vIconPos);
269  return true;
270  }
271  else
272  {
273  //--- Bone position
274  if (m_Owner.GetAnimation())
275  {
276  vector transform[4];
277  m_Owner.GetAnimation().GetBoneMatrix(m_iIconBoneIndex, transform);
278  pos = m_Owner.CoordToParent(transform[3] + m_vIconPos);
279  }
280  else
281  {
282  pos = m_Owner.CoordToParent(m_vIconPos);
283  }
284  return true;
285  }
286  return false;
287  }
288 
289  //------------------------------------------------------------------------------------------------
292  vector GetIconPos()
293  {
294  return m_vIconPos;
295  }
296 
297  //------------------------------------------------------------------------------------------------
300  bool GetTransform(out vector outTransform[4])
301  {
302  if (!m_Owner)
303  return false;
304 
305  m_Owner.GetTransform(outTransform);
306  return true;
307  }
308 
309  //------------------------------------------------------------------------------------------------
312  bool GetLocalTransform(out vector outTransform[4])
313  {
314  if (!m_Owner)
315  return false;
316 
317  if (m_Owner.GetParent())
318  {
319  //--- Use engine hierarchy
320  m_Owner.GetLocalTransform(outTransform);
321  }
322  else
323  {
324  //--- Calculate relative trandform towards editor hierarchy parent
325  m_Owner.GetTransform(outTransform);
326  if (m_ParentEntity)
327  {
328  vector parentTransform[4];
329  if (m_ParentEntity.GetTransform(parentTransform))
330  Math3D.MatrixInvMultiply4(parentTransform, outTransform, outTransform);
331  }
332  }
333  return true;
334  }
335 
336  //------------------------------------------------------------------------------------------------
339  int GetPlayerID()
340  {
341  return 0;
342  }
343 
344  //------------------------------------------------------------------------------------------------
347  Faction GetFaction()
348  {
349  return null;
350  }
351 
352  //------------------------------------------------------------------------------------------------
356  ScriptInvoker GetOnUIRefresh()
357  {
358  return null;
359  }
360 
361  //------------------------------------------------------------------------------------------------
365  ScriptInvoker GetOnUIReset()
366  {
367  return null;
368  }
369 
370  //------------------------------------------------------------------------------------------------
373  SCR_EditableEntityComponent GetAIGroup()
374  {
375  return null;
376  }
377 
378  //------------------------------------------------------------------------------------------------
381  SCR_EditableEntityComponent GetAIEntity()
382  {
383  return null;
384  }
385 
386  //------------------------------------------------------------------------------------------------
389  SCR_EditableEntityComponent GetVehicle()
390  {
391  return null;
392  }
393 
394  //------------------------------------------------------------------------------------------------
399  // to be overridden
400  int GetCrew(out notnull array<CompartmentAccessComponent> crewCompartmentAccess, bool ignorePlayers = true);
401 
402  //------------------------------------------------------------------------------------------------
405  float GetHealth()
406  {
407  if (!m_Owner)
408  return 0;
409 
411  if (damageManager)
412  return damageManager.GetHealthScaled();
413  else
414  return 1;
415  }
416 
417  //------------------------------------------------------------------------------------------------
419  bool CanDestroy()
420  {
421  DamageManagerComponent damageManager = DamageManagerComponent.Cast(GetOwner().FindComponent(DamageManagerComponent));
422  return damageManager && damageManager.IsDamageHandlingEnabled();
423  }
424 
425  //------------------------------------------------------------------------------------------------
428  bool IsDestroyed()
429  {
430  if (!m_Owner)
431  return true;
432 
434  if (damageManager)
435  return damageManager.GetState() == EDamageState.DESTROYED;
436  else
437  return false;
438  }
439 
440  //------------------------------------------------------------------------------------------------
448  void SetStatic(bool isStatic)
449  {
450  if (isStatic && m_Owner.GetFlags() & EntityFlags.ACTIVE)
451  {
452  Print(string.Format("Cannot mark '%1' as static, it's marked as EntityFlags.ACTIVE!", m_Owner), LogLevel.WARNING);
453  return;
454  }
455 
456  m_bStatic = isStatic;
457  if (m_bStatic)
458  UpdateStaticPos();
459  }
460 
461  //------------------------------------------------------------------------------------------------
464  bool GetStatic()
465  {
466  return m_bStatic;
467  }
468 
469  //------------------------------------------------------------------------------------------------
472  void UpdateStaticPos()
473  {
474  if (!m_bStatic)
475  return;
476 
477  m_bStatic = false; //--- Set to false so GetPos() below returns actual position
478  GetPos(m_vStaticPos);
479  m_bStatic = true;
480  }
481 
482  //------------------------------------------------------------------------------------------------
485  void SetHierarchyAsDirtyInParents()
486  {
487  if (!IsServer()) //--- Server-only flag
488  return;
489 
490  SCR_EditableEntityComponent parent = GetParentEntity();
491  while (parent)
492  {
493  parent.SetHierarchyAsDirty();
494  parent = parent.GetParentEntity();
495  }
496  }
497 
498  //------------------------------------------------------------------------------------------------
501  void SetHierarchyAsDirty()
502  {
503  m_Flags |= EEditableEntityFlag.DIRTY_HIERARCHY;
504  }
505 
506  //------------------------------------------------------------------------------------------------
509  void SetTransformWithChildren(vector transform[4])
510  {
511  if (!m_Owner || !IsServer())
512  return;
513 
514  SCR_EditorPreviewParams params = SCR_EditorPreviewParams.CreateParams(transform, verticalMode: EEditorTransformVertical.TERRAIN);
515  SCR_RefPreviewEntity.SpawnAndApplyReference(this, params);
516  }
517 
518  //------------------------------------------------------------------------------------------------
522  void SetTransform(vector transform[4], bool changedByUser = false)
523  {
524  if (!IsServer() || !m_Owner)
525  return;
526 
527  SCR_ResourceComponent resourceComponent = SCR_ResourceComponent.FindResourceComponent(m_Owner);
528  if (resourceComponent)
529  {
530  SCR_ResourceGrid resourceGrid = GetGame().GetResourceGrid();
531 
532  resourceGrid.IncreaseGridUpdateId();
533 
534  if (resourceComponent.IsDynamic())
535  resourceGrid.UpdateResourceDynamicItem(resourceComponent);
536  else
537  resourceGrid.UpdateResourceStaticItem(resourceComponent);
538  }
539 
540  //Inform Scheduler
541  RplComponent rpl = RplComponent.Cast(m_Owner.FindComponent(RplComponent));
542  vector prevTransform[4];
543 
544  m_Owner.GetWorldTransform(prevTransform);
545 
546  //--- Entities modified by user are always to be serialized.
547  if (changedByUser)
548  SetHierarchyAsDirtyInParents();
549 
550  //--- Not ideal to hard-code speific classes, but we can no longer use BaseGameEntity as it's also used for interactive lights
551  //BaseGameEntity baseGameEntity = BaseGameEntity.Cast(m_Owner);
552  if(!System.IsCLIParam("clientVehicles"))
553  {
554  if (m_Owner.IsInherited(ChimeraCharacter))
555  {
556  //--- Execute on owner, even server doesn't have the authority to do so
557  Rpc(SetTransformOwner, transform);
558  }
559  else if (m_Owner.GetPhysics() && m_Owner.IsInherited(Vehicle))
560  {
561  // TODO: Managed by NwkVehicleMovementComponent if teleportation causes chaotic prediction
562  if (CanRpc()) Rpc(SetTransformOwner, transform);
563  //--- Execute also on server if Vehicle
564  SetTransformOwner(transform);
565  }
566  else
567  {
568  SetTransformBroadcast(transform);
569  if (CanRpc()) Rpc(SetTransformBroadcast, transform);
570  }
571  }
572  else
573  {
574  if (m_Owner.GetPhysics() && (m_Owner.IsInherited(ChimeraCharacter) || m_Owner.IsInherited(Vehicle)))
575  {
576  //--- Execute on owner, even server doesn't have the authority to do so
577  Rpc(SetTransformOwner, transform);
578  }
579  else
580  {
581  SetTransformBroadcast(transform);
582  if (CanRpc()) Rpc(SetTransformBroadcast, transform);
583  }
584  }
585 
586  //Sends out on transform changed on server
588  if (core)
589  {
590  core.Event_OnEntityTransformChangedServer.Invoke(this, prevTransform);
591  }
592 
593  rpl.ForceNodeMovement(prevTransform[3]);
594  }
595 
596  //------------------------------------------------------------------------------------------------
597  [RplRpc(RplChannel.Reliable, RplRcver.Owner)]
598  protected void SetTransformOwner(vector transform[4])
599  {
600  BaseGameEntity baseGameEntity = BaseGameEntity.Cast(m_Owner);
601  if (baseGameEntity)
602  {
603  baseGameEntity.Teleport(transform);
604  //baseGameEntity.Update(); //--- Don't call Update, it would make characters fall through ground!
605 
606  Physics phys = baseGameEntity.GetPhysics();
607  if (phys)
608  {
609  phys.SetVelocity(vector.Zero);
610  phys.SetAngularVelocity(vector.Zero);
611  }
612  }
613  }
614 
615  //------------------------------------------------------------------------------------------------
616  [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
617  protected void SetTransformBroadcast(vector transform[4])
618  {
619  if (!m_Owner)
620  return;
621 
622  float scale = m_Owner.GetScale();
623  m_Owner.SetWorldTransform(transform);
624  m_Owner.SetScale(scale);
625  m_Owner.Update();
626  UpdateStaticPos();
627 
629  if (core)
630  core.Event_OnEntityTransformChanged.Invoke(this);
631  }
632 
633  //------------------------------------------------------------------------------------------------
636  bool Destroy()
637  {
638  if (IsServer())
639  {
640  if (!IsDestroyed() && CanDestroy())
641  {
643  damageManager.SetHealthScaled(0);
644  return true;
645  }
646  }
647  return IsDestroyed();
648  }
649 
650  //------------------------------------------------------------------------------------------------
655  bool Delete(bool changedByUser = false, bool updateNavmesh = true)
656  {
657  if (!IsServer())
658  return false;
659 
660  //--- Skip if the entity is already being deleted
661  if (!m_Owner || m_Owner.IsDeleted())
662  return true;
663 
664  //--- Skip when deleting is disabled
665  if (HasEntityFlag(EEditableEntityFlag.NON_DELETABLE))
666  return false;
667 
668  //--- Update navmesh
669  if (updateNavmesh)
670  {
671  SCR_AIWorld aiWorld = SCR_AIWorld.Cast(GetGame().GetAIWorld());
672  if (aiWorld)
673  {
674  array<ref Tuple2<vector, vector>> areas = {}; // min, max
675  array<bool> redoAreas = {};
676  aiWorld.GetNavmeshRebuildAreas(GetOwner(), areas, redoAreas);
677  GetGame().GetCallqueue().CallLater(aiWorld.RequestNavmeshRebuildAreas, 1000, false, areas, redoAreas); //--- Called *before* the entity is deleted with a delay, ensures the regeneration doesn't accidentaly get anything from the entity prior to full destruction
678  }
679  }
680 
681  //--- Mark parents as dirty
682  if (changedByUser)
683  SetHierarchyAsDirtyInParents();
684 
685  //--- Delete the entity
686  RplComponent.DeleteRplEntity(m_Owner, false);
687 
688  return true;
689  }
690 
691  //------------------------------------------------------------------------------------------------
693  RplId GetOwnerRplId()
694  {
695  RplComponent rpl = GetRplComponent();
696  if (rpl)
697  return rpl.Id();
698  else
699  return RplId.Invalid();
700  }
701 
702  //------------------------------------------------------------------------------------------------
705  float GetMaxDrawDistanceSq()
706  {
707  return m_fMaxDrawDistance;
708  }
709 
710  //------------------------------------------------------------------------------------------------
713  void SetMaxDrawDistance(float maxDrawDistance)
714  {
715  if (maxDrawDistance <= 0)
716  return; //--- ToDo: Load from core?
717 
718  m_fMaxDrawDistance = maxDrawDistance * maxDrawDistance;
719  }
720 
721  //------------------------------------------------------------------------------------------------
727  static SCR_EditableEntityComponent GetEditableEntity(IEntity owner)
728  {
729  if (owner)
730  return SCR_EditableEntityComponent.Cast(owner.FindComponent(SCR_EditableEntityComponent));
731  else
732  return null;
733  }
734 
735  //------------------------------------------------------------------------------------------------
740  bool GetEntityBudgetCost(out notnull array<ref SCR_EntityBudgetValue> outBudgets, IEntity owner = null)
741  {
742  SCR_EditableEntityUIInfo editableEntityUIInfo = SCR_EditableEntityUIInfo.Cast(GetInfo(owner));
743  if (editableEntityUIInfo)
744  editableEntityUIInfo.GetEntityBudgetCost(outBudgets);
745 
746  return !outBudgets.IsEmpty();
747  }
748 
749  //------------------------------------------------------------------------------------------------
754  bool GetEntityChildrenBudgetCost(out notnull array<ref SCR_EntityBudgetValue> outBudgets, IEntity owner = null)
755  {
756  SCR_EditableEntityUIInfo editableEntityUIInfo = SCR_EditableEntityUIInfo.Cast(GetInfo(owner));
757  if (editableEntityUIInfo)
758  {
759  editableEntityUIInfo.GetEntityChildrenBudgetCost(outBudgets);
760  }
761  return !outBudgets.IsEmpty();
762  }
763 
764  //------------------------------------------------------------------------------------------------
767  bool GetEntityAndChildrenBudgetCost(out notnull array<ref SCR_EntityBudgetValue> outBudgets, IEntity owner = null)
768  {
769  SCR_EditableEntityUIInfo editableEntityUIInfo = SCR_EditableEntityUIInfo.Cast(GetInfo(owner));
770  if (editableEntityUIInfo)
771  editableEntityUIInfo.GetEntityAndChildrenBudgetCost(outBudgets);
772 
773  return !outBudgets.IsEmpty();
774  }
775 
776  //------------------------------------------------------------------------------------------------
781  bool CanDuplicate(out notnull set<SCR_EditableEntityComponent> outRecipients)
782  {
783  if (HasEntityFlag(EEditableEntityFlag.NON_INTERACTIVE))
784  return false;
785 
787  if (factionAffiliationComponent)
788  {
789  Faction faction = factionAffiliationComponent.GetAffiliatedFaction();
790  SCR_DelegateFactionManagerComponent delegateFactionManager = SCR_DelegateFactionManagerComponent.GetInstance();
791  if (delegateFactionManager)
792  {
793  SCR_EditableFactionComponent factionDelegate = delegateFactionManager.GetFactionDelegate(faction);
794  if (factionDelegate)
795  outRecipients.Insert(factionDelegate);
796  }
797  }
798  return true;
799  }
800 
802  //--- Parent / child management
804 
809 
810  //------------------------------------------------------------------------------------------------
814  bool CanSetParent(SCR_EditableEntityComponent parentEntity)
815  {
816  SCR_EditableEntityInteraction interaction = GetEntityInteraction();
817  if (!interaction)
818  return false;
819 
820  //--- Assumed defaults. ToDo: Receive from client
822 
823  if (!IsDestroyed())
824  interactionFlags |= EEditableEntityInteractionFlag.ALIVE;
825 
826  if (GetPlayerID() == 0)
827  interactionFlags |= EEditableEntityInteractionFlag.NON_PLAYABLE;
828 
829  return interaction.CanSetParent(parentEntity, interactionFlags);
830  }
831 
832  //------------------------------------------------------------------------------------------------
839  SCR_EditableEntityComponent SetParentEntity(SCR_EditableEntityComponent parentEntity, bool changedByUser = false)
840  {
841  //--- Not on server or not replicated, ignore
842  if (!IsServer()/* || !IsReplicated()*/)
843  return parentEntity;
844 
845  //--- No change, ignore
846  if (parentEntity == m_ParentEntity)
847  return parentEntity;
848 
849  if (parentEntity)
850  {
851  //--- Setting to itself, ignore and notify
852  if (parentEntity == this)
853  {
854  Log("Cannot set parent to itself!", true, LogLevel.WARNING);
855  return parentEntity;
856  }
857 
858  //--- Setting to itself, ignore and notify
859  if (parentEntity.IsChildOf(this))
860  {
861  Log(string.Format("Cannot set parent to its own child %1!", parentEntity), true, LogLevel.WARNING);
862  return parentEntity;
863  }
864  }
865 
866  //--- Check if changing parent is allowed
867  if (!CanSetParent(parentEntity))
868  {
869  //Log(string.Format("Cannot set parent to %1, interaction condition not met!", parentEntity), true, LogLevel.WARNING);
870  return parentEntity; //--- ToDo: Notification for the user
871  }
872 
873  //--- Set and broadcast
874  SCR_EditableEntityComponent parentPrev = m_ParentEntity;
875  SetParentEntityBroadcast(parentEntity, parentPrev, changedByUser);
876  if (CanRpc())
877  Rpc(SetParentEntityBroadcastReceive, Replication.FindId(parentEntity), Replication.FindId(parentPrev), changedByUser);
878 
879  return parentEntity;
880  }
881 
882  //------------------------------------------------------------------------------------------------
885  void RestoreParentEntity()
886  {
887  //--- Not on server or not replicated, ignore
888  if (!IsServer()/* || !IsReplicated()*/)
889  return;
890 
891  SetParentEntityBroadcast(m_ParentEntity, m_ParentEntity);
892  if (CanRpc())
893  {
894  int parentEntityID = Replication.FindId(m_ParentEntity);
895  Rpc(SetParentEntityBroadcastReceive, parentEntityID, parentEntityID, false);
896  }
897  }
898 
899  //------------------------------------------------------------------------------------------------
903  void RemoveParentEntity()
904  {
905  //--- Not on server or not replicated, ignore
906  if (!IsServer()/* || !IsReplicated()*/)
907  return;
908 
909  if (IsRegistered())
910  {
911  OnRegistrationChanged(false);
912  if (CanRpc())
913  Rpc(OnRegistrationChanged, false);
914  }
915  }
916 
917  //------------------------------------------------------------------------------------------------
920  SCR_EditableEntityComponent GetParentEntity()
921  {
922  return m_ParentEntity;
923  }
924 
925  //------------------------------------------------------------------------------------------------
928  void GetParentEntities(out notnull array<SCR_EditableEntityComponent> entities)
929  {
930  entities.Clear();
931  SCR_EditableEntityComponent parent = GetParentEntity();
932  while (parent)
933  {
934  entities.Insert(parent);
935  parent = parent.GetParentEntity();
936  }
937  }
938 
939  //------------------------------------------------------------------------------------------------
943  bool IsChildOf(SCR_EditableEntityComponent entity)
944  {
945  SCR_EditableEntityComponent parent = GetParentEntity();
946  while (parent)
947  {
948  if (parent == entity)
949  return true;
950 
951  parent = parent.GetParentEntity();
952  }
953  return false;
954  }
955 
956  //------------------------------------------------------------------------------------------------
961  set<SCR_EditableEntityComponent> GetChildrenRef()
962  {
963  return m_Entities;
964  }
965 
966  //------------------------------------------------------------------------------------------------
972  void GetChildren(out notnull set<SCR_EditableEntityComponent> entities, bool onlyDirect = false, bool skipIgnored = false)
973  {
974  if (!m_Entities)
975  return;
976 
977  foreach (SCR_EditableEntityComponent entity : m_Entities)
978  {
979  if (!entity || (skipIgnored && entity.HasEntityFlag(EEditableEntityFlag.IGNORE_LAYERS)))
980  continue;
981 
982  entities.Insert(entity);
983  if (!onlyDirect)
984  entity.GetChildren(entities, onlyDirect, skipIgnored);
985  }
986  }
987 
988  //------------------------------------------------------------------------------------------------
993  void GetChildren(out notnull set<SCR_EditableEntityComponent> entities, bool onlyDirect, EEditableEntityAccessKey accessKey)
994  {
995  if (!m_Entities)
996  return;
997 
998  entities.Clear();
999  foreach (SCR_EditableEntityComponent entity : m_Entities)
1000  {
1001  if (!entity)
1002  continue;
1003 
1004  if (entity.HasAccessSelf(accessKey))
1005  {
1006  entities.Insert(entity);
1007  if (!onlyDirect)
1008  entity.GetChildren(entities, onlyDirect, accessKey);
1009  }
1010  }
1011  }
1012 
1013  //------------------------------------------------------------------------------------------------
1017  int GetChildrenCount(bool onlyDirect = false)
1018  {
1019  if (!m_Entities)
1020  return 0;
1021 
1022  if (onlyDirect)
1023  {
1024  return m_Entities.Count();
1025  }
1026  else
1027  {
1028  int count = m_Entities.Count();
1029  foreach (SCR_EditableEntityComponent child : m_Entities)
1030  {
1031  count += child.GetChildrenCount(onlyDirect);
1032  }
1033  return count;
1034  }
1035  }
1036 
1037  //------------------------------------------------------------------------------------------------
1041  SCR_EditableEntityComponent GetChild(int index)
1042  {
1043  if (!m_Entities.IsIndexValid(index))
1044  return null;
1045 
1046  return m_Entities[index];
1047  }
1048 
1049  //------------------------------------------------------------------------------------------------
1052  bool IsLayer()
1053  {
1054  return m_Entities && !m_Entities.IsEmpty();
1055  }
1056 
1057  //------------------------------------------------------------------------------------------------
1062  bool CanEnterLayer(SCR_LayersEditorComponent layersManager = null, bool toExtreme = false)
1063  {
1064  if (!layersManager)
1065  {
1067 
1068  if (!layersManager)
1069  return false;
1070  }
1071 
1072  return this != layersManager.GetCurrentLayer() //--- Entity is not the current layer
1073  && HasEntityFlag(EEditableEntityFlag.LAYER) //--- Entity is layer
1074  && (!toExtreme || GetParentEntity() != layersManager.GetCurrentLayer());
1075  }
1076 
1077  //------------------------------------------------------------------------------------------------
1081  bool IsRegistered()
1082  {
1083  return m_bAutoRegister == -1;
1084  }
1086 
1087  //------------------------------------------------------------------------------------------------
1090  // to be overridden
1091  void ForceVehicleCompartments(notnull array<ECompartmentType> forceVehicleCompartments);
1092 
1093  //------------------------------------------------------------------------------------------------
1094  protected void OnParentEntityChanged(SCR_EditableEntityComponent parentEntity, SCR_EditableEntityComponent parentEntityPrev, bool changedByUser)
1095  {
1096  m_ParentEntity = parentEntity;
1097 
1098  if (parentEntity != parentEntityPrev)
1099  RemoveFromParent(parentEntityPrev, changedByUser);
1100 
1101  AddToParent(parentEntity, changedByUser);
1102 
1104  if (core)
1105  core.Event_OnParentEntityChanged.Invoke(this, parentEntity, parentEntityPrev);
1106  }
1107 
1108  //------------------------------------------------------------------------------------------------
1109  protected void SetParentEntityBroadcast(SCR_EditableEntityComponent parentEntity, SCR_EditableEntityComponent parentEntityPrev, bool changedByUser = false, bool isAutoRegistration = false)
1110  {
1111  //if (!CanSetParent(parentEntity)) //--- Prevents players from being registered. ToDo: Fix
1112  // return;
1113 
1114  //--- Not registered, do it first (when allowed) and exit. This function will be called again from Register()
1115  if (!IsRegistered())
1116  {
1117  //--- Only when auto-registration is set to ALWAYS, not NEVER
1118  if (!isAutoRegistration || m_bAutoRegister <= EEditableEntityRegister.ALWAYS)
1119  {
1120  m_ParentEntity = parentEntity;
1121  OnRegistrationChanged(true);
1122  }
1123  return;
1124  }
1125 
1126  //--- Modify entity's parent when...
1127  if (
1128  //--- ...parent is root and entity is registered
1129  (!parentEntity && IsRegistered())
1130  ||
1131  //--- ...parent is an entity and it has the same registration as this entity (so that registration doesn't change)
1132  (parentEntity && parentEntity.IsRegistered() == IsRegistered())
1133  )
1134  {
1135  OnParentEntityChanged(parentEntity, parentEntityPrev, changedByUser);
1136  }
1137  }
1138 
1139  //------------------------------------------------------------------------------------------------
1140  [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1141  protected void SetParentEntityBroadcastReceive(RplId parentEntityID, RplId parentEntityPrevID, bool changedByUser)
1142  {
1143  SCR_EditableEntityComponent parentEntity = SCR_EditableEntityComponent.Cast(Replication.FindItem(parentEntityID));
1144  SCR_EditableEntityComponent parentEntityPrev = SCR_EditableEntityComponent.Cast(Replication.FindItem(parentEntityPrevID));
1145 
1146  //--- When parent entity was not streamed in yet, register this entity as an orphan that will be fully registered after the parent is initialized
1147  if (
1148  (parentEntityID.IsValid() && !parentEntity) //--- Parent expected, but not found
1149  || (parentEntity && !parentEntity.IsRegistered()) //--- Parent found, but not registered yet (e.g., when Replication order is different)
1150  )
1151  {
1153  core.AddOrphan(parentEntityID, Replication.FindId(this));
1154  }
1155  else
1156  {
1157  SetParentEntityBroadcast(parentEntity, parentEntityPrev, changedByUser);
1158  }
1159  }
1160 
1161  //------------------------------------------------------------------------------------------------
1162  [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1163  protected void OnRegistrationChanged(bool toRegister)
1164  {
1165  set<SCR_EditableEntityComponent> children = new set<SCR_EditableEntityComponent>();
1166  GetChildren(children);
1167 
1168  if (toRegister)
1169  {
1170  Register();
1171  foreach (SCR_EditableEntityComponent child : children)
1172  {
1173  child.Register();
1174  }
1175  }
1176  else
1177  {
1178  Unregister();
1179  foreach (SCR_EditableEntityComponent child : children)
1180  {
1181  child.Unregister();
1182  }
1183  }
1184  }
1185 
1186  //------------------------------------------------------------------------------------------------
1187  protected EEditableEntityRegister GetAutoRegister()
1188  {
1189  return m_bAutoRegister;
1190  }
1191 
1192  //------------------------------------------------------------------------------------------------
1193  protected void Register()
1194  {
1195  if (GetGame().GetWorld() != m_Owner.GetWorld())
1196  return;
1197 
1198  if (IsRegistered())
1199  return;
1200 
1201  m_bAutoRegister = -1; //--- Mark as registered locally
1203  if (core)
1204  core.RegisterEntity(this);
1205 
1206  SetParentEntityBroadcast(m_ParentEntity, m_ParentEntity);
1207 
1208  //--- Restore orphaned entites belonging to this parent
1209  array<SCR_EditableEntityComponent> orphans = {};
1210  for (int i = 0, count = core.RemoveOrphans(Replication.FindId(this), orphans); i < count; i++)
1211  {
1212  orphans[i].SetParentEntityBroadcast(this, orphans[i].GetParentEntity());
1213  Print(string.Format("Editor parent %1 restored for orphan %2", this, orphans[i]), LogLevel.VERBOSE);
1214  }
1215  }
1216 
1217  //------------------------------------------------------------------------------------------------
1218  protected void Unregister(IEntity owner = null)
1219  {
1220  if (!IsRegistered())
1221  return;
1222 
1223  m_bAutoRegister = EEditableEntityRegister.ALWAYS; //--- Mark as unregistered locally
1224 
1226  if (core)
1227  core.UnRegisterEntity(this, owner);
1228  }
1229 
1230  //------------------------------------------------------------------------------------------------
1232  // to be overridden
1233  void OnCreatedServer(notnull SCR_PlacingEditorComponent placedEditorComponent);
1234 
1235  //------------------------------------------------------------------------------------------------
1236  protected void AddToParent(SCR_EditableEntityComponent parentEntity, bool changedByUser)
1237  {
1238  if (parentEntity)
1239  {
1240  parentEntity.AddChild(this);
1241 
1242  //--- Mark a dirty
1243  if (changedByUser)
1244  SetHierarchyAsDirtyInParents();
1245  }
1246  else
1247  {
1249  if (core)
1250  core.AddToRoot(this);
1251  }
1252  }
1253 
1254  //------------------------------------------------------------------------------------------------
1255  protected void RemoveFromParent(SCR_EditableEntityComponent parentEntity, bool changedByUser)
1256  {
1257  if (parentEntity)
1258  {
1259  //--- Mark a dirty
1260  if (changedByUser)
1261  SetHierarchyAsDirtyInParents();
1262 
1263  parentEntity.RemoveChild(this);
1264  }
1265  else
1266  {
1268  if (core)
1269  core.RemoveFromRoot(this);
1270  }
1271  }
1272 
1273  //------------------------------------------------------------------------------------------------
1274  protected void AddChild(SCR_EditableEntityComponent entity)
1275  {
1276  if (entity.GetParentEntity() != this)
1277  return;
1278 
1279  //--- Add to editor hierarchy
1280  if (!m_Entities)
1281  m_Entities = new set<SCR_EditableEntityComponent>();
1282  m_Entities.Insert(entity);
1283 
1284  //--- Add to game hierarchy as well
1285  if (entity.HasEntityFlag(EEditableEntityFlag.GAME_HIERARCHY))
1286  UpdateGameHierarchy(m_Owner, entity.GetOwner(), true);
1287 
1288  entity.SetEntityFlag(EEditableEntityFlag.VIRTUAL, true);
1289 
1290  OnChildEntityChanged(entity, true);
1291  }
1292 
1293  //------------------------------------------------------------------------------------------------
1294  protected void RemoveChild(SCR_EditableEntityComponent entity)
1295  {
1296  if (entity.GetParentEntity() == this || !m_Entities)
1297  return;
1298 
1299  //--- Not a child of this entity, ignore
1300  int index = m_Entities.Find(entity);
1301  if (index == -1)
1302  return;
1303 
1304  //--- Remove from editor hierarchy
1305  m_Entities.Remove(index);
1306  if (m_Entities.IsEmpty())
1307  m_Entities = null;
1308 
1309  //--- Remove from game hierarchy
1310  if (entity.HasEntityFlag(EEditableEntityFlag.GAME_HIERARCHY))
1311  UpdateGameHierarchy(m_Owner, entity.m_Owner, false); //--- Don't use entity.GetOwner(), would cause a crash when closing the game
1312 
1313  OnChildEntityChanged(entity, false);
1314  }
1315 
1316  //------------------------------------------------------------------------------------------------
1317  protected void UpdateGameHierarchy(IEntity parent, IEntity child, bool toAdd)
1318  {
1319  if (!parent || !child)
1320  return;
1321 
1322  if (parent && parent.IsDeleted())
1323  return;
1324  if (child && child.IsDeleted())
1325  return;
1326 
1327  //--- Modify the hierarchy (on clients as well; ToDo: Rely on AutoHierarchy in RplComponent)
1328  if (toAdd)
1329  {
1330  parent.AddChild(child, -1, EAddChildFlags.AUTO_TRANSFORM | EAddChildFlags.RECALC_LOCAL_TRANSFORM);
1331  }
1332  else
1333  {
1334  vector transform[4];
1335  child.GetWorldTransform(transform);
1336  parent.RemoveChild(child);
1337  child.SetWorldTransform(transform);
1338  }
1339  }
1340 
1341  //------------------------------------------------------------------------------------------------
1342  //--- To be overloaded by inherited classes
1343  protected void OnChildEntityChanged(SCR_EditableEntityComponent child, bool isAdded);
1344 
1346  //--- State (local)
1348 
1349  //------------------------------------------------------------------------------------------------
1353  bool HasEntityState(EEditableEntityState state)
1354  {
1355  return (m_EntityState & state) == state;
1356  }
1357 
1358  //------------------------------------------------------------------------------------------------
1361  EEditableEntityState GetEntityStates()
1362  {
1363  return m_EntityState;
1364  }
1365 
1366  //------------------------------------------------------------------------------------------------
1372  void SetEntityState(EEditableEntityState state, bool toSet)
1373  {
1374  if (toSet)
1375  {
1376  if (m_EntityState & state)
1377  return;
1378 
1379  m_EntityState = m_EntityState | state;
1380  }
1381  else
1382  {
1383  if (!(m_EntityState & state))
1384  return;
1385 
1386  m_EntityState = m_EntityState &~ state;
1387  }
1388 
1389  if (HasEntityFlag(EEditableEntityFlag.VIRTUAL))
1390  SetEntityStateInChildren(m_Owner, state, toSet);
1391 
1392  //--- Global event call disabled, takes too much performance when editor mode is being initialized
1393  //SCR_EditableEntityCore core = SCR_EditableEntityCore.Cast(SCR_EditableEntityCore.GetInstance(SCR_EditableEntityCore));
1394  //if (core) core.Event_OnEntityStateChanged.Invoke(this, state, toSet);
1395  }
1396 
1397  //------------------------------------------------------------------------------------------------
1399  void ResetEntityStates()
1400  {
1401  EEditableEntityState state = m_EntityState;
1402  m_EntityState = 0;
1403 
1404  if (HasEntityFlag(EEditableEntityFlag.VIRTUAL))
1405  SetEntityStateInChildren(m_Owner, state, false);
1406 
1407 // //--- Deconstruct state flags and call handlers on each individual flag
1408 // SCR_EditableEntityCore core = SCR_EditableEntityCore.Cast(SCR_EditableEntityCore.GetInstance(SCR_EditableEntityCore));
1409 // int state = 1;
1410 // while (m_EntityState > 0 && state < int.MAX)
1411 // {
1412 // if (m_EntityState & state)
1413 // {
1414 // SetEntityStateInChildren(m_Owner, state, false);
1415 // //if (core) core.Event_OnEntityStateChanged.Invoke(this, state, false);
1416 // m_EntityState -= state;
1417 // }
1418 // state *= 2;
1419 // }
1420  }
1421 
1422  //------------------------------------------------------------------------------------------------
1426  bool HasEntityFlag(EEditableEntityFlag flag)
1427  {
1428  return (m_Flags & flag) == flag;
1429  }
1430 
1431  //------------------------------------------------------------------------------------------------
1434  EEditableEntityFlag GetEntityFlags()
1435  {
1436  return m_Flags;
1437  }
1438 
1439  //------------------------------------------------------------------------------------------------
1443  void SetEntityFlag(EEditableEntityFlag flag, bool toSet)
1444  {
1445  if (toSet)
1446  {
1447  if (m_Flags & flag)
1448  return;
1449 
1450  m_Flags = m_Flags | flag;
1451  }
1452  else
1453  {
1454  if (!(m_Flags & flag))
1455  return;
1456 
1457  m_Flags = m_Flags &~ flag;
1458  }
1459  }
1460 
1461  //------------------------------------------------------------------------------------------------
1464  void CopyEntityFlags(EEditableEntityFlag flags)
1465  {
1466  m_Flags = flags;
1467  }
1468 
1469  //------------------------------------------------------------------------------------------------
1470  protected void SetEntityStateInChildren(IEntity owner, EEditableEntityState state, bool toSet, out array<Managed> components = null)
1471  {
1472  if (!owner)
1473  return;
1474 
1475  //~ Get editable entity
1476  SCR_EditableEntityComponent editableEntity = SCR_EditableEntityComponent.Cast(owner.FindComponent(SCR_EditableEntityComponent));
1477 
1478  //~ Stop on editable entity that is not owner and does not have the VIRTUAL flag
1479  if (owner != m_Owner && editableEntity && !SCR_Enum.HasFlag(editableEntity.GetEntityFlags(), EEditableEntityFlag.VIRTUAL))
1480  return;
1481 
1482  //--- Call event on all SCR_EditableEntityBaseChildComponent on this entity
1483  if (!components)
1484  components = {};
1485 
1486  int componentsCount = owner.FindComponents(SCR_EditableEntityBaseChildComponent, components);
1487  for (int i = 0; i < componentsCount; i++)
1488  {
1490  if (component && component.CanApply(state))
1491  component.EOnStateChanged(GetEntityStates(), state, toSet);
1492  }
1493 
1494  //--- Go deeper
1495  IEntity child = owner.GetChildren();
1496  while (child)
1497  {
1498  SetEntityStateInChildren(child, state, toSet, components);
1499  child = child.GetSibling();
1500  }
1501  }
1502 
1504  //--- Visibility (local)
1506 
1507  //------------------------------------------------------------------------------------------------
1508  protected void OnVisibilityChanged()
1509  {
1511  if (core)
1512  core.Event_OnEntityVisibilityChanged.Invoke(this);
1513  }
1514 
1519 
1520  //------------------------------------------------------------------------------------------------
1524  void SetVisible(bool show)
1525  {
1526  m_bVisible = show;
1527  OnVisibilityChanged();
1528 
1529  RplComponent rpl = GetRplComponent();
1530  if (rpl && !rpl.IsProxy())
1531  Replication.BumpMe();
1532  }
1533 
1534  //------------------------------------------------------------------------------------------------
1537  void EnableVisibilityReplication(bool enable)
1538  {
1539  RplComponent rpl = GetRplComponent();
1540  if (!rpl || rpl.IsProxy())
1541  return;
1542 
1543  m_bEnabledVisibilityReplication = enable;
1544  Replication.BumpMe();
1545  }
1546 
1547  //------------------------------------------------------------------------------------------------
1549  bool CanReplicateVisibility()
1550  {
1551  return m_bEnabledVisibilityReplication;
1552  }
1553 
1554  //------------------------------------------------------------------------------------------------
1555  void OnRplVisibilityChanged()
1556  {
1557  SetVisible(m_bVisible);
1558  }
1559 
1560  //------------------------------------------------------------------------------------------------
1563  bool GetVisibleSelf()
1564  {
1565  //return HasEntityState(EEditableEntityState.VISIBLE);
1566  return m_bVisible;
1567  }
1568 
1569  //------------------------------------------------------------------------------------------------
1572  bool GetVisibleInHierarchy()
1573  {
1574  if (m_ParentEntity)
1575  return m_ParentEntity.GetVisibleInHierarchy();
1576  else
1577  return GetVisibleSelf();
1578  }
1580 
1582  //--- Access key
1584 
1585  //------------------------------------------------------------------------------------------------
1586  [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1587  protected void OnAccessKeyChanged(EEditableEntityAccessKey accessKey)
1588  {
1589  m_AccessKey = accessKey;
1590 
1592  if (!core)
1593  return;
1594 
1595  core.Event_OnEntityAccessKeyChanged.Invoke(this);
1596 
1597  //--- Execute handler also on all children
1598  SCR_AccessKeysEditorComponent accessKeysComponent = SCR_AccessKeysEditorComponent.Cast(SCR_AccessKeysEditorComponent.GetInstance(SCR_AccessKeysEditorComponent));
1599  EEditableEntityAccessKey editorAccessKey = -1;
1600  if (accessKeysComponent)
1601  editorAccessKey = accessKeysComponent.GetAccessKey();
1602 
1603  set<SCR_EditableEntityComponent> children = new set<SCR_EditableEntityComponent>;
1604  GetChildren(children, false, editorAccessKey);
1605  foreach (SCR_EditableEntityComponent child : children)
1606  {
1607  core.Event_OnEntityAccessKeyChanged.Invoke(child);
1608  }
1609  }
1610 
1611  //------------------------------------------------------------------------------------------------
1619 
1623  void AddAccessKey(EEditableEntityAccessKey accessKey)
1624  {
1625  if (!IsServer()/* || !IsReplicated()*/ || HasAccessSelf(accessKey))
1626  return;
1627 
1628  m_AccessKey = m_AccessKey | accessKey;
1629  OnAccessKeyChanged(m_AccessKey);
1630  if (CanRpc())
1631  Rpc(OnAccessKeyChanged, m_AccessKey);
1632  }
1633 
1634  //------------------------------------------------------------------------------------------------
1638  void RemoveAccessKey(EEditableEntityAccessKey accessKey)
1639  {
1640  if (!IsServer()/* || !IsReplicated()*/ || !HasAccessSelf(accessKey))
1641  return;
1642  m_AccessKey = m_AccessKey &~ accessKey;
1643  OnAccessKeyChanged(m_AccessKey);
1644  if (CanRpc())
1645  Rpc(OnAccessKeyChanged, m_AccessKey);
1646  }
1647 
1648  //------------------------------------------------------------------------------------------------
1651  void ClearAccessKeys()
1652  {
1653  if (!IsServer()/* || !IsReplicated()*/)
1654  return;
1655 
1656  m_AccessKey = 0;
1657  OnAccessKeyChanged(m_AccessKey);
1658  if (CanRpc())
1659  Rpc(OnAccessKeyChanged, m_AccessKey);
1660  }
1661 
1662  //------------------------------------------------------------------------------------------------
1665  EEditableEntityAccessKey GetAccessKey()
1666  {
1667  return m_AccessKey;
1668  }
1669 
1670  //------------------------------------------------------------------------------------------------
1674  bool HasAccessSelf(EEditableEntityAccessKey accessKey)
1675  {
1676  return m_AccessKey & accessKey;// || accessKey == int.MAX; //--- Enable this to let admin see also entities without any key
1677  }
1678 
1679  //------------------------------------------------------------------------------------------------
1683  bool HasAccessInHierarchy(EEditableEntityAccessKey accessKey)
1684  {
1685  if (m_ParentEntity)
1686  return m_ParentEntity.HasAccessInHierarchy(accessKey);
1687  else
1688  return HasAccessSelf(accessKey);
1689  }
1690 
1691  //------------------------------------------------------------------------------------------------
1694  bool HasAccessSelf()
1695  {
1696  SCR_AccessKeysEditorComponent accessKeysComponent = SCR_AccessKeysEditorComponent.Cast(SCR_AccessKeysEditorComponent.GetInstance(SCR_AccessKeysEditorComponent));
1697  if (!accessKeysComponent)
1698  return true;
1699 
1700  return HasAccessSelf(accessKeysComponent.GetAccessKey());
1701  }
1702 
1703  //------------------------------------------------------------------------------------------------
1707  bool HasAccessInHierarchy()
1708  {
1709  SCR_AccessKeysEditorComponent accessKeysComponent = SCR_AccessKeysEditorComponent.Cast(SCR_AccessKeysEditorComponent.GetInstance(SCR_AccessKeysEditorComponent));
1710  if (!accessKeysComponent)
1711  return true;
1712 
1713  return HasAccessInHierarchy(accessKeysComponent.GetAccessKey());
1714  }
1716 
1718  //--- Support Functions
1720 
1721  //------------------------------------------------------------------------------------------------
1722  //--- Will send event for GUI to refresh instantly, to be called from inherited classes in case initialization takes a bit longer.
1723  protected void Refresh()
1724  {
1726  if (core)
1727  core.Event_OnEntityRefreshed.Invoke(this);
1728  }
1729 
1730  //------------------------------------------------------------------------------------------------
1731  protected RplComponent GetRplComponent()
1732  {
1733  return RplComponent.Cast(GetOwner().FindComponent(RplComponent));
1734  }
1735 
1736  //------------------------------------------------------------------------------------------------
1737  protected bool ValidateType()
1738  {
1739  switch (GetEntityType())
1740  {
1741  case EEditableEntityType.CHARACTER:
1742  return m_Owner.IsInherited(ChimeraCharacter) || m_Owner.FindComponent(SCR_EditablePlayerDelegateComponent) != null;
1743 
1744  //--- No longer valid, tripods are considered vehicles even when not inheriting from class Vehicle
1745  //case EEditableEntityType.VEHICLE:
1746  // return m_Owner.IsInherited(Vehicle);
1747 
1748  case EEditableEntityType.GROUP:
1749  return m_Owner.IsInherited(AIGroup);
1750 
1751  case EEditableEntityType.WAYPOINT:
1752  return m_Owner.IsInherited(AIWaypoint);
1753 
1754  case EEditableEntityType.COMMENT:
1755  return this.IsInherited(SCR_EditableCommentComponent);
1756 
1757  case EEditableEntityType.ITEM:
1758  return m_Owner.FindComponent(InventoryItemComponent) != null;
1759  }
1760  return true;
1761  }
1762 
1764  //--- Log
1766 
1767  //------------------------------------------------------------------------------------------------
1770  string GetLogText(string prefix = "")
1771  {
1772  string displayName = GetDisplayName();
1773  string prefabName;
1774  EntityPrefabData prefabData = m_Owner.GetPrefabData();
1775  if (prefabData)
1776  prefabName = FilePath.StripPath(prefabData.GetPrefabName());
1777 
1778  string space = " ";
1779  for (int i = 0; i < 50 - prefix.Length() - displayName.Length(); i++)
1780  {
1781  space += " ";
1782  }
1783 
1784  return string.Format("%1%2 | entity: %3, prefab: '%4', pos: %5, flags: %6", displayName, space, m_Owner, prefabName, m_Owner.GetOrigin(), SCR_Enum.FlagsToString(EEditableEntityFlag, m_Flags));
1785  }
1786 
1787  //------------------------------------------------------------------------------------------------
1792  void Log(string prefix = "", bool onlyDirect = false, LogLevel logLevel = LogLevel.DEBUG)
1793  {
1794  if (!m_Owner)
1795  {
1796  Print(string.Format(prefix + " - Error: Null m_Owner in %1", this), LogLevel.WARNING);
1797  return;
1798  }
1799 
1800  if (m_Entities && !m_Entities.IsEmpty())
1801  {
1802  Print(prefix + "+ " + GetLogText(prefix), logLevel);
1803  if (onlyDirect)
1804  return;
1805 
1806  foreach (SCR_EditableEntityComponent entity : m_Entities)
1807  {
1808  if (entity)
1809  entity.Log(prefix + " ");
1810  else
1811  Log(string.Format(prefix + " - Error: Null child in %1!", this), true, LogLevel.WARNING)
1812  }
1813  }
1814  else
1815  {
1816  Print(prefix + "- " + GetLogText(prefix), logLevel);
1817  }
1818  }
1819 
1820  //------------------------------------------------------------------------------------------------
1824  void Log(string prefix, EEditableEntityAccessKey accessKey)
1825  {
1826  if (!m_Owner)
1827  return;
1828 
1829  if (m_Entities && !m_Entities.IsEmpty())
1830  {
1831  Print(prefix + "+ " + GetLogText(prefix), LogLevel.DEBUG);
1832  foreach (SCR_EditableEntityComponent entity : m_Entities)
1833  {
1834  if (entity.HasAccessSelf(m_AccessKey))
1835  entity.Log(prefix + " ", accessKey);
1836  }
1837  }
1838  else
1839  {
1840  Print(prefix + "- " + GetLogText(prefix), LogLevel.DEBUG);
1841  }
1842  }
1843 
1844  //------------------------------------------------------------------------------------------------
1846  void LogAccessKey()
1847  {
1848  string output = "";
1849  typename enumType = EEditableEntityAccessKey;
1850  int enumCount = enumType.GetVariableCount();
1851  for (int i = 0; i < enumCount; i++)
1852  {
1853  int val;
1854  if (enumType.GetVariableType(i) == int && enumType.GetVariableValue(null, i, val))
1855  {
1856  if (HasAccessSelf(val))
1857  {
1858  if (!output.IsEmpty())
1859  output += ", ";
1860 
1861  output += enumType.GetVariableName(i);
1862  }
1863  }
1864  }
1865  Print(string.Format("%1 access key: %2", GetDisplayName(), output), LogLevel.DEBUG);
1866  }
1867 
1869  //--- External events
1871 
1872  //------------------------------------------------------------------------------------------------
1880  SCR_EditableEntityComponent EOnEditorPlace(out SCR_EditableEntityComponent parent, SCR_EditableEntityComponent recipient, EEditorPlacingFlags flags, bool isQueue, int playerID = 0)
1881  {
1882  return this;
1883  }
1884 
1885  //------------------------------------------------------------------------------------------------
1888  void EOnEditorSessionLoad(SCR_EditableEntityComponent parent)
1889  {
1890  SCR_AIWorld aiWorld = SCR_AIWorld.Cast(GetGame().GetAIWorld());
1891  if (aiWorld)
1892  aiWorld.RequestNavmeshRebuildEntity(GetOwnerScripted());
1893  }
1894 
1896  //--- Default functions
1898 
1899  //------------------------------------------------------------------------------------------------
1900  //--- JIP on server
1901  override bool RplSave(ScriptBitWriter writer)
1902  {
1903  writer.Write(m_AccessKey, 32);
1904 
1905  RplId parentID = Replication.FindId(m_ParentEntity);
1906  writer.WriteRplId(parentID);
1907 
1908  return true;
1909  }
1910 
1911  //------------------------------------------------------------------------------------------------
1912  //--- JIP on client
1913  override bool RplLoad(ScriptBitReader reader)
1914  {
1915  reader.Read(m_AccessKey, 32);
1916 
1917  RplId parentID;
1918  reader.ReadRplId(parentID);
1919 
1920  SetParentEntityBroadcastReceive(parentID, parentID, false);
1921 
1922  return true;
1923  }
1924 
1925  //------------------------------------------------------------------------------------------------
1926  override void OnDelete(IEntity owner)
1927  {
1928  //--- Marked as -1 in constructor when edit mode is active
1929  if (m_EntityState == -1)
1930  return;
1931 
1932  if (m_OnDeleted)
1933  m_OnDeleted.Invoke(owner);
1934 
1935  //--- Delete entities in editor hierarchy
1936  if (IsServer() && m_Entities)
1937  {
1938  for (int i = m_Entities.Count() - 1; i >= 0; i--)
1939  {
1941  if (!entity.HasEntityFlag(EEditableEntityFlag.GAME_HIERARCHY))
1942  m_Entities[i].Delete(false);
1943  }
1944  }
1945 
1946  //--- Unregister
1947  SCR_EditableEntityComponent parentEntity = GetParentEntity();
1948  m_ParentEntity = null; //--- Clear the variable, otherise condition in RemoveChild() would ignore this
1949  RemoveFromParent(parentEntity, false);
1950  Unregister(owner);
1951  }
1952 
1953  //------------------------------------------------------------------------------------------------
1954  override void OnPostInit(IEntity owner)
1955  {
1956  if (!m_Owner)
1957  return;
1958 
1959  //--- Determine entity type
1960 #ifdef WORKBENCH
1961  if (!ValidateType())
1962  Log(string.Format("Wrong type %1 used!", typename.EnumToString(EEditableEntityType, GetEntityType())), true, LogLevel.WARNING);
1963 #endif
1964 
1965  //--- Update static pos
1966  SetStatic(m_bStatic);
1967 
1968  //--- Exit in edit mode, can wreck havoc when WB thumbnails of editable entities are loaded while the game is running
1969  if (SCR_Global.IsEditMode(owner))
1970  return;
1971 
1972  //--- Check for presence of RplComponent. Entity cannot be editable without it.
1973  RplComponent rpl = RplComponent.Cast(m_Owner.FindComponent(RplComponent));
1974  if (HasEntityFlag(EEditableEntityFlag.LOCAL))
1975  {
1976  if (rpl)
1977  {
1978  Print(string.Format("Editable entity @\"%1\" is flagged as LOCAL, but contains RplComponent!", GetPrefab()), LogLevel.ERROR);
1979  m_Owner = null;
1980  return;
1981  }
1982  }
1983  else
1984  {
1985  if (!rpl)
1986  {
1987  Print(string.Format("Editable entity @\"%1\" is missing RplComponent! Maybe try regenerating it again.", GetPrefab()), LogLevel.ERROR);
1988  m_Owner = null;
1989  return;
1990  }
1991  }
1992 
1993  //--- Make sure distance value is squared
1994  if (m_fMaxDrawDistance != 0)
1995  m_fMaxDrawDistance *= m_fMaxDrawDistance;
1996 
1997  //--- Register to the system
1998  if (IsServer())
1999  SetParentEntityBroadcast(m_ParentEntity, m_ParentEntity, isAutoRegistration: true);
2000  }
2001 
2002  //------------------------------------------------------------------------------------------------
2003  // constructor
2007  void SCR_EditableEntityComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
2008  {
2009  if (DiagMenu.GetValue(SCR_DebugMenuID.DEBUGUI_EDITOR_ENTITIES_DISABLE))
2010  return;
2011 
2012  m_Owner = GenericEntity.Cast(ent);
2013 
2014  //--- Ignore when not in run-time
2015  if (!GetGame() || SCR_Global.IsEditMode(ent))
2016  {
2017  m_EntityState = -1; //--- Tell destructor and OnDelete to terminate
2018  return;
2019  }
2020 
2021  //--- Get bone index on which the icon will be rendered
2022  SCR_EditableEntityComponentClass prefabData = GetEditableEntityData();
2023  if (prefabData)
2024  {
2025  string boneName = prefabData.GetIconBoneName();
2026  if (!boneName.IsEmpty())
2027  m_iIconBoneIndex = m_Owner.GetAnimation().GetBoneIndex(boneName);
2028  }
2029 
2030  //--- Get parent entity
2031  if (parent)
2032  {
2033  GenericEntity genericParent = GenericEntity.Cast(parent);
2034  SCR_EditableEntityComponent parentEntity;
2035  if (genericParent)
2036  {
2037  parentEntity = SCR_EditableEntityComponent.Cast(genericParent.FindComponent(SCR_EditableEntityComponent));
2038  if (parentEntity)
2039  {
2040  //--- Cannot have worse auto-registration settings than parent (to make sure child entities are registered)
2041  if (m_bAutoRegister != EEditableEntityRegister.NEVER)
2042  m_bAutoRegister = Math.Min(m_bAutoRegister, parentEntity.GetAutoRegister());
2043 
2044  //--- Cannot be marked as registered yet (registered value is -1, see Register())
2045  m_bAutoRegister = Math.Max(m_bAutoRegister, EEditableEntityRegister.ALWAYS);
2046  }
2047  }
2048  m_ParentEntity = parentEntity;
2049  }
2050 
2051  //--- When spawned dynamically, change auto-registration WHEN_SPAWNED to ALWAYS
2052  if (m_bAutoRegister == EEditableEntityRegister.WHEN_SPAWNED && !m_Owner.IsLoaded())
2053  m_bAutoRegister = EEditableEntityRegister.ALWAYS;
2054  }
2055 }
EEditableEntityState
EEditableEntityState
Definition: EEditableEntityState.c:37
SCR_ResourceGrid
void SCR_ResourceGrid()
Definition: SCR_ResourceGrid.c:785
EEditableEntityFlag
EEditableEntityFlag
Unique flags of the entity.
Definition: EEditableEntityFlag.c:5
SCR_EditableEntityCore
Definition: SCR_EditableEntityCore.c:10
SCR_Enum
Definition: SCR_Enum.c:1
ScriptComponent
SCR_SiteSlotEntityClass ScriptComponent
RplProp
SCR_RplTestEntityClass RplProp
Used for handling entity spawning requests for SCR_CatalogEntitySpawnerComponent and inherited classe...
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
SCR_EditableEntityUIInfo
Definition: SCR_EditableEntityUIInfo.c:2
EDamageState
EDamageState
Definition: EDamageState.c:12
desc
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
Definition: SCR_RespawnBriefingComponent.c:17
RplRpc
SCR_AchievementsHandlerClass ScriptComponentClass RplRpc(RplChannel.Reliable, RplRcver.Owner)] void UnlockOnClient(AchievementId achievement)
Definition: SCR_AchievementsHandler.c:11
GenericEntity
SCR_GenericBoxEntityClass GenericEntity
EEditableEntityRegister
EEditableEntityRegister
Definition: EEditableEntityRegister.c:10
SCR_AIWorld
Definition: SCR_AIWorld.c:23
EEditorTransformVertical
EEditorTransformVertical
Vertical transformation mode.
Definition: EEditorTransformVertical.c:5
SCR_BaseEditorComponent
Definition: SCR_BaseEditorComponent.c:119
Attribute
typedef Attribute
Post-process effect of scripted camera.
IsInherited
bool IsInherited(string factionKey)
Definition: SCR_Faction.c:227
EEditableEntityAccessKey
EEditableEntityAccessKey
Definition: EEditableEntityAccessKey.c:8
EEditableEntityType
EEditableEntityType
Defines type of SCR_EditableEntityComponent. Assigned automatically based on IEntity inheritance.
Definition: EEditableEntityType.c:5
ScriptInvokerEntity
ScriptInvokerBase< ScriptInvokerEntityMethod > ScriptInvokerEntity
Definition: SCR_ScriptInvokerHelper.c:92
m_Entities
protected ref SCR_SortedArray< SCR_EditableEntityComponent > m_Entities
Definition: SCR_EntitiesToolbarEditorUIComponent.c:31
EEditorPlacingFlags
EEditorPlacingFlags
Definition: EEditorPlacingFlags.c:1
SCR_EditableEntityBaseChildComponent
void SCR_EditableEntityBaseChildComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
Definition: SCR_EditableEntityBaseChildComponent.c:70
GetOwner
IEntity GetOwner()
Owner entity of the fuel tank.
Definition: SCR_FuelNode.c:128
EEditableEntityInteractionFlag
EEditableEntityInteractionFlag
Details of entity interaction.
Definition: EEditableEntityInteractionFlag.c:5
SCR_UIInfo
Definition: SCR_UIInfo.c:7
SCR_EditableEntityComponent
Definition: SCR_EditableEntityComponent.c:13
InventoryItemComponent
Definition: InventoryItemComponent.c:12
SCR_BaseContainerTools
Definition: SCR_BaseContainerTools.c:3
Faction
Definition: Faction.c:12
index
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
Definition: SCR_DestructionSynchronizationComponent.c:17
SCR_LayersEditorComponent
Definition: SCR_LayersEditorManager.c:11
SCR_Global
Definition: Functions.c:6
EEditableEntitySaveFlag
EEditableEntitySaveFlag
Definition: EEditableEntitySaveFlag.c:9
params
Configs ServerBrowser KickDialogs params
Definition: SCR_NotificationSenderComponent.c:24
SCR_DelegateFactionManagerComponent
Definition: SCR_DelegateFactionManagerComponent.c:15
SCR_FactionAffiliationComponent
Definition: SCR_FactionAffiliationComponent.c:10
SCR_RefPreviewEntity
Definition: SCR_RefPreviewEntity.c:10
SCR_EditableEntityInteraction
Definition: SCR_EditableEntityInteraction.c:2
m_bVisible
protected bool m_bVisible
Definition: SCR_UITaskManagerComponent.c:28
SCR_EditableEntityComponentClass
Definition: SCR_EditableEntityComponentClass.c:2
DamageManagerComponent
Definition: DamageManagerComponent.c:12
SCR_DebugMenuID
SCR_DebugMenuID
This enum contains all IDs for DiagMenu entries added in script.
Definition: DebugMenuID.c:3
SCR_PlacingEditorComponent
Definition: SCR_PlacingEditorComponent.c:118
m_Owner
SCR_AIGroupUtilityComponentClass m_Owner
SCR_EditorPreviewParams
Network packet of variables for entity placing and transformation.
Definition: SCR_EditorPreviewParams.c:4
category
params category
Definition: SCR_VehicleDamageManagerComponent.c:180